aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang14/tools/libclang
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/tools/libclang
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/tools/libclang')
-rw-r--r--contrib/libs/clang14/tools/libclang/ARCMigrate.cpp138
-rw-r--r--contrib/libs/clang14/tools/libclang/BuildSystem.cpp152
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndex.cpp9234
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexCXX.cpp122
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexCodeCompletion.cpp1046
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexDiagnostic.cpp468
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexDiagnostic.h165
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexHigh.cpp534
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexInclusionStack.cpp94
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexUSRs.cpp139
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexer.cpp222
-rw-r--r--contrib/libs/clang14/tools/libclang/CIndexer.h153
-rw-r--r--contrib/libs/clang14/tools/libclang/CLog.h102
-rw-r--r--contrib/libs/clang14/tools/libclang/CXComment.cpp408
-rw-r--r--contrib/libs/clang14/tools/libclang/CXComment.h63
-rw-r--r--contrib/libs/clang14/tools/libclang/CXCompilationDatabase.cpp167
-rw-r--r--contrib/libs/clang14/tools/libclang/CXCursor.cpp1721
-rw-r--r--contrib/libs/clang14/tools/libclang/CXCursor.h293
-rw-r--r--contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.cpp1312
-rw-r--r--contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.h500
-rw-r--r--contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.cpp394
-rw-r--r--contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.h93
-rw-r--r--contrib/libs/clang14/tools/libclang/CXSourceLocation.cpp374
-rw-r--r--contrib/libs/clang14/tools/libclang/CXSourceLocation.h81
-rw-r--r--contrib/libs/clang14/tools/libclang/CXStoredDiagnostic.cpp111
-rw-r--r--contrib/libs/clang14/tools/libclang/CXString.cpp191
-rw-r--r--contrib/libs/clang14/tools/libclang/CXString.h108
-rw-r--r--contrib/libs/clang14/tools/libclang/CXTranslationUnit.h89
-rw-r--r--contrib/libs/clang14/tools/libclang/CXType.cpp1338
-rw-r--r--contrib/libs/clang14/tools/libclang/CXType.h25
-rw-r--r--contrib/libs/clang14/tools/libclang/CursorVisitor.h278
-rw-r--r--contrib/libs/clang14/tools/libclang/FatalErrorHandler.cpp32
-rw-r--r--contrib/libs/clang14/tools/libclang/Index_Internal.h54
-rw-r--r--contrib/libs/clang14/tools/libclang/Indexing.cpp997
-rw-r--r--contrib/libs/clang14/tools/libclang/Rewrite.cpp63
-rw-r--r--contrib/libs/clang14/tools/libclang/dynamic/ya.make3
-rw-r--r--contrib/libs/clang14/tools/libclang/libclang-generic.exports395
-rw-r--r--contrib/libs/clang14/tools/libclang/ya.make87
38 files changed, 21746 insertions, 0 deletions
diff --git a/contrib/libs/clang14/tools/libclang/ARCMigrate.cpp b/contrib/libs/clang14/tools/libclang/ARCMigrate.cpp
new file mode 100644
index 0000000000..da8a7e4b91
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/ARCMigrate.cpp
@@ -0,0 +1,138 @@
+//===- ARCMigrate.cpp - Clang-C ARC Migration Library ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main API hooks in the Clang-C ARC Migration library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-c/Index.h"
+#include "CXString.h"
+#include "clang/ARCMigrate/ARCMT.h"
+#include "clang/Config/config.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace clang;
+using namespace arcmt;
+
+namespace {
+
+struct Remap {
+ std::vector<std::pair<std::string, std::string> > Vec;
+};
+
+} // anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// libClang public APIs.
+//===----------------------------------------------------------------------===//
+
+CXRemapping clang_getRemappings(const char *migrate_dir_path) {
+#if !CLANG_ENABLE_ARCMT
+ llvm::errs() << "error: feature not enabled in this build\n";
+ return nullptr;
+#else
+ bool Logging = ::getenv("LIBCLANG_LOGGING");
+
+ if (!migrate_dir_path) {
+ if (Logging)
+ llvm::errs() << "clang_getRemappings was called with NULL parameter\n";
+ return nullptr;
+ }
+
+ if (!llvm::sys::fs::exists(migrate_dir_path)) {
+ if (Logging) {
+ llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
+ << "\")\n";
+ llvm::errs() << "\"" << migrate_dir_path << "\" does not exist\n";
+ }
+ return nullptr;
+ }
+
+ TextDiagnosticBuffer diagBuffer;
+ std::unique_ptr<Remap> remap(new Remap());
+
+ bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer);
+
+ if (err) {
+ if (Logging) {
+ llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
+ << "\")\n";
+ for (TextDiagnosticBuffer::const_iterator
+ I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
+ llvm::errs() << I->second << '\n';
+ }
+ return nullptr;
+ }
+
+ return remap.release();
+#endif
+}
+
+CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
+ unsigned numFiles) {
+#if !CLANG_ENABLE_ARCMT
+ llvm::errs() << "error: feature not enabled in this build\n";
+ return nullptr;
+#else
+ bool Logging = ::getenv("LIBCLANG_LOGGING");
+
+ std::unique_ptr<Remap> remap(new Remap());
+
+ if (numFiles == 0) {
+ if (Logging)
+ llvm::errs() << "clang_getRemappingsFromFileList was called with "
+ "numFiles=0\n";
+ return remap.release();
+ }
+
+ if (!filePaths) {
+ if (Logging)
+ llvm::errs() << "clang_getRemappingsFromFileList was called with "
+ "NULL filePaths\n";
+ return nullptr;
+ }
+
+ TextDiagnosticBuffer diagBuffer;
+ SmallVector<StringRef, 32> Files(filePaths, filePaths + numFiles);
+
+ bool err = arcmt::getFileRemappingsFromFileList(remap->Vec, Files,
+ &diagBuffer);
+
+ if (err) {
+ if (Logging) {
+ llvm::errs() << "Error by clang_getRemappingsFromFileList\n";
+ for (TextDiagnosticBuffer::const_iterator
+ I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
+ llvm::errs() << I->second << '\n';
+ }
+ return remap.release();
+ }
+
+ return remap.release();
+#endif
+}
+
+unsigned clang_remap_getNumFiles(CXRemapping map) {
+ return static_cast<Remap *>(map)->Vec.size();
+
+}
+
+void clang_remap_getFilenames(CXRemapping map, unsigned index,
+ CXString *original, CXString *transformed) {
+ if (original)
+ *original = cxstring::createDup(
+ static_cast<Remap *>(map)->Vec[index].first);
+ if (transformed)
+ *transformed = cxstring::createDup(
+ static_cast<Remap *>(map)->Vec[index].second);
+}
+
+void clang_remap_dispose(CXRemapping map) {
+ delete static_cast<Remap *>(map);
+}
diff --git a/contrib/libs/clang14/tools/libclang/BuildSystem.cpp b/contrib/libs/clang14/tools/libclang/BuildSystem.cpp
new file mode 100644
index 0000000000..2f638ee870
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/BuildSystem.cpp
@@ -0,0 +1,152 @@
+//===- BuildSystem.cpp - Utilities for use by build systems ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements various utilities for use by build systems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-c/BuildSystem.h"
+#include "CXString.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemAlloc.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace llvm::sys;
+
+unsigned long long clang_getBuildSessionTimestamp(void) {
+ return llvm::sys::toTimeT(std::chrono::system_clock::now());
+}
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::vfs::YAMLVFSWriter,
+ CXVirtualFileOverlay)
+
+CXVirtualFileOverlay clang_VirtualFileOverlay_create(unsigned) {
+ return wrap(new llvm::vfs::YAMLVFSWriter());
+}
+
+enum CXErrorCode
+clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay VFO,
+ const char *virtualPath,
+ const char *realPath) {
+ if (!VFO || !virtualPath || !realPath)
+ return CXError_InvalidArguments;
+ if (!path::is_absolute(virtualPath))
+ return CXError_InvalidArguments;
+ if (!path::is_absolute(realPath))
+ return CXError_InvalidArguments;
+
+ for (path::const_iterator
+ PI = path::begin(virtualPath),
+ PE = path::end(virtualPath); PI != PE; ++PI) {
+ StringRef Comp = *PI;
+ if (Comp == "." || Comp == "..")
+ return CXError_InvalidArguments;
+ }
+
+ unwrap(VFO)->addFileMapping(virtualPath, realPath);
+ return CXError_Success;
+}
+
+enum CXErrorCode
+clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay VFO,
+ int caseSensitive) {
+ if (!VFO)
+ return CXError_InvalidArguments;
+ unwrap(VFO)->setCaseSensitivity(caseSensitive);
+ return CXError_Success;
+}
+
+enum CXErrorCode
+clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay VFO, unsigned,
+ char **out_buffer_ptr,
+ unsigned *out_buffer_size) {
+ if (!VFO || !out_buffer_ptr || !out_buffer_size)
+ return CXError_InvalidArguments;
+
+ llvm::SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ unwrap(VFO)->write(OS);
+
+ StringRef Data = OS.str();
+ *out_buffer_ptr = static_cast<char*>(llvm::safe_malloc(Data.size()));
+ *out_buffer_size = Data.size();
+ memcpy(*out_buffer_ptr, Data.data(), Data.size());
+ return CXError_Success;
+}
+
+void clang_free(void *buffer) {
+ free(buffer);
+}
+
+void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay VFO) {
+ delete unwrap(VFO);
+}
+
+
+struct CXModuleMapDescriptorImpl {
+ std::string ModuleName;
+ std::string UmbrellaHeader;
+};
+
+CXModuleMapDescriptor clang_ModuleMapDescriptor_create(unsigned) {
+ return new CXModuleMapDescriptorImpl();
+}
+
+enum CXErrorCode
+clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor MMD,
+ const char *name) {
+ if (!MMD || !name)
+ return CXError_InvalidArguments;
+
+ MMD->ModuleName = name;
+ return CXError_Success;
+}
+
+enum CXErrorCode
+clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor MMD,
+ const char *name) {
+ if (!MMD || !name)
+ return CXError_InvalidArguments;
+
+ MMD->UmbrellaHeader = name;
+ return CXError_Success;
+}
+
+enum CXErrorCode
+clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor MMD, unsigned,
+ char **out_buffer_ptr,
+ unsigned *out_buffer_size) {
+ if (!MMD || !out_buffer_ptr || !out_buffer_size)
+ return CXError_InvalidArguments;
+
+ llvm::SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "framework module " << MMD->ModuleName << " {\n";
+ OS << " umbrella header \"";
+ OS.write_escaped(MMD->UmbrellaHeader) << "\"\n";
+ OS << '\n';
+ OS << " export *\n";
+ OS << " module * { export * }\n";
+ OS << "}\n";
+
+ StringRef Data = OS.str();
+ *out_buffer_ptr = static_cast<char*>(llvm::safe_malloc(Data.size()));
+ *out_buffer_size = Data.size();
+ memcpy(*out_buffer_ptr, Data.data(), Data.size());
+ return CXError_Success;
+}
+
+void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor MMD) {
+ delete MMD;
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndex.cpp b/contrib/libs/clang14/tools/libclang/CIndex.cpp
new file mode 100644
index 0000000000..53494ecc7a
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndex.cpp
@@ -0,0 +1,9234 @@
+//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main API hooks in the Clang-C Source Indexing
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CLog.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "CXType.h"
+#include "CursorVisitor.h"
+#include "clang-c/FatalErrorHandler.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclObjCCommon.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticCategories.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/Stack.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Index/CommentToXML.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/thread.h"
+#include <mutex>
+
+#if LLVM_ENABLE_THREADS != 0 && defined(__APPLE__)
+#define USE_DARWIN_THREADS
+#endif
+
+#ifdef USE_DARWIN_THREADS
+#include <pthread.h>
+#endif
+
+using namespace clang;
+using namespace clang::cxcursor;
+using namespace clang::cxtu;
+using namespace clang::cxindex;
+
+CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx,
+ std::unique_ptr<ASTUnit> AU) {
+ if (!AU)
+ return nullptr;
+ assert(CIdx);
+ CXTranslationUnit D = new CXTranslationUnitImpl();
+ D->CIdx = CIdx;
+ D->TheASTUnit = AU.release();
+ D->StringPool = new cxstring::CXStringPool();
+ D->Diagnostics = nullptr;
+ D->OverridenCursorsPool = createOverridenCXCursorsPool();
+ D->CommentToXML = nullptr;
+ D->ParsingOptions = 0;
+ D->Arguments = {};
+ return D;
+}
+
+bool cxtu::isASTReadError(ASTUnit *AU) {
+ for (ASTUnit::stored_diag_iterator D = AU->stored_diag_begin(),
+ DEnd = AU->stored_diag_end();
+ D != DEnd; ++D) {
+ if (D->getLevel() >= DiagnosticsEngine::Error &&
+ DiagnosticIDs::getCategoryNumberForDiag(D->getID()) ==
+ diag::DiagCat_AST_Deserialization_Issue)
+ return true;
+ }
+ return false;
+}
+
+cxtu::CXTUOwner::~CXTUOwner() {
+ if (TU)
+ clang_disposeTranslationUnit(TU);
+}
+
+/// Compare two source ranges to determine their relative position in
+/// the translation unit.
+static RangeComparisonResult RangeCompare(SourceManager &SM, SourceRange R1,
+ SourceRange R2) {
+ assert(R1.isValid() && "First range is invalid?");
+ assert(R2.isValid() && "Second range is invalid?");
+ if (R1.getEnd() != R2.getBegin() &&
+ SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
+ return RangeBefore;
+ if (R2.getEnd() != R1.getBegin() &&
+ SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
+ return RangeAfter;
+ return RangeOverlap;
+}
+
+/// Determine if a source location falls within, before, or after a
+/// a given source range.
+static RangeComparisonResult LocationCompare(SourceManager &SM,
+ SourceLocation L, SourceRange R) {
+ assert(R.isValid() && "First range is invalid?");
+ assert(L.isValid() && "Second range is invalid?");
+ if (L == R.getBegin() || L == R.getEnd())
+ return RangeOverlap;
+ if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
+ return RangeBefore;
+ if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
+ return RangeAfter;
+ return RangeOverlap;
+}
+
+/// Translate a Clang source range into a CIndex source range.
+///
+/// Clang internally represents ranges where the end location points to the
+/// start of the token at the end. However, for external clients it is more
+/// useful to have a CXSourceRange be a proper half-open interval. This routine
+/// does the appropriate translation.
+CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const CharSourceRange &R) {
+ // We want the last character in this location, so we will adjust the
+ // location accordingly.
+ SourceLocation EndLoc = R.getEnd();
+ bool IsTokenRange = R.isTokenRange();
+ if (EndLoc.isValid() && EndLoc.isMacroID() &&
+ !SM.isMacroArgExpansion(EndLoc)) {
+ CharSourceRange Expansion = SM.getExpansionRange(EndLoc);
+ EndLoc = Expansion.getEnd();
+ IsTokenRange = Expansion.isTokenRange();
+ }
+ if (IsTokenRange && EndLoc.isValid()) {
+ unsigned Length =
+ Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc), SM, LangOpts);
+ EndLoc = EndLoc.getLocWithOffset(Length);
+ }
+
+ CXSourceRange Result = {
+ {&SM, &LangOpts}, R.getBegin().getRawEncoding(), EndLoc.getRawEncoding()};
+ return Result;
+}
+
+CharSourceRange cxloc::translateCXRangeToCharRange(CXSourceRange R) {
+ return CharSourceRange::getCharRange(
+ SourceLocation::getFromRawEncoding(R.begin_int_data),
+ SourceLocation::getFromRawEncoding(R.end_int_data));
+}
+
+//===----------------------------------------------------------------------===//
+// Cursor visitor.
+//===----------------------------------------------------------------------===//
+
+static SourceRange getRawCursorExtent(CXCursor C);
+static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);
+
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
+ return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
+}
+
+/// Visit the given cursor and, if requested by the visitor,
+/// its children.
+///
+/// \param Cursor the cursor to visit.
+///
+/// \param CheckedRegionOfInterest if true, then the caller already checked
+/// that this cursor is within the region of interest.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
+ if (clang_isInvalid(Cursor.kind))
+ return false;
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ const Decl *D = getCursorDecl(Cursor);
+ if (!D) {
+ assert(0 && "Invalid declaration cursor");
+ return true; // abort.
+ }
+
+ // Ignore implicit declarations, unless it's an objc method because
+ // currently we should report implicit methods for properties when indexing.
+ if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
+ return false;
+ }
+
+ // If we have a range of interest, and this cursor doesn't intersect with it,
+ // we're done.
+ if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
+ SourceRange Range = getRawCursorExtent(Cursor);
+ if (Range.isInvalid() || CompareRegionOfInterest(Range))
+ return false;
+ }
+
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
+
+ case CXChildVisit_Continue:
+ return false;
+
+ case CXChildVisit_Recurse: {
+ bool ret = VisitChildren(Cursor);
+ if (PostChildrenVisitor)
+ if (PostChildrenVisitor(Cursor, ClientData))
+ return true;
+ return ret;
+ }
+ }
+
+ llvm_unreachable("Invalid CXChildVisitResult!");
+}
+
+static bool visitPreprocessedEntitiesInRange(SourceRange R,
+ PreprocessingRecord &PPRec,
+ CursorVisitor &Visitor) {
+ SourceManager &SM = Visitor.getASTUnit()->getSourceManager();
+ FileID FID;
+
+ if (!Visitor.shouldVisitIncludedEntities()) {
+ // If the begin/end of the range lie in the same FileID, do the optimization
+ // where we skip preprocessed entities that do not come from the same
+ // FileID.
+ FID = SM.getFileID(SM.getFileLoc(R.getBegin()));
+ if (FID != SM.getFileID(SM.getFileLoc(R.getEnd())))
+ FID = FileID();
+ }
+
+ const auto &Entities = PPRec.getPreprocessedEntitiesInRange(R);
+ return Visitor.visitPreprocessedEntities(Entities.begin(), Entities.end(),
+ PPRec, FID);
+}
+
+bool CursorVisitor::visitFileRegion() {
+ if (RegionOfInterest.isInvalid())
+ return false;
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ SourceManager &SM = Unit->getSourceManager();
+
+ std::pair<FileID, unsigned> Begin = SM.getDecomposedLoc(
+ SM.getFileLoc(RegionOfInterest.getBegin())),
+ End = SM.getDecomposedLoc(
+ SM.getFileLoc(RegionOfInterest.getEnd()));
+
+ if (End.first != Begin.first) {
+ // If the end does not reside in the same file, try to recover by
+ // picking the end of the file of begin location.
+ End.first = Begin.first;
+ End.second = SM.getFileIDSize(Begin.first);
+ }
+
+ assert(Begin.first == End.first);
+ if (Begin.second > End.second)
+ return false;
+
+ FileID File = Begin.first;
+ unsigned Offset = Begin.second;
+ unsigned Length = End.second - Begin.second;
+
+ if (!VisitDeclsOnly && !VisitPreprocessorLast)
+ if (visitPreprocessedEntitiesInRegion())
+ return true; // visitation break.
+
+ if (visitDeclsFromFileRegion(File, Offset, Length))
+ return true; // visitation break.
+
+ if (!VisitDeclsOnly && VisitPreprocessorLast)
+ return visitPreprocessedEntitiesInRegion();
+
+ return false;
+}
+
+static bool isInLexicalContext(Decl *D, DeclContext *DC) {
+ if (!DC)
+ return false;
+
+ for (DeclContext *DeclDC = D->getLexicalDeclContext(); DeclDC;
+ DeclDC = DeclDC->getLexicalParent()) {
+ if (DeclDC == DC)
+ return true;
+ }
+ return false;
+}
+
+bool CursorVisitor::visitDeclsFromFileRegion(FileID File, unsigned Offset,
+ unsigned Length) {
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ SourceManager &SM = Unit->getSourceManager();
+ SourceRange Range = RegionOfInterest;
+
+ SmallVector<Decl *, 16> Decls;
+ Unit->findFileRegionDecls(File, Offset, Length, Decls);
+
+ // If we didn't find any file level decls for the file, try looking at the
+ // file that it was included from.
+ while (Decls.empty() || Decls.front()->isTopLevelDeclInObjCContainer()) {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SLEntry = SM.getSLocEntry(File, &Invalid);
+ if (Invalid)
+ return false;
+
+ SourceLocation Outer;
+ if (SLEntry.isFile())
+ Outer = SLEntry.getFile().getIncludeLoc();
+ else
+ Outer = SLEntry.getExpansion().getExpansionLocStart();
+ if (Outer.isInvalid())
+ return false;
+
+ std::tie(File, Offset) = SM.getDecomposedExpansionLoc(Outer);
+ Length = 0;
+ Unit->findFileRegionDecls(File, Offset, Length, Decls);
+ }
+
+ assert(!Decls.empty());
+
+ bool VisitedAtLeastOnce = false;
+ DeclContext *CurDC = nullptr;
+ SmallVectorImpl<Decl *>::iterator DIt = Decls.begin();
+ for (SmallVectorImpl<Decl *>::iterator DE = Decls.end(); DIt != DE; ++DIt) {
+ Decl *D = *DIt;
+ if (D->getSourceRange().isInvalid())
+ continue;
+
+ if (isInLexicalContext(D, CurDC))
+ continue;
+
+ CurDC = dyn_cast<DeclContext>(D);
+
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ if (!TD->isFreeStanding())
+ continue;
+
+ RangeComparisonResult CompRes =
+ RangeCompare(SM, D->getSourceRange(), Range);
+ if (CompRes == RangeBefore)
+ continue;
+ if (CompRes == RangeAfter)
+ break;
+
+ assert(CompRes == RangeOverlap);
+ VisitedAtLeastOnce = true;
+
+ if (isa<ObjCContainerDecl>(D)) {
+ FileDI_current = &DIt;
+ FileDE_current = DE;
+ } else {
+ FileDI_current = nullptr;
+ }
+
+ if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))
+ return true; // visitation break.
+ }
+
+ if (VisitedAtLeastOnce)
+ return false;
+
+ // No Decls overlapped with the range. Move up the lexical context until there
+ // is a context that contains the range or we reach the translation unit
+ // level.
+ DeclContext *DC = DIt == Decls.begin()
+ ? (*DIt)->getLexicalDeclContext()
+ : (*(DIt - 1))->getLexicalDeclContext();
+
+ while (DC && !DC->isTranslationUnit()) {
+ Decl *D = cast<Decl>(DC);
+ SourceRange CurDeclRange = D->getSourceRange();
+ if (CurDeclRange.isInvalid())
+ break;
+
+ if (RangeCompare(SM, CurDeclRange, Range) == RangeOverlap) {
+ if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))
+ return true; // visitation break.
+ }
+
+ DC = D->getLexicalDeclContext();
+ }
+
+ return false;
+}
+
+bool CursorVisitor::visitPreprocessedEntitiesInRegion() {
+ if (!AU->getPreprocessor().getPreprocessingRecord())
+ return false;
+
+ PreprocessingRecord &PPRec = *AU->getPreprocessor().getPreprocessingRecord();
+ SourceManager &SM = AU->getSourceManager();
+
+ if (RegionOfInterest.isValid()) {
+ SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest);
+ SourceLocation B = MappedRange.getBegin();
+ SourceLocation E = MappedRange.getEnd();
+
+ if (AU->isInPreambleFileID(B)) {
+ if (SM.isLoadedSourceLocation(E))
+ return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec,
+ *this);
+
+ // Beginning of range lies in the preamble but it also extends beyond
+ // it into the main file. Split the range into 2 parts, one covering
+ // the preamble and another covering the main file. This allows subsequent
+ // calls to visitPreprocessedEntitiesInRange to accept a source range that
+ // lies in the same FileID, allowing it to skip preprocessed entities that
+ // do not come from the same FileID.
+ bool breaked = visitPreprocessedEntitiesInRange(
+ SourceRange(B, AU->getEndOfPreambleFileID()), PPRec, *this);
+ if (breaked)
+ return true;
+ return visitPreprocessedEntitiesInRange(
+ SourceRange(AU->getStartOfMainFileID(), E), PPRec, *this);
+ }
+
+ return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec, *this);
+ }
+
+ bool OnlyLocalDecls = !AU->isMainFileAST() && AU->getOnlyLocalDecls();
+
+ if (OnlyLocalDecls)
+ return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end(),
+ PPRec);
+
+ return visitPreprocessedEntities(PPRec.begin(), PPRec.end(), PPRec);
+}
+
+template <typename InputIterator>
+bool CursorVisitor::visitPreprocessedEntities(InputIterator First,
+ InputIterator Last,
+ PreprocessingRecord &PPRec,
+ FileID FID) {
+ for (; First != Last; ++First) {
+ if (!FID.isInvalid() && !PPRec.isEntityInFileID(First, FID))
+ continue;
+
+ PreprocessedEntity *PPE = *First;
+ if (!PPE)
+ continue;
+
+ if (MacroExpansion *ME = dyn_cast<MacroExpansion>(PPE)) {
+ if (Visit(MakeMacroExpansionCursor(ME, TU)))
+ return true;
+
+ continue;
+ }
+
+ if (MacroDefinitionRecord *MD = dyn_cast<MacroDefinitionRecord>(PPE)) {
+ if (Visit(MakeMacroDefinitionCursor(MD, TU)))
+ return true;
+
+ continue;
+ }
+
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
+ if (Visit(MakeInclusionDirectiveCursor(ID, TU)))
+ return true;
+
+ continue;
+ }
+ }
+
+ return false;
+}
+
+/// Visit the children of the given cursor.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::VisitChildren(CXCursor Cursor) {
+ if (clang_isReference(Cursor.kind) &&
+ Cursor.kind != CXCursor_CXXBaseSpecifier) {
+ // By definition, references have no children.
+ return false;
+ }
+
+ // Set the Parent field to Cursor, then back to its old value once we're
+ // done.
+ SetParentRAII SetParent(Parent, StmtParent, Cursor);
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = const_cast<Decl *>(getCursorDecl(Cursor));
+ if (!D)
+ return false;
+
+ return VisitAttributes(D) || Visit(D);
+ }
+
+ if (clang_isStatement(Cursor.kind)) {
+ if (const Stmt *S = getCursorStmt(Cursor))
+ return Visit(S);
+
+ return false;
+ }
+
+ if (clang_isExpression(Cursor.kind)) {
+ if (const Expr *E = getCursorExpr(Cursor))
+ return Visit(E);
+
+ return false;
+ }
+
+ if (clang_isTranslationUnit(Cursor.kind)) {
+ CXTranslationUnit TU = getCursorTU(Cursor);
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+
+ int VisitOrder[2] = {VisitPreprocessorLast, !VisitPreprocessorLast};
+ for (unsigned I = 0; I != 2; ++I) {
+ if (VisitOrder[I]) {
+ if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
+ RegionOfInterest.isInvalid()) {
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ const Optional<bool> V = handleDeclForVisitation(*TL);
+ if (!V.hasValue())
+ continue;
+ return V.getValue();
+ }
+ } else if (VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl()))
+ return true;
+ continue;
+ }
+
+ // Walk the preprocessing record.
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord())
+ visitPreprocessedEntitiesInRegion();
+ }
+
+ return false;
+ }
+
+ if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
+ if (const CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
+ if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
+ return Visit(BaseTSInfo->getTypeLoc());
+ }
+ }
+ }
+
+ if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
+ const IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor));
+ if (const ObjCObjectType *ObjT = A->getInterface()->getAs<ObjCObjectType>())
+ return Visit(cxcursor::MakeCursorObjCClassRef(
+ ObjT->getInterface(),
+ A->getInterfaceLoc()->getTypeLoc().getBeginLoc(), TU));
+ }
+
+ // If pointing inside a macro definition, check if the token is an identifier
+ // that was ever defined as a macro. In such a case, create a "pseudo" macro
+ // expansion cursor for that token.
+ SourceLocation BeginLoc = RegionOfInterest.getBegin();
+ if (Cursor.kind == CXCursor_MacroDefinition &&
+ BeginLoc == RegionOfInterest.getEnd()) {
+ SourceLocation Loc = AU->mapLocationToPreamble(BeginLoc);
+ const MacroInfo *MI =
+ getMacroInfo(cxcursor::getCursorMacroDefinition(Cursor), TU);
+ if (MacroDefinitionRecord *MacroDef =
+ checkForMacroInMacroDefinition(MI, Loc, TU))
+ return Visit(cxcursor::MakeMacroExpansionCursor(MacroDef, BeginLoc, TU));
+ }
+
+ // Nothing to visit at the moment.
+ return false;
+}
+
+bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
+ if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ if (Stmt *Body = B->getBody())
+ return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());
+ if (Range.isInvalid())
+ return None;
+
+ switch (CompareRegionOfInterest(Range)) {
+ case RangeBefore:
+ // This declaration comes before the region of interest; skip it.
+ return None;
+
+ case RangeAfter:
+ // This declaration comes after the region of interest; we're done.
+ return false;
+
+ case RangeOverlap:
+ // This declaration overlaps the region of interest; visit it.
+ break;
+ }
+ }
+ return true;
+}
+
+bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
+ DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+
+ // FIXME: Eventually remove. This part of a hack to support proper
+ // iteration over all Decls contained lexically within an ObjC container.
+ SaveAndRestore<DeclContext::decl_iterator *> DI_saved(DI_current, &I);
+ SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);
+
+ for (; I != E; ++I) {
+ Decl *D = *I;
+ if (D->getLexicalDeclContext() != DC)
+ continue;
+ // Filter out synthesized property accessor redeclarations.
+ if (isa<ObjCImplDecl>(DC))
+ if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
+ if (OMD->isSynthesizedAccessorStub())
+ continue;
+ const Optional<bool> V = handleDeclForVisitation(D);
+ if (!V.hasValue())
+ continue;
+ return V.getValue();
+ }
+ return false;
+}
+
+Optional<bool> CursorVisitor::handleDeclForVisitation(const Decl *D) {
+ CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
+
+ // Ignore synthesized ivars here, otherwise if we have something like:
+ // @synthesize prop = _prop;
+ // and '_prop' is not declared, we will encounter a '_prop' ivar before
+ // encountering the 'prop' synthesize declaration and we will think that
+ // we passed the region-of-interest.
+ if (auto *ivarD = dyn_cast<ObjCIvarDecl>(D)) {
+ if (ivarD->getSynthesize())
+ return None;
+ }
+
+ // FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol
+ // declarations is a mismatch with the compiler semantics.
+ if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {
+ auto *ID = cast<ObjCInterfaceDecl>(D);
+ if (!ID->isThisDeclarationADefinition())
+ Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);
+
+ } else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {
+ auto *PD = cast<ObjCProtocolDecl>(D);
+ if (!PD->isThisDeclarationADefinition())
+ Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);
+ }
+
+ const Optional<bool> V = shouldVisitCursor(Cursor);
+ if (!V.hasValue())
+ return None;
+ if (!V.getValue())
+ return false;
+ if (Visit(Cursor, true))
+ return true;
+ return None;
+}
+
+bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ llvm_unreachable("Translation units are visited directly by Visit()");
+}
+
+bool CursorVisitor::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return Visit(MakeCXCursor(D->getTemplatedDecl(), TU, RegionOfInterest));
+}
+
+bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTagDecl(TagDecl *D) { return VisitDeclContext(D); }
+
+bool CursorVisitor::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ bool ShouldVisitBody = false;
+ switch (D->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // Nothing to visit
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ ShouldVisitBody = true;
+ break;
+ }
+
+ // Visit the template arguments used in the specialization.
+ if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
+ TypeLoc TL = SpecType->getTypeLoc();
+ if (TemplateSpecializationTypeLoc TSTLoc =
+ TL.getAs<TemplateSpecializationTypeLoc>()) {
+ for (unsigned I = 0, N = TSTLoc.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TSTLoc.getArgLoc(I)))
+ return true;
+ }
+ }
+
+ return ShouldVisitBody && VisitCXXRecordDecl(D);
+}
+
+bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ // Visit the partial specialization arguments.
+ const ASTTemplateArgumentListInfo *Info = D->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *TemplateArgs = Info->getTemplateArgs();
+ for (unsigned I = 0, N = Info->NumTemplateArgs; I != N; ++I)
+ if (VisitTemplateArgumentLoc(TemplateArgs[I]))
+ return true;
+
+ return VisitCXXRecordDecl(D);
+}
+
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ if (const auto *TC = D->getTypeConstraint())
+ if (Visit(MakeCXCursor(TC->getImmediatelyDeclaredConstraint(), StmtParent,
+ TU, RegionOfInterest)))
+ return true;
+
+ // Visit the default argument.
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
+ if (Visit(DefArg->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ if (Expr *Init = D->getInitExpr())
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
+ return false;
+}
+
+bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ unsigned NumParamList = DD->getNumTemplateParameterLists();
+ for (unsigned i = 0; i < NumParamList; i++) {
+ TemplateParameterList *Params = DD->getTemplateParameterList(i);
+ if (VisitTemplateParameters(Params))
+ return true;
+ }
+
+ if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return false;
+}
+
+static bool HasTrailingReturnType(FunctionDecl *ND) {
+ const QualType Ty = ND->getType();
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT))
+ return FT->hasTrailingReturn();
+ }
+
+ return false;
+}
+
+/// Compare two base or member initializers based on their source order.
+static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
+ CXXCtorInitializer *const *Y) {
+ return (*X)->getSourceOrder() - (*Y)->getSourceOrder();
+}
+
+bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
+ unsigned NumParamList = ND->getNumTemplateParameterLists();
+ for (unsigned i = 0; i < NumParamList; i++) {
+ TemplateParameterList *Params = ND->getTemplateParameterList(i);
+ if (VisitTemplateParameters(Params))
+ return true;
+ }
+
+ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
+ // Visit the function declaration's syntactic components in the order
+ // written. This requires a bit of work.
+ TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+ FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>();
+ const bool HasTrailingRT = HasTrailingReturnType(ND);
+
+ // If we have a function declared directly (without the use of a typedef),
+ // visit just the return type. Otherwise, just visit the function's type
+ // now.
+ if ((FTL && !isa<CXXConversionDecl>(ND) && !HasTrailingRT &&
+ Visit(FTL.getReturnLoc())) ||
+ (!FTL && Visit(TL)))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ // Visit the declaration name.
+ if (!isa<CXXDestructorDecl>(ND))
+ if (VisitDeclarationNameInfo(ND->getNameInfo()))
+ return true;
+
+ // FIXME: Visit explicitly-specified template arguments!
+
+ // Visit the function parameters, if we have a function type.
+ if (FTL && VisitFunctionTypeLoc(FTL, true))
+ return true;
+
+ // Visit the function's trailing return type.
+ if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc()))
+ return true;
+
+ // FIXME: Attributes?
+ }
+
+ if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
+ // Find the initializers that were written in the source.
+ SmallVector<CXXCtorInitializer *, 4> WrittenInits;
+ for (auto *I : Constructor->inits()) {
+ if (!I->isWritten())
+ continue;
+
+ WrittenInits.push_back(I);
+ }
+
+ // Sort the initializers in source order
+ llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
+ &CompareCXXCtorInitializers);
+
+ // Visit the initializers in source order
+ for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
+ CXXCtorInitializer *Init = WrittenInits[I];
+ if (Init->isAnyMemberInitializer()) {
+ if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
+ Init->getMemberLocation(), TU)))
+ return true;
+ } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) {
+ if (Visit(TInfo->getTypeLoc()))
+ return true;
+ }
+
+ // Visit the initializer value.
+ if (Expr *Initializer = Init->getInit())
+ if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest)))
+ return true;
+ }
+ }
+
+ if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *BitWidth = D->getBitWidth())
+ return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
+
+ if (Expr *Init = D->getInClassInitializer())
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitVarDecl(VarDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *Init = D->getInit())
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (Expr *DefArg = D->getDefaultArgument())
+ return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ auto *FD = D->getTemplatedDecl();
+ return VisitAttributes(FD) || VisitFunctionDecl(FD);
+}
+
+bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ auto *CD = D->getTemplatedDecl();
+ return VisitAttributes(CD) || VisitCXXRecordDecl(CD);
+}
+
+bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
+ VisitTemplateArgumentLoc(D->getDefaultArgument()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ // Visit the bound, if it's explicit.
+ if (D->hasExplicitBound()) {
+ if (auto TInfo = D->getTypeSourceInfo()) {
+ if (Visit(TInfo->getTypeLoc()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
+ if (TypeSourceInfo *TSInfo = ND->getReturnTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ for (const auto *P : ND->parameters()) {
+ if (Visit(MakeCXCursor(P, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest));
+}
+
+template <typename DeclIt>
+static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current,
+ SourceManager &SM, SourceLocation EndLoc,
+ SmallVectorImpl<Decl *> &Decls) {
+ DeclIt next = *DI_current;
+ while (++next != DE_current) {
+ Decl *D_next = *next;
+ if (!D_next)
+ break;
+ SourceLocation L = D_next->getBeginLoc();
+ if (!L.isValid())
+ break;
+ if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
+ *DI_current = next;
+ Decls.push_back(D_next);
+ continue;
+ }
+ break;
+ }
+}
+
+bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially
+ // an @implementation can lexically contain Decls that are not properly
+ // nested in the AST. When we identify such cases, we need to retrofit
+ // this nesting here.
+ if (!DI_current && !FileDI_current)
+ return VisitDeclContext(D);
+
+ // Scan the Decls that immediately come after the container
+ // in the current DeclContext. If any fall within the
+ // container's lexical region, stash them into a vector
+ // for later processing.
+ SmallVector<Decl *, 24> DeclsInContainer;
+ SourceLocation EndLoc = D->getSourceRange().getEnd();
+ SourceManager &SM = AU->getSourceManager();
+ if (EndLoc.isValid()) {
+ if (DI_current) {
+ addRangedDeclsInContainer(DI_current, DE_current, SM, EndLoc,
+ DeclsInContainer);
+ } else {
+ addRangedDeclsInContainer(FileDI_current, FileDE_current, SM, EndLoc,
+ DeclsInContainer);
+ }
+ }
+
+ // The common case.
+ if (DeclsInContainer.empty())
+ return VisitDeclContext(D);
+
+ // Get all the Decls in the DeclContext, and sort them with the
+ // additional ones we've collected. Then visit them.
+ for (auto *SubDecl : D->decls()) {
+ if (!SubDecl || SubDecl->getLexicalDeclContext() != D ||
+ SubDecl->getBeginLoc().isInvalid())
+ continue;
+ DeclsInContainer.push_back(SubDecl);
+ }
+
+ // Now sort the Decls so that they appear in lexical order.
+ llvm::sort(DeclsInContainer, [&SM](Decl *A, Decl *B) {
+ SourceLocation L_A = A->getBeginLoc();
+ SourceLocation L_B = B->getBeginLoc();
+ return L_A != L_B
+ ? SM.isBeforeInTranslationUnit(L_A, L_B)
+ : SM.isBeforeInTranslationUnit(A->getEndLoc(), B->getEndLoc());
+ });
+
+ // Now visit the decls.
+ for (SmallVectorImpl<Decl *>::iterator I = DeclsInContainer.begin(),
+ E = DeclsInContainer.end();
+ I != E; ++I) {
+ CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest);
+ const Optional<bool> &V = shouldVisitCursor(Cursor);
+ if (!V.hasValue())
+ continue;
+ if (!V.getValue())
+ return false;
+ if (Visit(Cursor, true))
+ return true;
+ }
+ return false;
+}
+
+bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
+ TU)))
+ return true;
+
+ if (VisitObjCTypeParamList(ND->getTypeParamList()))
+ return true;
+
+ ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
+ for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
+ E = ND->protocol_end();
+ I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(ND);
+}
+
+bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ if (!PID->isThisDeclarationADefinition())
+ return Visit(MakeCursorObjCProtocolRef(PID, PID->getLocation(), TU));
+
+ ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
+ E = PID->protocol_end();
+ I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(PID);
+}
+
+bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
+ if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))
+ return true;
+
+ // FIXME: This implements a workaround with @property declarations also being
+ // installed in the DeclContext for the @interface. Eventually this code
+ // should be removed.
+ ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
+ if (!CDecl || !CDecl->IsClassExtension())
+ return false;
+
+ ObjCInterfaceDecl *ID = CDecl->getClassInterface();
+ if (!ID)
+ return false;
+
+ IdentifierInfo *PropertyId = PD->getIdentifier();
+ ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(
+ cast<DeclContext>(ID), PropertyId, PD->getQueryKind());
+
+ if (!prevDecl)
+ return false;
+
+ // Visit synthesized methods since they will be skipped when visiting
+ // the @interface.
+ if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
+ if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
+ if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
+ return true;
+
+ if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
+ if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
+ if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCTypeParamList(ObjCTypeParamList *typeParamList) {
+ if (!typeParamList)
+ return false;
+
+ for (auto *typeParam : *typeParamList) {
+ // Visit the type parameter.
+ if (Visit(MakeCXCursor(typeParam, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ if (!D->isThisDeclarationADefinition()) {
+ // Forward declaration is treated like a reference.
+ return Visit(MakeCursorObjCClassRef(D, D->getLocation(), TU));
+ }
+
+ // Objective-C type parameters.
+ if (VisitObjCTypeParamList(D->getTypeParamListAsWritten()))
+ return true;
+
+ // Issue callbacks for super class.
+ if (D->getSuperClass() && Visit(MakeCursorObjCSuperClassRef(
+ D->getSuperClass(), D->getSuperClassLoc(), TU)))
+ return true;
+
+ if (TypeSourceInfo *SuperClassTInfo = D->getSuperClassTInfo())
+ if (Visit(SuperClassTInfo->getTypeLoc()))
+ return true;
+
+ ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end();
+ I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(D);
+}
+
+bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
+ return VisitObjCContainerDecl(D);
+}
+
+bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ // 'ID' could be null when dealing with invalid code.
+ if (ObjCInterfaceDecl *ID = D->getClassInterface())
+ if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
+ return true;
+
+ return VisitObjCImplDecl(D);
+}
+
+bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+#if 0
+ // Issue callbacks for super class.
+ // FIXME: No source location information!
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+#endif
+
+ return VisitObjCImplDecl(D);
+}
+
+bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
+ if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
+ if (PD->isIvarNameSpecified())
+ return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
+ D->getTargetNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ }
+
+ if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))
+ return true;
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
+ D->getIdentLocation(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ }
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ if (Visit(MakeCXCursor(D->getAssertExpr(), StmtParent, TU, RegionOfInterest)))
+ return true;
+ if (StringLiteral *Message = D->getMessage())
+ if (Visit(MakeCXCursor(Message, StmtParent, TU, RegionOfInterest)))
+ return true;
+ return false;
+}
+
+bool CursorVisitor::VisitFriendDecl(FriendDecl *D) {
+ if (NamedDecl *FriendD = D->getFriendDecl()) {
+ if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest)))
+ return true;
+ } else if (TypeSourceInfo *TI = D->getFriendType()) {
+ if (Visit(TI->getTypeLoc()))
+ return true;
+ }
+ return false;
+}
+
+bool CursorVisitor::VisitDecompositionDecl(DecompositionDecl *D) {
+ for (auto *B : D->bindings()) {
+ if (Visit(MakeCXCursor(B, TU, RegionOfInterest)))
+ return true;
+ }
+ return VisitVarDecl(D);
+}
+
+bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
+ switch (Name.getName().getNameKind()) {
+ case clang::DeclarationName::Identifier:
+ case clang::DeclarationName::CXXLiteralOperatorName:
+ case clang::DeclarationName::CXXDeductionGuideName:
+ case clang::DeclarationName::CXXOperatorName:
+ case clang::DeclarationName::CXXUsingDirective:
+ return false;
+
+ case clang::DeclarationName::CXXConstructorName:
+ case clang::DeclarationName::CXXDestructorName:
+ case clang::DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case clang::DeclarationName::ObjCZeroArgSelector:
+ case clang::DeclarationName::ObjCOneArgSelector:
+ case clang::DeclarationName::ObjCMultiArgSelector:
+ // FIXME: Per-identifier location info?
+ return false;
+ }
+
+ llvm_unreachable("Invalid DeclarationName::Kind!");
+}
+
+bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range) {
+ // FIXME: This whole routine is a hack to work around the lack of proper
+ // source information in nested-name-specifiers (PR5791). Since we do have
+ // a beginning source location, we can visit the first component of the
+ // nested-name-specifier, if it's a single-token component.
+ if (!NNS)
+ return false;
+
+ // Get the first component in the nested-name-specifier.
+ while (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ NNS = Prefix;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ return Visit(
+ MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU));
+
+ case NestedNameSpecifier::NamespaceAlias:
+ return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
+ Range.getBegin(), TU));
+
+ case NestedNameSpecifier::TypeSpec: {
+ // If the type has a form where we know that the beginning of the source
+ // range matches up with a reference cursor. Visit the appropriate reference
+ // cursor.
+ const Type *T = NNS->getAsType();
+ if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
+ if (const TagType *Tag = dyn_cast<TagType>(T))
+ return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
+ if (const TemplateSpecializationType *TST =
+ dyn_cast<TemplateSpecializationType>(T))
+ return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Super:
+ break;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc Qualifier) {
+ SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+ for (; Qualifier; Qualifier = Qualifier.getPrefix())
+ Qualifiers.push_back(Qualifier);
+
+ while (!Qualifiers.empty()) {
+ NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+ NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
+ Q.getLocalBeginLoc(), TU)))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
+ Q.getLocalBeginLoc(), TU)))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (Visit(Q.getTypeLoc()))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Super:
+ break;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateParameters(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return false;
+
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+ switch (Name.getKind()) {
+ case TemplateName::Template:
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+
+ case TemplateName::OverloadedTemplate:
+ // Visit the overloaded template set.
+ if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
+ return true;
+
+ return false;
+
+ case TemplateName::AssumedTemplate:
+ // FIXME: Visit DeclarationName?
+ return false;
+
+ case TemplateName::DependentTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return false;
+
+ case TemplateName::QualifiedTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsQualifiedTemplateName()->getDecl(), Loc, TU));
+
+ case TemplateName::SubstTemplateTemplateParm:
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsSubstTemplateTemplateParm()->getParameter(), Loc, TU));
+
+ case TemplateName::SubstTemplateTemplateParmPack:
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc,
+ TU));
+ }
+
+ llvm_unreachable("Invalid TemplateName::Kind!");
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+ switch (TAL.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ return false;
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case TemplateArgument::Declaration:
+ if (Expr *E = TAL.getSourceDeclExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::NullPtr:
+ if (Expr *E = TAL.getSourceNullPtrExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::Expression:
+ if (Expr *E = TAL.getSourceExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
+ return true;
+
+ return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
+ TAL.getTemplateNameLoc());
+ }
+
+ llvm_unreachable("Invalid TemplateArgument::Kind!");
+}
+
+bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return Visit(TL.getUnqualifiedLoc());
+}
+
+bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ ASTContext &Context = AU->getASTContext();
+
+ // Some builtin types (such as Objective-C's "id", "sel", and
+ // "Class") have associated declarations. Create cursors for those.
+ QualType VisitType;
+ switch (TL.getTypePtr()->getKind()) {
+
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Dependent:
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLReserveID:
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64SVEACLETypes.def"
+#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
+#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
+#define BUILTIN_TYPE(Id, SingletonId)
+#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ break;
+
+ case BuiltinType::ObjCId:
+ VisitType = Context.getObjCIdType();
+ break;
+
+ case BuiltinType::ObjCClass:
+ VisitType = Context.getObjCClassType();
+ break;
+
+ case BuiltinType::ObjCSel:
+ VisitType = Context.getObjCSelType();
+ break;
+ }
+
+ if (!VisitType.isNull()) {
+ if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
+ return Visit(
+ MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(), TU));
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
+ if (TL.isDefinition())
+ return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));
+
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
+ if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getBeginLoc(), TU)))
+ return true;
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumTypeArgs(); I != N; ++I) {
+ if (Visit(TL.getTypeArgTInfo(I)->getTypeLoc()))
+ return true;
+ }
+
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
+ return Visit(TL.getInnerLoc());
+}
+
+bool CursorVisitor::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
+ return Visit(TL.getInnerLoc());
+}
+
+bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitUsingTypeLoc(UsingTypeLoc TL) { return false; }
+
+bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ return Visit(TL.getModifiedLoc());
+}
+
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
+ bool SkipResultType) {
+ if (!SkipResultType && Visit(TL.getReturnLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumParams(); I != N; ++I)
+ if (Decl *D = TL.getParam(I))
+ if (Visit(MakeCXCursor(D, TU, RegionOfInterest)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ if (Visit(TL.getElementLoc()))
+ return true;
+
+ if (Expr *Size = TL.getSizeExpr())
+ return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ return Visit(TL.getOriginalLoc());
+}
+
+bool CursorVisitor::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ return Visit(TL.getOriginalLoc());
+}
+
+bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc(
+ DeducedTemplateSpecializationTypeLoc TL) {
+ if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
+ TL.getTemplateNameLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ // Visit the template name.
+ if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
+ TL.getTemplateNameLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ return VisitNestedNameSpecifierLoc(TL.getQualifierLoc());
+}
+
+bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ // Visit the nested-name-specifier, if there is one.
+ if (TL.getQualifierLoc() && VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return Visit(TL.getNamedTypeLoc());
+}
+
+bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ return Visit(TL.getPatternLoc());
+}
+
+bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ if (Expr *E = TL.getUnderlyingExpr())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ return Visit(TL.getValueLoc());
+}
+
+bool CursorVisitor::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ return Visit(TL.getValueLoc());
+}
+
+#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \
+ bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
+ return Visit##PARENT##Loc(TL); \
+ }
+
+DEFAULT_TYPELOC_IMPL(Complex, Type)
+DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type)
+DEFAULT_TYPELOC_IMPL(DependentVector, Type)
+DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
+DEFAULT_TYPELOC_IMPL(Vector, Type)
+DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)
+DEFAULT_TYPELOC_IMPL(ConstantMatrix, MatrixType)
+DEFAULT_TYPELOC_IMPL(DependentSizedMatrix, MatrixType)
+DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType)
+DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType)
+DEFAULT_TYPELOC_IMPL(Record, TagType)
+DEFAULT_TYPELOC_IMPL(Enum, TagType)
+DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
+DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
+DEFAULT_TYPELOC_IMPL(Auto, Type)
+DEFAULT_TYPELOC_IMPL(BitInt, Type)
+DEFAULT_TYPELOC_IMPL(DependentBitInt, Type)
+
+bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ if (D->isCompleteDefinition()) {
+ for (const auto &I : D->bases()) {
+ if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(&I, TU)))
+ return true;
+ }
+ }
+
+ return VisitTagDecl(D);
+}
+
+bool CursorVisitor::VisitAttributes(Decl *D) {
+ for (const auto *I : D->attrs())
+ if ((TU->ParsingOptions & CXTranslationUnit_VisitImplicitAttributes ||
+ !I->isImplicit()) &&
+ Visit(MakeCXCursor(I, D, TU)))
+ return true;
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Data-recursive visitor methods.
+//===----------------------------------------------------------------------===//
+
+namespace {
+#define DEF_JOB(NAME, DATA, KIND) \
+ class NAME : public VisitorJob { \
+ public: \
+ NAME(const DATA *d, CXCursor parent) \
+ : VisitorJob(parent, VisitorJob::KIND, d) {} \
+ static bool classof(const VisitorJob *VJ) { \
+ return VJ->getKind() == KIND; \
+ } \
+ const DATA *get() const { return static_cast<const DATA *>(data[0]); } \
+ };
+
+DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
+DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
+DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
+DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
+DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
+DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)
+DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)
+#undef DEF_JOB
+
+class ExplicitTemplateArgsVisit : public VisitorJob {
+public:
+ ExplicitTemplateArgsVisit(const TemplateArgumentLoc *Begin,
+ const TemplateArgumentLoc *End, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::ExplicitTemplateArgsVisitKind, Begin,
+ End) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == ExplicitTemplateArgsVisitKind;
+ }
+ const TemplateArgumentLoc *begin() const {
+ return static_cast<const TemplateArgumentLoc *>(data[0]);
+ }
+ const TemplateArgumentLoc *end() {
+ return static_cast<const TemplateArgumentLoc *>(data[1]);
+ }
+};
+class DeclVisit : public VisitorJob {
+public:
+ DeclVisit(const Decl *D, CXCursor parent, bool isFirst)
+ : VisitorJob(parent, VisitorJob::DeclVisitKind, D,
+ isFirst ? (void *)1 : (void *)nullptr) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == DeclVisitKind;
+ }
+ const Decl *get() const { return static_cast<const Decl *>(data[0]); }
+ bool isFirst() const { return data[1] != nullptr; }
+};
+class TypeLocVisit : public VisitorJob {
+public:
+ TypeLocVisit(TypeLoc tl, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::TypeLocVisitKind,
+ tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == TypeLocVisitKind;
+ }
+
+ TypeLoc get() const {
+ QualType T = QualType::getFromOpaquePtr(data[0]);
+ return TypeLoc(T, const_cast<void *>(data[1]));
+ }
+};
+
+class LabelRefVisit : public VisitorJob {
+public:
+ LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
+ labelLoc.getPtrEncoding()) {}
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::LabelRefVisitKind;
+ }
+ const LabelDecl *get() const {
+ return static_cast<const LabelDecl *>(data[0]);
+ }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromPtrEncoding(data[1]);
+ }
+};
+
+class NestedNameSpecifierLocVisit : public VisitorJob {
+public:
+ NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
+ Qualifier.getNestedNameSpecifier(),
+ Qualifier.getOpaqueData()) {}
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;
+ }
+
+ NestedNameSpecifierLoc get() const {
+ return NestedNameSpecifierLoc(
+ const_cast<NestedNameSpecifier *>(
+ static_cast<const NestedNameSpecifier *>(data[0])),
+ const_cast<void *>(data[1]));
+ }
+};
+
+class DeclarationNameInfoVisit : public VisitorJob {
+public:
+ DeclarationNameInfoVisit(const Stmt *S, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;
+ }
+ DeclarationNameInfo get() const {
+ const Stmt *S = static_cast<const Stmt *>(data[0]);
+ switch (S->getStmtClass()) {
+ default:
+ llvm_unreachable("Unhandled Stmt");
+ case clang::Stmt::MSDependentExistsStmtClass:
+ return cast<MSDependentExistsStmt>(S)->getNameInfo();
+ case Stmt::CXXDependentScopeMemberExprClass:
+ return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
+ case Stmt::DependentScopeDeclRefExprClass:
+ return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
+ case Stmt::OMPCriticalDirectiveClass:
+ return cast<OMPCriticalDirective>(S)->getDirectiveName();
+ }
+ }
+};
+class MemberRefVisit : public VisitorJob {
+public:
+ MemberRefVisit(const FieldDecl *D, SourceLocation L, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,
+ L.getPtrEncoding()) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::MemberRefVisitKind;
+ }
+ const FieldDecl *get() const {
+ return static_cast<const FieldDecl *>(data[0]);
+ }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromRawEncoding(
+ (SourceLocation::UIntTy)(uintptr_t)data[1]);
+ }
+};
+class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
+ friend class OMPClauseEnqueue;
+ VisitorWorkList &WL;
+ CXCursor Parent;
+
+public:
+ EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)
+ : WL(wl), Parent(parent) {}
+
+ void VisitAddrLabelExpr(const AddrLabelExpr *E);
+ void VisitBlockExpr(const BlockExpr *B);
+ void VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
+ void VisitCompoundStmt(const CompoundStmt *S);
+ void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */
+ }
+ void VisitMSDependentExistsStmt(const MSDependentExistsStmt *S);
+ void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E);
+ void VisitCXXNewExpr(const CXXNewExpr *E);
+ void VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
+ void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *E);
+ void VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E);
+ void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *E);
+ void VisitCXXTypeidExpr(const CXXTypeidExpr *E);
+ void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *E);
+ void VisitCXXUuidofExpr(const CXXUuidofExpr *E);
+ void VisitCXXCatchStmt(const CXXCatchStmt *S);
+ void VisitCXXForRangeStmt(const CXXForRangeStmt *S);
+ void VisitDeclRefExpr(const DeclRefExpr *D);
+ void VisitDeclStmt(const DeclStmt *S);
+ void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E);
+ void VisitDesignatedInitExpr(const DesignatedInitExpr *E);
+ void VisitExplicitCastExpr(const ExplicitCastExpr *E);
+ void VisitForStmt(const ForStmt *FS);
+ void VisitGotoStmt(const GotoStmt *GS);
+ void VisitIfStmt(const IfStmt *If);
+ void VisitInitListExpr(const InitListExpr *IE);
+ void VisitMemberExpr(const MemberExpr *M);
+ void VisitOffsetOfExpr(const OffsetOfExpr *E);
+ void VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
+ void VisitObjCMessageExpr(const ObjCMessageExpr *M);
+ void VisitOverloadExpr(const OverloadExpr *E);
+ void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
+ void VisitStmt(const Stmt *S);
+ void VisitSwitchStmt(const SwitchStmt *S);
+ void VisitWhileStmt(const WhileStmt *W);
+ void VisitTypeTraitExpr(const TypeTraitExpr *E);
+ void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E);
+ void VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
+ void VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *U);
+ void VisitVAArgExpr(const VAArgExpr *E);
+ void VisitSizeOfPackExpr(const SizeOfPackExpr *E);
+ void VisitPseudoObjectExpr(const PseudoObjectExpr *E);
+ void VisitOpaqueValueExpr(const OpaqueValueExpr *E);
+ void VisitLambdaExpr(const LambdaExpr *E);
+ void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
+ void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D);
+ void VisitOMPLoopDirective(const OMPLoopDirective *D);
+ void VisitOMPParallelDirective(const OMPParallelDirective *D);
+ void VisitOMPSimdDirective(const OMPSimdDirective *D);
+ void
+ VisitOMPLoopTransformationDirective(const OMPLoopTransformationDirective *D);
+ void VisitOMPTileDirective(const OMPTileDirective *D);
+ void VisitOMPUnrollDirective(const OMPUnrollDirective *D);
+ void VisitOMPForDirective(const OMPForDirective *D);
+ void VisitOMPForSimdDirective(const OMPForSimdDirective *D);
+ void VisitOMPSectionsDirective(const OMPSectionsDirective *D);
+ void VisitOMPSectionDirective(const OMPSectionDirective *D);
+ void VisitOMPSingleDirective(const OMPSingleDirective *D);
+ void VisitOMPMasterDirective(const OMPMasterDirective *D);
+ void VisitOMPCriticalDirective(const OMPCriticalDirective *D);
+ void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
+ void VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective *D);
+ void VisitOMPParallelMasterDirective(const OMPParallelMasterDirective *D);
+ void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
+ void VisitOMPTaskDirective(const OMPTaskDirective *D);
+ void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
+ void VisitOMPBarrierDirective(const OMPBarrierDirective *D);
+ void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D);
+ void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D);
+ void
+ VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D);
+ void VisitOMPCancelDirective(const OMPCancelDirective *D);
+ void VisitOMPFlushDirective(const OMPFlushDirective *D);
+ void VisitOMPDepobjDirective(const OMPDepobjDirective *D);
+ void VisitOMPScanDirective(const OMPScanDirective *D);
+ void VisitOMPOrderedDirective(const OMPOrderedDirective *D);
+ void VisitOMPAtomicDirective(const OMPAtomicDirective *D);
+ void VisitOMPTargetDirective(const OMPTargetDirective *D);
+ void VisitOMPTargetDataDirective(const OMPTargetDataDirective *D);
+ void VisitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective *D);
+ void VisitOMPTargetExitDataDirective(const OMPTargetExitDataDirective *D);
+ void VisitOMPTargetParallelDirective(const OMPTargetParallelDirective *D);
+ void
+ VisitOMPTargetParallelForDirective(const OMPTargetParallelForDirective *D);
+ void VisitOMPTeamsDirective(const OMPTeamsDirective *D);
+ void VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D);
+ void VisitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective *D);
+ void VisitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective *D);
+ void
+ VisitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective *D);
+ void VisitOMPParallelMasterTaskLoopDirective(
+ const OMPParallelMasterTaskLoopDirective *D);
+ void VisitOMPParallelMasterTaskLoopSimdDirective(
+ const OMPParallelMasterTaskLoopSimdDirective *D);
+ void VisitOMPDistributeDirective(const OMPDistributeDirective *D);
+ void VisitOMPDistributeParallelForDirective(
+ const OMPDistributeParallelForDirective *D);
+ void VisitOMPDistributeParallelForSimdDirective(
+ const OMPDistributeParallelForSimdDirective *D);
+ void VisitOMPDistributeSimdDirective(const OMPDistributeSimdDirective *D);
+ void VisitOMPTargetParallelForSimdDirective(
+ const OMPTargetParallelForSimdDirective *D);
+ void VisitOMPTargetSimdDirective(const OMPTargetSimdDirective *D);
+ void VisitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective *D);
+ void VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *D);
+ void VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *D);
+ void VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *D);
+ void VisitOMPTargetTeamsDirective(const OMPTargetTeamsDirective *D);
+ void VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *D);
+ void VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *D);
+ void VisitOMPTargetTeamsDistributeParallelForSimdDirective(
+ const OMPTargetTeamsDistributeParallelForSimdDirective *D);
+ void VisitOMPTargetTeamsDistributeSimdDirective(
+ const OMPTargetTeamsDistributeSimdDirective *D);
+
+private:
+ void AddDeclarationNameInfo(const Stmt *S);
+ void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
+ void AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
+ unsigned NumTemplateArgs);
+ void AddMemberRef(const FieldDecl *D, SourceLocation L);
+ void AddStmt(const Stmt *S);
+ void AddDecl(const Decl *D, bool isFirst = true);
+ void AddTypeLoc(TypeSourceInfo *TI);
+ void EnqueueChildren(const Stmt *S);
+ void EnqueueChildren(const OMPClause *S);
+};
+} // namespace
+
+void EnqueueVisitor::AddDeclarationNameInfo(const Stmt *S) {
+ // 'S' should always be non-null, since it comes from the
+ // statement we are visiting.
+ WL.push_back(DeclarationNameInfoVisit(S, Parent));
+}
+
+void EnqueueVisitor::AddNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc Qualifier) {
+ if (Qualifier)
+ WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));
+}
+
+void EnqueueVisitor::AddStmt(const Stmt *S) {
+ if (S)
+ WL.push_back(StmtVisit(S, Parent));
+}
+void EnqueueVisitor::AddDecl(const Decl *D, bool isFirst) {
+ if (D)
+ WL.push_back(DeclVisit(D, Parent, isFirst));
+}
+void EnqueueVisitor::AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
+ unsigned NumTemplateArgs) {
+ WL.push_back(ExplicitTemplateArgsVisit(A, A + NumTemplateArgs, Parent));
+}
+void EnqueueVisitor::AddMemberRef(const FieldDecl *D, SourceLocation L) {
+ if (D)
+ WL.push_back(MemberRefVisit(D, L, Parent));
+}
+void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {
+ if (TI)
+ WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));
+}
+void EnqueueVisitor::EnqueueChildren(const Stmt *S) {
+ unsigned size = WL.size();
+ for (const Stmt *SubStmt : S->children()) {
+ AddStmt(SubStmt);
+ }
+ if (size == WL.size())
+ return;
+ // Now reverse the entries we just added. This will match the DFS
+ // ordering performed by the worklist.
+ VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+ std::reverse(I, E);
+}
+namespace {
+class OMPClauseEnqueue : public ConstOMPClauseVisitor<OMPClauseEnqueue> {
+ EnqueueVisitor *Visitor;
+ /// Process clauses with list of variables.
+ template <typename T> void VisitOMPClauseList(T *Node);
+
+public:
+ OMPClauseEnqueue(EnqueueVisitor *Visitor) : Visitor(Visitor) {}
+#define GEN_CLANG_CLAUSE_CLASS
+#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(const Class *C);
+#include "llvm/Frontend/OpenMP/OMP.inc"
+ void VisitOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
+ void VisitOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
+};
+
+void OMPClauseEnqueue::VisitOMPClauseWithPreInit(
+ const OMPClauseWithPreInit *C) {
+ Visitor->AddStmt(C->getPreInitStmt());
+}
+
+void OMPClauseEnqueue::VisitOMPClauseWithPostUpdate(
+ const OMPClauseWithPostUpdate *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getPostUpdateExpr());
+}
+
+void OMPClauseEnqueue::VisitOMPIfClause(const OMPIfClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getCondition());
+}
+
+void OMPClauseEnqueue::VisitOMPFinalClause(const OMPFinalClause *C) {
+ Visitor->AddStmt(C->getCondition());
+}
+
+void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getNumThreads());
+}
+
+void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
+ Visitor->AddStmt(C->getSafelen());
+}
+
+void OMPClauseEnqueue::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
+ Visitor->AddStmt(C->getSimdlen());
+}
+
+void OMPClauseEnqueue::VisitOMPSizesClause(const OMPSizesClause *C) {
+ for (auto E : C->getSizesRefs())
+ Visitor->AddStmt(E);
+}
+
+void OMPClauseEnqueue::VisitOMPFullClause(const OMPFullClause *C) {}
+
+void OMPClauseEnqueue::VisitOMPPartialClause(const OMPPartialClause *C) {
+ Visitor->AddStmt(C->getFactor());
+}
+
+void OMPClauseEnqueue::VisitOMPAllocatorClause(const OMPAllocatorClause *C) {
+ Visitor->AddStmt(C->getAllocator());
+}
+
+void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) {
+ Visitor->AddStmt(C->getNumForLoops());
+}
+
+void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) {}
+
+void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) {}
+
+void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getChunkSize());
+}
+
+void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) {
+ Visitor->AddStmt(C->getNumForLoops());
+}
+
+void OMPClauseEnqueue::VisitOMPDetachClause(const OMPDetachClause *C) {
+ Visitor->AddStmt(C->getEventHandler());
+}
+
+void OMPClauseEnqueue::VisitOMPNowaitClause(const OMPNowaitClause *) {}
+
+void OMPClauseEnqueue::VisitOMPUntiedClause(const OMPUntiedClause *) {}
+
+void OMPClauseEnqueue::VisitOMPMergeableClause(const OMPMergeableClause *) {}
+
+void OMPClauseEnqueue::VisitOMPReadClause(const OMPReadClause *) {}
+
+void OMPClauseEnqueue::VisitOMPWriteClause(const OMPWriteClause *) {}
+
+void OMPClauseEnqueue::VisitOMPUpdateClause(const OMPUpdateClause *) {}
+
+void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {}
+
+void OMPClauseEnqueue::VisitOMPCompareClause(const OMPCompareClause *) {}
+
+void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+
+void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
+
+void OMPClauseEnqueue::VisitOMPAcquireClause(const OMPAcquireClause *) {}
+
+void OMPClauseEnqueue::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
+void OMPClauseEnqueue::VisitOMPRelaxedClause(const OMPRelaxedClause *) {}
+
+void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
+
+void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
+
+void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
+
+void OMPClauseEnqueue::VisitOMPInitClause(const OMPInitClause *C) {
+ VisitOMPClauseList(C);
+}
+
+void OMPClauseEnqueue::VisitOMPUseClause(const OMPUseClause *C) {
+ Visitor->AddStmt(C->getInteropVar());
+}
+
+void OMPClauseEnqueue::VisitOMPDestroyClause(const OMPDestroyClause *C) {
+ if (C->getInteropVar())
+ Visitor->AddStmt(C->getInteropVar());
+}
+
+void OMPClauseEnqueue::VisitOMPNovariantsClause(const OMPNovariantsClause *C) {
+ Visitor->AddStmt(C->getCondition());
+}
+
+void OMPClauseEnqueue::VisitOMPNocontextClause(const OMPNocontextClause *C) {
+ Visitor->AddStmt(C->getCondition());
+}
+
+void OMPClauseEnqueue::VisitOMPFilterClause(const OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getThreadID());
+}
+
+void OMPClauseEnqueue::VisitOMPAlignClause(const OMPAlignClause *C) {
+ Visitor->AddStmt(C->getAlignment());
+}
+
+void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
+ const OMPUnifiedAddressClause *) {}
+
+void OMPClauseEnqueue::VisitOMPUnifiedSharedMemoryClause(
+ const OMPUnifiedSharedMemoryClause *) {}
+
+void OMPClauseEnqueue::VisitOMPReverseOffloadClause(
+ const OMPReverseOffloadClause *) {}
+
+void OMPClauseEnqueue::VisitOMPDynamicAllocatorsClause(
+ const OMPDynamicAllocatorsClause *) {}
+
+void OMPClauseEnqueue::VisitOMPAtomicDefaultMemOrderClause(
+ const OMPAtomicDefaultMemOrderClause *) {}
+
+void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
+ Visitor->AddStmt(C->getDevice());
+}
+
+void OMPClauseEnqueue::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getNumTeams());
+}
+
+void OMPClauseEnqueue::VisitOMPThreadLimitClause(
+ const OMPThreadLimitClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getThreadLimit());
+}
+
+void OMPClauseEnqueue::VisitOMPPriorityClause(const OMPPriorityClause *C) {
+ Visitor->AddStmt(C->getPriority());
+}
+
+void OMPClauseEnqueue::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
+ Visitor->AddStmt(C->getGrainsize());
+}
+
+void OMPClauseEnqueue::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
+ Visitor->AddStmt(C->getNumTasks());
+}
+
+void OMPClauseEnqueue::VisitOMPHintClause(const OMPHintClause *C) {
+ Visitor->AddStmt(C->getHint());
+}
+
+template <typename T> void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
+ for (const auto *I : Node->varlists()) {
+ Visitor->AddStmt(I);
+ }
+}
+
+void OMPClauseEnqueue::VisitOMPInclusiveClause(const OMPInclusiveClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPExclusiveClause(const OMPExclusiveClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPAllocateClause(const OMPAllocateClause *C) {
+ VisitOMPClauseList(C);
+ Visitor->AddStmt(C->getAllocator());
+}
+void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) {
+ VisitOMPClauseList(C);
+ for (const auto *E : C->private_copies()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPFirstprivateClause(
+ const OMPFirstprivateClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPreInit(C);
+ for (const auto *E : C->private_copies()) {
+ Visitor->AddStmt(E);
+ }
+ for (const auto *E : C->inits()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPLastprivateClause(
+ const OMPLastprivateClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
+ for (auto *E : C->private_copies()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->source_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
+ for (auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->lhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Visitor->AddStmt(E);
+ }
+ if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {
+ for (auto *E : C->copy_ops()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->copy_array_temps()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->copy_array_elems()) {
+ Visitor->AddStmt(E);
+ }
+ }
+}
+void OMPClauseEnqueue::VisitOMPTaskReductionClause(
+ const OMPTaskReductionClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
+ for (auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->lhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPInReductionClause(
+ const OMPInReductionClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
+ for (auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->lhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->taskgroup_descriptors())
+ Visitor->AddStmt(E);
+}
+void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
+ VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
+ for (const auto *E : C->privates()) {
+ Visitor->AddStmt(E);
+ }
+ for (const auto *E : C->inits()) {
+ Visitor->AddStmt(E);
+ }
+ for (const auto *E : C->updates()) {
+ Visitor->AddStmt(E);
+ }
+ for (const auto *E : C->finals()) {
+ Visitor->AddStmt(E);
+ }
+ Visitor->AddStmt(C->getStep());
+ Visitor->AddStmt(C->getCalcStep());
+}
+void OMPClauseEnqueue::VisitOMPAlignedClause(const OMPAlignedClause *C) {
+ VisitOMPClauseList(C);
+ Visitor->AddStmt(C->getAlignment());
+}
+void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
+ VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPCopyprivateClause(
+ const OMPCopyprivateClause *C) {
+ VisitOMPClauseList(C);
+ for (auto *E : C->source_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->destination_exprs()) {
+ Visitor->AddStmt(E);
+ }
+ for (auto *E : C->assignment_ops()) {
+ Visitor->AddStmt(E);
+ }
+}
+void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPDepobjClause(const OMPDepobjClause *C) {
+ Visitor->AddStmt(C->getDepobj());
+}
+void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPMapClause(const OMPMapClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPDistScheduleClause(
+ const OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Visitor->AddStmt(C->getChunkSize());
+}
+void OMPClauseEnqueue::VisitOMPDefaultmapClause(
+ const OMPDefaultmapClause * /*C*/) {}
+void OMPClauseEnqueue::VisitOMPToClause(const OMPToClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPFromClause(const OMPFromClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPUseDevicePtrClause(
+ const OMPUseDevicePtrClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPUseDeviceAddrClause(
+ const OMPUseDeviceAddrClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPIsDevicePtrClause(
+ const OMPIsDevicePtrClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseEnqueue::VisitOMPNontemporalClause(
+ const OMPNontemporalClause *C) {
+ VisitOMPClauseList(C);
+ for (const auto *E : C->private_refs())
+ Visitor->AddStmt(E);
+}
+void OMPClauseEnqueue::VisitOMPOrderClause(const OMPOrderClause *C) {}
+void OMPClauseEnqueue::VisitOMPUsesAllocatorsClause(
+ const OMPUsesAllocatorsClause *C) {
+ for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
+ const OMPUsesAllocatorsClause::Data &D = C->getAllocatorData(I);
+ Visitor->AddStmt(D.Allocator);
+ Visitor->AddStmt(D.AllocatorTraits);
+ }
+}
+void OMPClauseEnqueue::VisitOMPAffinityClause(const OMPAffinityClause *C) {
+ Visitor->AddStmt(C->getModifier());
+ for (const Expr *E : C->varlists())
+ Visitor->AddStmt(E);
+}
+void OMPClauseEnqueue::VisitOMPBindClause(const OMPBindClause *C) {}
+
+} // namespace
+
+void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
+ unsigned size = WL.size();
+ OMPClauseEnqueue Visitor(this);
+ Visitor.Visit(S);
+ if (size == WL.size())
+ return;
+ // Now reverse the entries we just added. This will match the DFS
+ // ordering performed by the worklist.
+ VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+ std::reverse(I, E);
+}
+void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) {
+ WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
+}
+void EnqueueVisitor::VisitBlockExpr(const BlockExpr *B) {
+ AddDecl(B->getBlockDecl());
+}
+void EnqueueVisitor::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCompoundStmt(const CompoundStmt *S) {
+ for (auto &I : llvm::reverse(S->body()))
+ AddStmt(I);
+}
+void EnqueueVisitor::VisitMSDependentExistsStmt(
+ const MSDependentExistsStmt *S) {
+ AddStmt(S->getSubStmt());
+ AddDeclarationNameInfo(S);
+ if (NestedNameSpecifierLoc QualifierLoc = S->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+}
+
+void EnqueueVisitor::VisitCXXDependentScopeMemberExpr(
+ const CXXDependentScopeMemberExpr *E) {
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
+ AddDeclarationNameInfo(E);
+ if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+ if (!E->isImplicitAccess())
+ AddStmt(E->getBase());
+}
+void EnqueueVisitor::VisitCXXNewExpr(const CXXNewExpr *E) {
+ // Enqueue the initializer , if any.
+ AddStmt(E->getInitializer());
+ // Enqueue the array size, if any.
+ AddStmt(E->getArraySize().getValueOr(nullptr));
+ // Enqueue the allocated type.
+ AddTypeLoc(E->getAllocatedTypeSourceInfo());
+ // Enqueue the placement arguments.
+ for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)
+ AddStmt(E->getPlacementArg(I - 1));
+}
+void EnqueueVisitor::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *CE) {
+ for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)
+ AddStmt(CE->getArg(I - 1));
+ AddStmt(CE->getCallee());
+ AddStmt(CE->getArg(0));
+}
+void EnqueueVisitor::VisitCXXPseudoDestructorExpr(
+ const CXXPseudoDestructorExpr *E) {
+ // Visit the name of the type being destroyed.
+ AddTypeLoc(E->getDestroyedTypeInfo());
+ // Visit the scope type that looks disturbingly like the nested-name-specifier
+ // but isn't.
+ AddTypeLoc(E->getScopeTypeInfo());
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+ // Visit base expression.
+ AddStmt(E->getBase());
+}
+void EnqueueVisitor::VisitCXXScalarValueInitExpr(
+ const CXXScalarValueInitExpr *E) {
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXTemporaryObjectExpr(
+ const CXXTemporaryObjectExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
+ EnqueueChildren(E);
+ if (E->isTypeOperand())
+ AddTypeLoc(E->getTypeOperandSourceInfo());
+}
+
+void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(
+ const CXXUnresolvedConstructExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ EnqueueChildren(E);
+ if (E->isTypeOperand())
+ AddTypeLoc(E->getTypeOperandSourceInfo());
+}
+
+void EnqueueVisitor::VisitCXXCatchStmt(const CXXCatchStmt *S) {
+ EnqueueChildren(S);
+ AddDecl(S->getExceptionDecl());
+}
+
+void EnqueueVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
+ AddStmt(S->getBody());
+ AddStmt(S->getRangeInit());
+ AddDecl(S->getLoopVariable());
+}
+
+void EnqueueVisitor::VisitDeclRefExpr(const DeclRefExpr *DR) {
+ if (DR->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(DR->getTemplateArgs(), DR->getNumTemplateArgs());
+ WL.push_back(DeclRefExprParts(DR, Parent));
+}
+void EnqueueVisitor::VisitDependentScopeDeclRefExpr(
+ const DependentScopeDeclRefExpr *E) {
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
+ AddDeclarationNameInfo(E);
+ AddNestedNameSpecifierLoc(E->getQualifierLoc());
+}
+void EnqueueVisitor::VisitDeclStmt(const DeclStmt *S) {
+ unsigned size = WL.size();
+ bool isFirst = true;
+ for (const auto *D : S->decls()) {
+ AddDecl(D, isFirst);
+ isFirst = false;
+ }
+ if (size == WL.size())
+ return;
+ // Now reverse the entries we just added. This will match the DFS
+ // ordering performed by the worklist.
+ VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+ std::reverse(I, E);
+}
+void EnqueueVisitor::VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
+ AddStmt(E->getInit());
+ for (const DesignatedInitExpr::Designator &D :
+ llvm::reverse(E->designators())) {
+ if (D.isFieldDesignator()) {
+ if (FieldDecl *Field = D.getField())
+ AddMemberRef(Field, D.getFieldLoc());
+ continue;
+ }
+ if (D.isArrayDesignator()) {
+ AddStmt(E->getArrayIndex(D));
+ continue;
+ }
+ assert(D.isArrayRangeDesignator() && "Unknown designator kind");
+ AddStmt(E->getArrayRangeEnd(D));
+ AddStmt(E->getArrayRangeStart(D));
+ }
+}
+void EnqueueVisitor::VisitExplicitCastExpr(const ExplicitCastExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeInfoAsWritten());
+}
+void EnqueueVisitor::VisitForStmt(const ForStmt *FS) {
+ AddStmt(FS->getBody());
+ AddStmt(FS->getInc());
+ AddStmt(FS->getCond());
+ AddDecl(FS->getConditionVariable());
+ AddStmt(FS->getInit());
+}
+void EnqueueVisitor::VisitGotoStmt(const GotoStmt *GS) {
+ WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));
+}
+void EnqueueVisitor::VisitIfStmt(const IfStmt *If) {
+ AddStmt(If->getElse());
+ AddStmt(If->getThen());
+ AddStmt(If->getCond());
+ AddStmt(If->getInit());
+ AddDecl(If->getConditionVariable());
+}
+void EnqueueVisitor::VisitInitListExpr(const InitListExpr *IE) {
+ // We care about the syntactic form of the initializer list, only.
+ if (InitListExpr *Syntactic = IE->getSyntacticForm())
+ IE = Syntactic;
+ EnqueueChildren(IE);
+}
+void EnqueueVisitor::VisitMemberExpr(const MemberExpr *M) {
+ WL.push_back(MemberExprParts(M, Parent));
+
+ // If the base of the member access expression is an implicit 'this', don't
+ // visit it.
+ // FIXME: If we ever want to show these implicit accesses, this will be
+ // unfortunate. However, clang_getCursor() relies on this behavior.
+ if (M->isImplicitAccess())
+ return;
+
+ // Ignore base anonymous struct/union fields, otherwise they will shadow the
+ // real field that we are interested in.
+ if (auto *SubME = dyn_cast<MemberExpr>(M->getBase())) {
+ if (auto *FD = dyn_cast_or_null<FieldDecl>(SubME->getMemberDecl())) {
+ if (FD->isAnonymousStructOrUnion()) {
+ AddStmt(SubME->getBase());
+ return;
+ }
+ }
+ }
+
+ AddStmt(M->getBase());
+}
+void EnqueueVisitor::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
+ AddTypeLoc(E->getEncodedTypeSourceInfo());
+}
+void EnqueueVisitor::VisitObjCMessageExpr(const ObjCMessageExpr *M) {
+ EnqueueChildren(M);
+ AddTypeLoc(M->getClassReceiverTypeInfo());
+}
+void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
+ // Visit the components of the offsetof expression.
+ for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
+ const OffsetOfNode &Node = E->getComponent(I - 1);
+ switch (Node.getKind()) {
+ case OffsetOfNode::Array:
+ AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
+ break;
+ case OffsetOfNode::Field:
+ AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
+ break;
+ case OffsetOfNode::Identifier:
+ case OffsetOfNode::Base:
+ continue;
+ }
+ }
+ // Visit the type into which we're computing the offset.
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitOverloadExpr(const OverloadExpr *E) {
+ if (E->hasExplicitTemplateArgs())
+ AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
+ WL.push_back(OverloadExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
+ const UnaryExprOrTypeTraitExpr *E) {
+ EnqueueChildren(E);
+ if (E->isArgumentType())
+ AddTypeLoc(E->getArgumentTypeInfo());
+}
+void EnqueueVisitor::VisitStmt(const Stmt *S) { EnqueueChildren(S); }
+void EnqueueVisitor::VisitSwitchStmt(const SwitchStmt *S) {
+ AddStmt(S->getBody());
+ AddStmt(S->getCond());
+ AddDecl(S->getConditionVariable());
+}
+
+void EnqueueVisitor::VisitWhileStmt(const WhileStmt *W) {
+ AddStmt(W->getBody());
+ AddStmt(W->getCond());
+ AddDecl(W->getConditionVariable());
+}
+
+void EnqueueVisitor::VisitTypeTraitExpr(const TypeTraitExpr *E) {
+ for (unsigned I = E->getNumArgs(); I > 0; --I)
+ AddTypeLoc(E->getArg(I - 1));
+}
+
+void EnqueueVisitor::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
+ AddTypeLoc(E->getQueriedTypeSourceInfo());
+}
+
+void EnqueueVisitor::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
+ EnqueueChildren(E);
+}
+
+void EnqueueVisitor::VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *U) {
+ VisitOverloadExpr(U);
+ if (!U->isImplicitAccess())
+ AddStmt(U->getBase());
+}
+void EnqueueVisitor::VisitVAArgExpr(const VAArgExpr *E) {
+ AddStmt(E->getSubExpr());
+ AddTypeLoc(E->getWrittenTypeInfo());
+}
+void EnqueueVisitor::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
+ WL.push_back(SizeOfPackExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
+ // If the opaque value has a source expression, just transparently
+ // visit that. This is useful for (e.g.) pseudo-object expressions.
+ if (Expr *SourceExpr = E->getSourceExpr())
+ return Visit(SourceExpr);
+}
+void EnqueueVisitor::VisitLambdaExpr(const LambdaExpr *E) {
+ AddStmt(E->getBody());
+ WL.push_back(LambdaExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
+ // Treat the expression like its syntactic form.
+ Visit(E->getSyntacticForm());
+}
+
+void EnqueueVisitor::VisitOMPExecutableDirective(
+ const OMPExecutableDirective *D) {
+ EnqueueChildren(D);
+ for (ArrayRef<OMPClause *>::iterator I = D->clauses().begin(),
+ E = D->clauses().end();
+ I != E; ++I)
+ EnqueueChildren(*I);
+}
+
+void EnqueueVisitor::VisitOMPLoopBasedDirective(
+ const OMPLoopBasedDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPLoopDirective(const OMPLoopDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelDirective(const OMPParallelDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPSimdDirective(const OMPSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPLoopTransformationDirective(
+ const OMPLoopTransformationDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTileDirective(const OMPTileDirective *D) {
+ VisitOMPLoopTransformationDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPUnrollDirective(const OMPUnrollDirective *D) {
+ VisitOMPLoopTransformationDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPForDirective(const OMPForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPForSimdDirective(const OMPForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPSectionsDirective(const OMPSectionsDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPSectionDirective(const OMPSectionDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPSingleDirective(const OMPSingleDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPMasterDirective(const OMPMasterDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPCriticalDirective(const OMPCriticalDirective *D) {
+ VisitOMPExecutableDirective(D);
+ AddDeclarationNameInfo(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelForDirective(
+ const OMPParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelForSimdDirective(
+ const OMPParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelMasterDirective(
+ const OMPParallelMasterDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelSectionsDirective(
+ const OMPParallelSectionsDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskyieldDirective(
+ const OMPTaskyieldDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPBarrierDirective(const OMPBarrierDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskgroupDirective(
+ const OMPTaskgroupDirective *D) {
+ VisitOMPExecutableDirective(D);
+ if (const Expr *E = D->getReductionRef())
+ VisitStmt(E);
+}
+
+void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDepobjDirective(const OMPDepobjDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPScanDirective(const OMPScanDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPAtomicDirective(const OMPAtomicDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetDataDirective(
+ const OMPTargetDataDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetEnterDataDirective(
+ const OMPTargetEnterDataDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetExitDataDirective(
+ const OMPTargetExitDataDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetParallelDirective(
+ const OMPTargetParallelDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetParallelForDirective(
+ const OMPTargetParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDirective(const OMPTeamsDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPCancellationPointDirective(
+ const OMPCancellationPointDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPCancelDirective(const OMPCancelDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTaskLoopSimdDirective(
+ const OMPTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPMasterTaskLoopDirective(
+ const OMPMasterTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPMasterTaskLoopSimdDirective(
+ const OMPMasterTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelMasterTaskLoopDirective(
+ const OMPParallelMasterTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPParallelMasterTaskLoopSimdDirective(
+ const OMPParallelMasterTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDistributeDirective(
+ const OMPDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDistributeParallelForDirective(
+ const OMPDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDistributeParallelForSimdDirective(
+ const OMPDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPDistributeSimdDirective(
+ const OMPDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetParallelForSimdDirective(
+ const OMPTargetParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetSimdDirective(
+ const OMPTargetSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDirective(
+ const OMPTargetTeamsDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
+ const OMPTargetTeamsDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeSimdDirective(
+ const OMPTargetTeamsDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
+ EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU, RegionOfInterest))
+ .Visit(S);
+}
+
+bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange Range = getRawCursorExtent(C);
+ if (Range.isInvalid() || CompareRegionOfInterest(Range))
+ return false;
+ }
+ return true;
+}
+
+bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
+ while (!WL.empty()) {
+ // Dequeue the worklist item.
+ VisitorJob LI = WL.pop_back_val();
+
+ // Set the Parent field, then back to its old value once we're done.
+ SetParentRAII SetParent(Parent, StmtParent, LI.getParent());
+
+ switch (LI.getKind()) {
+ case VisitorJob::DeclVisitKind: {
+ const Decl *D = cast<DeclVisit>(&LI)->get();
+ if (!D)
+ continue;
+
+ // For now, perform default visitation for Decls.
+ if (Visit(MakeCXCursor(D, TU, RegionOfInterest,
+ cast<DeclVisit>(&LI)->isFirst())))
+ return true;
+
+ continue;
+ }
+ case VisitorJob::ExplicitTemplateArgsVisitKind: {
+ for (const TemplateArgumentLoc &Arg :
+ *cast<ExplicitTemplateArgsVisit>(&LI)) {
+ if (VisitTemplateArgumentLoc(Arg))
+ return true;
+ }
+ continue;
+ }
+ case VisitorJob::TypeLocVisitKind: {
+ // Perform default visitation for TypeLocs.
+ if (Visit(cast<TypeLocVisit>(&LI)->get()))
+ return true;
+ continue;
+ }
+ case VisitorJob::LabelRefVisitKind: {
+ const LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
+ if (LabelStmt *stmt = LS->getStmt()) {
+ if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),
+ TU))) {
+ return true;
+ }
+ }
+ continue;
+ }
+
+ case VisitorJob::NestedNameSpecifierLocVisitKind: {
+ NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);
+ if (VisitNestedNameSpecifierLoc(V->get()))
+ return true;
+ continue;
+ }
+
+ case VisitorJob::DeclarationNameInfoVisitKind: {
+ if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)->get()))
+ return true;
+ continue;
+ }
+ case VisitorJob::MemberRefVisitKind: {
+ MemberRefVisit *V = cast<MemberRefVisit>(&LI);
+ if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))
+ return true;
+ continue;
+ }
+ case VisitorJob::StmtVisitKind: {
+ const Stmt *S = cast<StmtVisit>(&LI)->get();
+ if (!S)
+ continue;
+
+ // Update the current cursor.
+ CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest);
+ if (!IsInRegionOfInterest(Cursor))
+ continue;
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
+ case CXChildVisit_Continue:
+ break;
+ case CXChildVisit_Recurse:
+ if (PostChildrenVisitor)
+ WL.push_back(PostChildrenVisit(nullptr, Cursor));
+ EnqueueWorkList(WL, S);
+ break;
+ }
+ continue;
+ }
+ case VisitorJob::MemberExprPartsKind: {
+ // Handle the other pieces in the MemberExpr besides the base.
+ const MemberExpr *M = cast<MemberExprParts>(&LI)->get();
+
+ // Visit the nested-name-specifier
+ if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(M->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments, if any.
+ if (M->hasExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),
+ *ArgEnd = Arg + M->getNumTemplateArgs();
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+ continue;
+ }
+ case VisitorJob::DeclRefExprPartsKind: {
+ const DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
+ // Visit nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ // Visit declaration name.
+ if (VisitDeclarationNameInfo(DR->getNameInfo()))
+ return true;
+ continue;
+ }
+ case VisitorJob::OverloadExprPartsKind: {
+ const OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(O->getNameInfo()))
+ return true;
+ // Visit the overloaded declaration reference.
+ if (Visit(MakeCursorOverloadedDeclRef(O, TU)))
+ return true;
+ continue;
+ }
+ case VisitorJob::SizeOfPackExprPartsKind: {
+ const SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();
+ NamedDecl *Pack = E->getPack();
+ if (isa<TemplateTypeParmDecl>(Pack)) {
+ if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),
+ E->getPackLoc(), TU)))
+ return true;
+
+ continue;
+ }
+
+ if (isa<TemplateTemplateParmDecl>(Pack)) {
+ if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),
+ E->getPackLoc(), TU)))
+ return true;
+
+ continue;
+ }
+
+ // Non-type template parameter packs and function parameter packs are
+ // treated like DeclRefExpr cursors.
+ continue;
+ }
+
+ case VisitorJob::LambdaExprPartsKind: {
+ // Visit non-init captures.
+ const LambdaExpr *E = cast<LambdaExprParts>(&LI)->get();
+ for (LambdaExpr::capture_iterator C = E->explicit_capture_begin(),
+ CEnd = E->explicit_capture_end();
+ C != CEnd; ++C) {
+ if (!C->capturesVariable())
+ continue;
+
+ if (Visit(MakeCursorVariableRef(C->getCapturedVar(), C->getLocation(),
+ TU)))
+ return true;
+ }
+ // Visit init captures
+ for (auto InitExpr : E->capture_inits()) {
+ if (InitExpr && Visit(InitExpr))
+ return true;
+ }
+
+ TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ // Visit parameters and return type, if present.
+ if (FunctionTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+ if (E->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
+ if (Visit(MakeCXCursor(Proto.getParam(I), TU)))
+ return true;
+ }
+ if (E->hasExplicitResultType()) {
+ // Visit result type.
+ if (Visit(Proto.getReturnLoc()))
+ return true;
+ }
+ }
+ break;
+ }
+
+ case VisitorJob::PostChildrenVisitKind:
+ if (PostChildrenVisitor(Parent, ClientData))
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
+bool CursorVisitor::Visit(const Stmt *S) {
+ VisitorWorkList *WL = nullptr;
+ if (!WorkListFreeList.empty()) {
+ WL = WorkListFreeList.back();
+ WL->clear();
+ WorkListFreeList.pop_back();
+ } else {
+ WL = new VisitorWorkList();
+ WorkListCache.push_back(WL);
+ }
+ EnqueueWorkList(*WL, S);
+ bool result = RunVisitorWorkList(*WL);
+ WorkListFreeList.push_back(WL);
+ return result;
+}
+
+namespace {
+typedef SmallVector<SourceRange, 4> RefNamePieces;
+RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
+ const DeclarationNameInfo &NI, SourceRange QLoc,
+ const SourceRange *TemplateArgsLoc = nullptr) {
+ const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
+ const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
+ const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
+
+ const DeclarationName::NameKind Kind = NI.getName().getNameKind();
+
+ RefNamePieces Pieces;
+
+ if (WantQualifier && QLoc.isValid())
+ Pieces.push_back(QLoc);
+
+ if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
+ Pieces.push_back(NI.getLoc());
+
+ if (WantTemplateArgs && TemplateArgsLoc && TemplateArgsLoc->isValid())
+ Pieces.push_back(*TemplateArgsLoc);
+
+ if (Kind == DeclarationName::CXXOperatorName) {
+ Pieces.push_back(NI.getInfo().getCXXOperatorNameBeginLoc());
+ Pieces.push_back(NI.getInfo().getCXXOperatorNameEndLoc());
+ }
+
+ if (WantSinglePiece) {
+ SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd());
+ Pieces.clear();
+ Pieces.push_back(R);
+ }
+
+ return Pieces;
+}
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// Misc. API hooks.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct RegisterFatalErrorHandler {
+ RegisterFatalErrorHandler() {
+ clang_install_aborting_llvm_fatal_error_handler();
+ }
+};
+} // namespace
+
+static llvm::ManagedStatic<RegisterFatalErrorHandler>
+ RegisterFatalErrorHandlerOnce;
+
+CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+ int displayDiagnostics) {
+ // We use crash recovery to make some of our APIs more reliable, implicitly
+ // enable it.
+ if (!getenv("LIBCLANG_DISABLE_CRASH_RECOVERY"))
+ llvm::CrashRecoveryContext::Enable();
+
+ // Look through the managed static to trigger construction of the managed
+ // static which registers our fatal error handler. This ensures it is only
+ // registered once.
+ (void)*RegisterFatalErrorHandlerOnce;
+
+ // Initialize targets for clang module support.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+
+ CIndexer *CIdxr = new CIndexer();
+
+ if (excludeDeclarationsFromPCH)
+ CIdxr->setOnlyLocalDecls();
+ if (displayDiagnostics)
+ CIdxr->setDisplayDiagnostics();
+
+ if (getenv("LIBCLANG_BGPRIO_INDEX"))
+ CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
+ CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
+ if (getenv("LIBCLANG_BGPRIO_EDIT"))
+ CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
+ CXGlobalOpt_ThreadBackgroundPriorityForEditing);
+
+ return CIdxr;
+}
+
+void clang_disposeIndex(CXIndex CIdx) {
+ if (CIdx)
+ delete static_cast<CIndexer *>(CIdx);
+}
+
+void clang_CXIndex_setGlobalOptions(CXIndex CIdx, unsigned options) {
+ if (CIdx)
+ static_cast<CIndexer *>(CIdx)->setCXGlobalOptFlags(options);
+}
+
+unsigned clang_CXIndex_getGlobalOptions(CXIndex CIdx) {
+ if (CIdx)
+ return static_cast<CIndexer *>(CIdx)->getCXGlobalOptFlags();
+ return 0;
+}
+
+void clang_CXIndex_setInvocationEmissionPathOption(CXIndex CIdx,
+ const char *Path) {
+ if (CIdx)
+ static_cast<CIndexer *>(CIdx)->setInvocationEmissionPath(Path ? Path : "");
+}
+
+void clang_toggleCrashRecovery(unsigned isEnabled) {
+ if (isEnabled)
+ llvm::CrashRecoveryContext::Enable();
+ else
+ llvm::CrashRecoveryContext::Disable();
+}
+
+CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
+ const char *ast_filename) {
+ CXTranslationUnit TU;
+ enum CXErrorCode Result =
+ clang_createTranslationUnit2(CIdx, ast_filename, &TU);
+ (void)Result;
+ assert((TU && Result == CXError_Success) ||
+ (!TU && Result != CXError_Success));
+ return TU;
+}
+
+enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
+ const char *ast_filename,
+ CXTranslationUnit *out_TU) {
+ if (out_TU)
+ *out_TU = nullptr;
+
+ if (!CIdx || !ast_filename || !out_TU)
+ return CXError_InvalidArguments;
+
+ LOG_FUNC_SECTION { *Log << ast_filename; }
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ FileSystemOptions FileSystemOpts;
+
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ CompilerInstance::createDiagnostics(new DiagnosticOptions());
+ std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
+ ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(),
+ ASTUnit::LoadEverything, Diags, FileSystemOpts, /*UseDebugInfo=*/false,
+ CXXIdx->getOnlyLocalDecls(), CaptureDiagsKind::All,
+ /*AllowASTWithCompilerErrors=*/true,
+ /*UserFilesAreVolatile=*/true);
+ *out_TU = MakeCXTranslationUnit(CXXIdx, std::move(AU));
+ return *out_TU ? CXError_Success : CXError_Failure;
+}
+
+unsigned clang_defaultEditingTranslationUnitOptions() {
+ return CXTranslationUnit_PrecompiledPreamble |
+ CXTranslationUnit_CacheCompletionResults;
+}
+
+CXTranslationUnit 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) {
+ unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord;
+ return clang_parseTranslationUnit(CIdx, source_filename, command_line_args,
+ num_command_line_args, unsaved_files,
+ num_unsaved_files, Options);
+}
+
+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) {
+ // Set up the initial return values.
+ if (out_TU)
+ *out_TU = nullptr;
+
+ // Check arguments.
+ if (!CIdx || !out_TU)
+ return CXError_InvalidArguments;
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
+ bool CreatePreambleOnFirstParse =
+ options & CXTranslationUnit_CreatePreambleOnFirstParse;
+ // FIXME: Add a flag for modules.
+ TranslationUnitKind TUKind = (options & (CXTranslationUnit_Incomplete |
+ CXTranslationUnit_SingleFileParse))
+ ? TU_Prefix
+ : TU_Complete;
+ bool CacheCodeCompletionResults =
+ options & CXTranslationUnit_CacheCompletionResults;
+ bool IncludeBriefCommentsInCodeCompletion =
+ options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
+ bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
+ bool ForSerialization = options & CXTranslationUnit_ForSerialization;
+ bool RetainExcludedCB =
+ options & CXTranslationUnit_RetainExcludedConditionalBlocks;
+ SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
+ if (options & CXTranslationUnit_SkipFunctionBodies) {
+ SkipFunctionBodies =
+ (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble)
+ ? SkipFunctionBodiesScope::Preamble
+ : SkipFunctionBodiesScope::PreambleAndMainFile;
+ }
+
+ // Configure the diagnostics.
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ CompilerInstance::createDiagnostics(new DiagnosticOptions));
+
+ if (options & CXTranslationUnit_KeepGoing)
+ Diags->setFatalsAsError(true);
+
+ CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::All;
+ if (options & CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles)
+ CaptureDiagnostics = CaptureDiagsKind::AllWithoutNonErrorsFromIncludes;
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ DiagnosticsEngine,
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
+ DiagCleanup(Diags.get());
+
+ std::unique_ptr<std::vector<ASTUnit::RemappedFile>> RemappedFiles(
+ new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<ASTUnit::RemappedFile>>
+ RemappedCleanup(RemappedFiles.get());
+
+ for (auto &UF : unsaved_files) {
+ std::unique_ptr<llvm::MemoryBuffer> MB =
+ llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
+ RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
+ }
+
+ std::unique_ptr<std::vector<const char *>> Args(
+ new std::vector<const char *>());
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char *>>
+ ArgsCleanup(Args.get());
+
+ // Since the Clang C library is primarily used by batch tools dealing with
+ // (often very broken) source code, where spell-checking can have a
+ // significant negative impact on performance (particularly when
+ // precompiled headers are involved), we disable it by default.
+ // Only do this if we haven't found a spell-checking-related argument.
+ bool FoundSpellCheckingArgument = false;
+ for (int I = 0; I != num_command_line_args; ++I) {
+ if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||
+ strcmp(command_line_args[I], "-fspell-checking") == 0) {
+ FoundSpellCheckingArgument = true;
+ break;
+ }
+ }
+ Args->insert(Args->end(), command_line_args,
+ command_line_args + num_command_line_args);
+
+ if (!FoundSpellCheckingArgument)
+ Args->insert(Args->begin() + 1, "-fno-spell-checking");
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ // Put the source file after command_line_args otherwise if '-x' flag is
+ // present it will be unused.
+ if (source_filename)
+ Args->push_back(source_filename);
+
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ Args->push_back("-Xclang");
+ Args->push_back("-detailed-preprocessing-record");
+ }
+
+ // Suppress any editor placeholder diagnostics.
+ Args->push_back("-fallow-editor-placeholders");
+
+ unsigned NumErrors = Diags->getClient()->getNumErrors();
+ std::unique_ptr<ASTUnit> ErrUnit;
+ // Unless the user specified that they want the preamble on the first parse
+ // set it up to be created on the first reparse. This makes the first parse
+ // faster, trading for a slower (first) reparse.
+ unsigned PrecompilePreambleAfterNParses =
+ !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
+
+ LibclangInvocationReporter InvocationReporter(
+ *CXXIdx, LibclangInvocationReporter::OperationKind::ParseOperation,
+ options, llvm::makeArrayRef(*Args), /*InvocationArgs=*/None,
+ unsaved_files);
+ std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
+ Args->data(), Args->data() + Args->size(),
+ CXXIdx->getPCHContainerOperations(), Diags,
+ CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(),
+ CaptureDiagnostics, *RemappedFiles.get(),
+ /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses,
+ TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion,
+ /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse,
+ /*UserFilesAreVolatile=*/true, ForSerialization, RetainExcludedCB,
+ CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(),
+ &ErrUnit));
+
+ // Early failures in LoadFromCommandLine may return with ErrUnit unset.
+ if (!Unit && !ErrUnit)
+ return CXError_ASTReadError;
+
+ if (NumErrors != Diags->getClient()->getNumErrors()) {
+ // Make sure to check that 'Unit' is non-NULL.
+ if (CXXIdx->getDisplayDiagnostics())
+ printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
+ }
+
+ if (isASTReadError(Unit ? Unit.get() : ErrUnit.get()))
+ return CXError_ASTReadError;
+
+ *out_TU = MakeCXTranslationUnit(CXXIdx, std::move(Unit));
+ if (CXTranslationUnitImpl *TU = *out_TU) {
+ TU->ParsingOptions = options;
+ TU->Arguments.reserve(Args->size());
+ for (const char *Arg : *Args)
+ TU->Arguments.push_back(Arg);
+ return CXError_Success;
+ }
+ return CXError_Failure;
+}
+
+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) {
+ CXTranslationUnit TU;
+ enum CXErrorCode Result = clang_parseTranslationUnit2(
+ CIdx, source_filename, command_line_args, num_command_line_args,
+ unsaved_files, num_unsaved_files, options, &TU);
+ (void)Result;
+ assert((TU && Result == CXError_Success) ||
+ (!TU && Result != CXError_Success));
+ return TU;
+}
+
+enum CXErrorCode 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) {
+ noteBottomOfStack();
+ SmallVector<const char *, 4> Args;
+ Args.push_back("clang");
+ Args.append(command_line_args, command_line_args + num_command_line_args);
+ return clang_parseTranslationUnit2FullArgv(
+ CIdx, source_filename, Args.data(), Args.size(), unsaved_files,
+ num_unsaved_files, options, out_TU);
+}
+
+enum CXErrorCode 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) {
+ LOG_FUNC_SECTION {
+ *Log << source_filename << ": ";
+ for (int i = 0; i != num_command_line_args; ++i)
+ *Log << command_line_args[i] << " ";
+ }
+
+ if (num_unsaved_files && !unsaved_files)
+ return CXError_InvalidArguments;
+
+ CXErrorCode result = CXError_Failure;
+ auto ParseTranslationUnitImpl = [=, &result] {
+ noteBottomOfStack();
+ result = clang_parseTranslationUnit_Impl(
+ CIdx, source_filename, command_line_args, num_command_line_args,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), options, out_TU);
+ };
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, ParseTranslationUnitImpl)) {
+ fprintf(stderr, "libclang: crash detected during parsing: {\n");
+ fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
+ fprintf(stderr, " 'command_line_args' : [");
+ for (int i = 0; i != num_command_line_args; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "'%s'", command_line_args[i]);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'unsaved_files' : [");
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
+ unsaved_files[i].Length);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return CXError_Crashed;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
+ if (CXTranslationUnit *TU = out_TU)
+ PrintLibclangResourceUsage(*TU);
+ }
+
+ return result;
+}
+
+CXString clang_Type_getObjCEncoding(CXType CT) {
+ CXTranslationUnit tu = static_cast<CXTranslationUnit>(CT.data[1]);
+ ASTContext &Ctx = getASTUnit(tu)->getASTContext();
+ std::string encoding;
+ Ctx.getObjCEncodingForType(QualType::getFromOpaquePtr(CT.data[0]), encoding);
+
+ return cxstring::createDup(encoding);
+}
+
+static const IdentifierInfo *getMacroIdentifier(CXCursor C) {
+ if (C.kind == CXCursor_MacroDefinition) {
+ if (const MacroDefinitionRecord *MDR = getCursorMacroDefinition(C))
+ return MDR->getName();
+ } else if (C.kind == CXCursor_MacroExpansion) {
+ MacroExpansionCursor ME = getCursorMacroExpansion(C);
+ return ME.getName();
+ }
+ return nullptr;
+}
+
+unsigned clang_Cursor_isMacroFunctionLike(CXCursor C) {
+ const IdentifierInfo *II = getMacroIdentifier(C);
+ if (!II) {
+ return false;
+ }
+ ASTUnit *ASTU = getCursorASTUnit(C);
+ Preprocessor &PP = ASTU->getPreprocessor();
+ if (const MacroInfo *MI = PP.getMacroInfo(II))
+ return MI->isFunctionLike();
+ return false;
+}
+
+unsigned clang_Cursor_isMacroBuiltin(CXCursor C) {
+ const IdentifierInfo *II = getMacroIdentifier(C);
+ if (!II) {
+ return false;
+ }
+ ASTUnit *ASTU = getCursorASTUnit(C);
+ Preprocessor &PP = ASTU->getPreprocessor();
+ if (const MacroInfo *MI = PP.getMacroInfo(II))
+ return MI->isBuiltinMacro();
+ return false;
+}
+
+unsigned clang_Cursor_isFunctionInlined(CXCursor C) {
+ const Decl *D = getCursorDecl(C);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (!FD) {
+ return false;
+ }
+ return FD->isInlined();
+}
+
+static StringLiteral *getCFSTR_value(CallExpr *callExpr) {
+ if (callExpr->getNumArgs() != 1) {
+ return nullptr;
+ }
+
+ StringLiteral *S = nullptr;
+ auto *arg = callExpr->getArg(0);
+ if (arg->getStmtClass() == Stmt::ImplicitCastExprClass) {
+ ImplicitCastExpr *I = static_cast<ImplicitCastExpr *>(arg);
+ auto *subExpr = I->getSubExprAsWritten();
+
+ if (subExpr->getStmtClass() != Stmt::StringLiteralClass) {
+ return nullptr;
+ }
+
+ S = static_cast<StringLiteral *>(I->getSubExprAsWritten());
+ } else if (arg->getStmtClass() == Stmt::StringLiteralClass) {
+ S = static_cast<StringLiteral *>(callExpr->getArg(0));
+ } else {
+ return nullptr;
+ }
+ return S;
+}
+
+struct ExprEvalResult {
+ CXEvalResultKind EvalType;
+ union {
+ unsigned long long unsignedVal;
+ long long intVal;
+ double floatVal;
+ char *stringVal;
+ } EvalData;
+ bool IsUnsignedInt;
+ ~ExprEvalResult() {
+ if (EvalType != CXEval_UnExposed && EvalType != CXEval_Float &&
+ EvalType != CXEval_Int) {
+ delete[] EvalData.stringVal;
+ }
+ }
+};
+
+void clang_EvalResult_dispose(CXEvalResult E) {
+ delete static_cast<ExprEvalResult *>(E);
+}
+
+CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E) {
+ if (!E) {
+ return CXEval_UnExposed;
+ }
+ return ((ExprEvalResult *)E)->EvalType;
+}
+
+int clang_EvalResult_getAsInt(CXEvalResult E) {
+ return clang_EvalResult_getAsLongLong(E);
+}
+
+long long clang_EvalResult_getAsLongLong(CXEvalResult E) {
+ if (!E) {
+ return 0;
+ }
+ ExprEvalResult *Result = (ExprEvalResult *)E;
+ if (Result->IsUnsignedInt)
+ return Result->EvalData.unsignedVal;
+ return Result->EvalData.intVal;
+}
+
+unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E) {
+ return ((ExprEvalResult *)E)->IsUnsignedInt;
+}
+
+unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E) {
+ if (!E) {
+ return 0;
+ }
+
+ ExprEvalResult *Result = (ExprEvalResult *)E;
+ if (Result->IsUnsignedInt)
+ return Result->EvalData.unsignedVal;
+ return Result->EvalData.intVal;
+}
+
+double clang_EvalResult_getAsDouble(CXEvalResult E) {
+ if (!E) {
+ return 0;
+ }
+ return ((ExprEvalResult *)E)->EvalData.floatVal;
+}
+
+const char *clang_EvalResult_getAsStr(CXEvalResult E) {
+ if (!E) {
+ return nullptr;
+ }
+ return ((ExprEvalResult *)E)->EvalData.stringVal;
+}
+
+static const ExprEvalResult *evaluateExpr(Expr *expr, CXCursor C) {
+ Expr::EvalResult ER;
+ ASTContext &ctx = getCursorContext(C);
+ if (!expr)
+ return nullptr;
+
+ expr = expr->IgnoreParens();
+ if (expr->isValueDependent())
+ return nullptr;
+ if (!expr->EvaluateAsRValue(ER, ctx))
+ return nullptr;
+
+ QualType rettype;
+ CallExpr *callExpr;
+ auto result = std::make_unique<ExprEvalResult>();
+ result->EvalType = CXEval_UnExposed;
+ result->IsUnsignedInt = false;
+
+ if (ER.Val.isInt()) {
+ result->EvalType = CXEval_Int;
+
+ auto &val = ER.Val.getInt();
+ if (val.isUnsigned()) {
+ result->IsUnsignedInt = true;
+ result->EvalData.unsignedVal = val.getZExtValue();
+ } else {
+ result->EvalData.intVal = val.getExtValue();
+ }
+
+ return result.release();
+ }
+
+ if (ER.Val.isFloat()) {
+ llvm::SmallVector<char, 100> Buffer;
+ ER.Val.getFloat().toString(Buffer);
+ std::string floatStr(Buffer.data(), Buffer.size());
+ result->EvalType = CXEval_Float;
+ bool ignored;
+ llvm::APFloat apFloat = ER.Val.getFloat();
+ apFloat.convert(llvm::APFloat::IEEEdouble(),
+ llvm::APFloat::rmNearestTiesToEven, &ignored);
+ result->EvalData.floatVal = apFloat.convertToDouble();
+ return result.release();
+ }
+
+ if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
+ const ImplicitCastExpr *I = dyn_cast<ImplicitCastExpr>(expr);
+ auto *subExpr = I->getSubExprAsWritten();
+ if (subExpr->getStmtClass() == Stmt::StringLiteralClass ||
+ subExpr->getStmtClass() == Stmt::ObjCStringLiteralClass) {
+ const StringLiteral *StrE = nullptr;
+ const ObjCStringLiteral *ObjCExpr;
+ ObjCExpr = dyn_cast<ObjCStringLiteral>(subExpr);
+
+ if (ObjCExpr) {
+ StrE = ObjCExpr->getString();
+ result->EvalType = CXEval_ObjCStrLiteral;
+ } else {
+ StrE = cast<StringLiteral>(I->getSubExprAsWritten());
+ result->EvalType = CXEval_StrLiteral;
+ }
+
+ std::string strRef(StrE->getString().str());
+ result->EvalData.stringVal = new char[strRef.size() + 1];
+ strncpy((char *)result->EvalData.stringVal, strRef.c_str(),
+ strRef.size());
+ result->EvalData.stringVal[strRef.size()] = '\0';
+ return result.release();
+ }
+ } else if (expr->getStmtClass() == Stmt::ObjCStringLiteralClass ||
+ expr->getStmtClass() == Stmt::StringLiteralClass) {
+ const StringLiteral *StrE = nullptr;
+ const ObjCStringLiteral *ObjCExpr;
+ ObjCExpr = dyn_cast<ObjCStringLiteral>(expr);
+
+ if (ObjCExpr) {
+ StrE = ObjCExpr->getString();
+ result->EvalType = CXEval_ObjCStrLiteral;
+ } else {
+ StrE = cast<StringLiteral>(expr);
+ result->EvalType = CXEval_StrLiteral;
+ }
+
+ std::string strRef(StrE->getString().str());
+ result->EvalData.stringVal = new char[strRef.size() + 1];
+ strncpy((char *)result->EvalData.stringVal, strRef.c_str(), strRef.size());
+ result->EvalData.stringVal[strRef.size()] = '\0';
+ return result.release();
+ }
+
+ if (expr->getStmtClass() == Stmt::CStyleCastExprClass) {
+ CStyleCastExpr *CC = static_cast<CStyleCastExpr *>(expr);
+
+ rettype = CC->getType();
+ if (rettype.getAsString() == "CFStringRef" &&
+ CC->getSubExpr()->getStmtClass() == Stmt::CallExprClass) {
+
+ callExpr = static_cast<CallExpr *>(CC->getSubExpr());
+ StringLiteral *S = getCFSTR_value(callExpr);
+ if (S) {
+ std::string strLiteral(S->getString().str());
+ result->EvalType = CXEval_CFStr;
+
+ result->EvalData.stringVal = new char[strLiteral.size() + 1];
+ strncpy((char *)result->EvalData.stringVal, strLiteral.c_str(),
+ strLiteral.size());
+ result->EvalData.stringVal[strLiteral.size()] = '\0';
+ return result.release();
+ }
+ }
+
+ } else if (expr->getStmtClass() == Stmt::CallExprClass) {
+ callExpr = static_cast<CallExpr *>(expr);
+ rettype = callExpr->getCallReturnType(ctx);
+
+ if (rettype->isVectorType() || callExpr->getNumArgs() > 1)
+ return nullptr;
+
+ if (rettype->isIntegralType(ctx) || rettype->isRealFloatingType()) {
+ if (callExpr->getNumArgs() == 1 &&
+ !callExpr->getArg(0)->getType()->isIntegralType(ctx))
+ return nullptr;
+ } else if (rettype.getAsString() == "CFStringRef") {
+
+ StringLiteral *S = getCFSTR_value(callExpr);
+ if (S) {
+ std::string strLiteral(S->getString().str());
+ result->EvalType = CXEval_CFStr;
+ result->EvalData.stringVal = new char[strLiteral.size() + 1];
+ strncpy((char *)result->EvalData.stringVal, strLiteral.c_str(),
+ strLiteral.size());
+ result->EvalData.stringVal[strLiteral.size()] = '\0';
+ return result.release();
+ }
+ }
+ } else if (expr->getStmtClass() == Stmt::DeclRefExprClass) {
+ DeclRefExpr *D = static_cast<DeclRefExpr *>(expr);
+ ValueDecl *V = D->getDecl();
+ if (V->getKind() == Decl::Function) {
+ std::string strName = V->getNameAsString();
+ result->EvalType = CXEval_Other;
+ result->EvalData.stringVal = new char[strName.size() + 1];
+ strncpy(result->EvalData.stringVal, strName.c_str(), strName.size());
+ result->EvalData.stringVal[strName.size()] = '\0';
+ return result.release();
+ }
+ }
+
+ return nullptr;
+}
+
+static const Expr *evaluateDeclExpr(const Decl *D) {
+ if (!D)
+ return nullptr;
+ if (auto *Var = dyn_cast<VarDecl>(D))
+ return Var->getInit();
+ else if (auto *Field = dyn_cast<FieldDecl>(D))
+ return Field->getInClassInitializer();
+ return nullptr;
+}
+
+static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) {
+ assert(CS && "invalid compound statement");
+ for (auto *bodyIterator : CS->body()) {
+ if (const auto *E = dyn_cast<Expr>(bodyIterator))
+ return E;
+ }
+ return nullptr;
+}
+
+CXEvalResult clang_Cursor_Evaluate(CXCursor C) {
+ const Expr *E = nullptr;
+ if (clang_getCursorKind(C) == CXCursor_CompoundStmt)
+ E = evaluateCompoundStmtExpr(cast<CompoundStmt>(getCursorStmt(C)));
+ else if (clang_isDeclaration(C.kind))
+ E = evaluateDeclExpr(getCursorDecl(C));
+ else if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+ if (E)
+ return const_cast<CXEvalResult>(
+ reinterpret_cast<const void *>(evaluateExpr(const_cast<Expr *>(E), C)));
+ return nullptr;
+}
+
+unsigned clang_Cursor_hasAttrs(CXCursor C) {
+ const Decl *D = getCursorDecl(C);
+ if (!D) {
+ return 0;
+ }
+
+ if (D->hasAttrs()) {
+ return 1;
+ }
+
+ return 0;
+}
+unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
+ return CXSaveTranslationUnit_None;
+}
+
+static CXSaveError clang_saveTranslationUnit_Impl(CXTranslationUnit TU,
+ const char *FileName,
+ unsigned options) {
+ CIndexer *CXXIdx = TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ bool hadError = cxtu::getASTUnit(TU)->Save(FileName);
+ return hadError ? CXSaveError_Unknown : CXSaveError_None;
+}
+
+int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
+ unsigned options) {
+ LOG_FUNC_SECTION { *Log << TU << ' ' << FileName; }
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return CXSaveError_InvalidTU;
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+ if (!CXXUnit->hasSema())
+ return CXSaveError_InvalidTU;
+
+ CXSaveError result;
+ auto SaveTranslationUnitImpl = [=, &result]() {
+ result = clang_saveTranslationUnit_Impl(TU, FileName, options);
+ };
+
+ if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred()) {
+ SaveTranslationUnitImpl();
+
+ if (getenv("LIBCLANG_RESOURCE_USAGE"))
+ PrintLibclangResourceUsage(TU);
+
+ return result;
+ }
+
+ // We have an AST that has invalid nodes due to compiler errors.
+ // Use a crash recovery thread for protection.
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, SaveTranslationUnitImpl)) {
+ fprintf(stderr, "libclang: crash detected during AST saving: {\n");
+ fprintf(stderr, " 'filename' : '%s'\n", FileName);
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return CXSaveError_Unknown;
+
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
+ PrintLibclangResourceUsage(TU);
+ }
+
+ return result;
+}
+
+void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
+ if (CTUnit) {
+ // If the translation unit has been marked as unsafe to free, just discard
+ // it.
+ ASTUnit *Unit = cxtu::getASTUnit(CTUnit);
+ if (Unit && Unit->isUnsafeToFree())
+ return;
+
+ delete cxtu::getASTUnit(CTUnit);
+ delete CTUnit->StringPool;
+ delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
+ disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
+ delete CTUnit->CommentToXML;
+ delete CTUnit;
+ }
+}
+
+unsigned clang_suspendTranslationUnit(CXTranslationUnit CTUnit) {
+ if (CTUnit) {
+ ASTUnit *Unit = cxtu::getASTUnit(CTUnit);
+
+ if (Unit && Unit->isUnsafeToFree())
+ return false;
+
+ Unit->ResetForParse();
+ return true;
+ }
+
+ return false;
+}
+
+unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
+ return CXReparse_None;
+}
+
+static CXErrorCode
+clang_reparseTranslationUnit_Impl(CXTranslationUnit TU,
+ ArrayRef<CXUnsavedFile> unsaved_files,
+ unsigned options) {
+ // Check arguments.
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return CXError_InvalidArguments;
+ }
+
+ // Reset the associated diagnostics.
+ delete static_cast<CXDiagnosticSetImpl *>(TU->Diagnostics);
+ TU->Diagnostics = nullptr;
+
+ CIndexer *CXXIdx = TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
+ setThreadBackgroundPriority();
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ std::unique_ptr<std::vector<ASTUnit::RemappedFile>> RemappedFiles(
+ new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<ASTUnit::RemappedFile>>
+ RemappedCleanup(RemappedFiles.get());
+
+ for (auto &UF : unsaved_files) {
+ std::unique_ptr<llvm::MemoryBuffer> MB =
+ llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
+ RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release()));
+ }
+
+ if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(),
+ *RemappedFiles.get()))
+ return CXError_Success;
+ if (isASTReadError(CXXUnit))
+ return CXError_ASTReadError;
+ return CXError_Failure;
+}
+
+int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options) {
+ LOG_FUNC_SECTION { *Log << TU; }
+
+ if (num_unsaved_files && !unsaved_files)
+ return CXError_InvalidArguments;
+
+ CXErrorCode result;
+ auto ReparseTranslationUnitImpl = [=, &result]() {
+ result = clang_reparseTranslationUnit_Impl(
+ TU, llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
+ };
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, ReparseTranslationUnitImpl)) {
+ fprintf(stderr, "libclang: crash detected during reparsing\n");
+ cxtu::getASTUnit(TU)->setUnsafeToFree(true);
+ return CXError_Crashed;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
+ PrintLibclangResourceUsage(TU);
+
+ return result;
+}
+
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
+ if (isNotUsableTU(CTUnit)) {
+ LOG_BAD_TU(CTUnit);
+ return cxstring::createEmpty();
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
+ return cxstring::createDup(CXXUnit->getOriginalSourceFileName());
+}
+
+CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullCursor();
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);
+}
+
+CXTargetInfo clang_getTranslationUnitTargetInfo(CXTranslationUnit CTUnit) {
+ if (isNotUsableTU(CTUnit)) {
+ LOG_BAD_TU(CTUnit);
+ return nullptr;
+ }
+
+ CXTargetInfoImpl *impl = new CXTargetInfoImpl();
+ impl->TranslationUnit = CTUnit;
+ return impl;
+}
+
+CXString clang_TargetInfo_getTriple(CXTargetInfo TargetInfo) {
+ if (!TargetInfo)
+ return cxstring::createEmpty();
+
+ CXTranslationUnit CTUnit = TargetInfo->TranslationUnit;
+ assert(!isNotUsableTU(CTUnit) &&
+ "Unexpected unusable translation unit in TargetInfo");
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
+ std::string Triple =
+ CXXUnit->getASTContext().getTargetInfo().getTriple().normalize();
+ return cxstring::createDup(Triple);
+}
+
+int clang_TargetInfo_getPointerWidth(CXTargetInfo TargetInfo) {
+ if (!TargetInfo)
+ return -1;
+
+ CXTranslationUnit CTUnit = TargetInfo->TranslationUnit;
+ assert(!isNotUsableTU(CTUnit) &&
+ "Unexpected unusable translation unit in TargetInfo");
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
+ return CXXUnit->getASTContext().getTargetInfo().getMaxPointerWidth();
+}
+
+void clang_TargetInfo_dispose(CXTargetInfo TargetInfo) {
+ if (!TargetInfo)
+ return;
+
+ delete TargetInfo;
+}
+
+//===----------------------------------------------------------------------===//
+// CXFile Operations.
+//===----------------------------------------------------------------------===//
+
+CXString clang_getFileName(CXFile SFile) {
+ if (!SFile)
+ return cxstring::createNull();
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return cxstring::createRef(FEnt->getName());
+}
+
+time_t clang_getFileTime(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return FEnt->getModificationTime();
+}
+
+CXFile clang_getFile(CXTranslationUnit TU, const char *file_name) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+
+ FileManager &FMgr = CXXUnit->getFileManager();
+ auto File = FMgr.getFile(file_name);
+ if (!File)
+ return nullptr;
+ return const_cast<FileEntry *>(*File);
+}
+
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
+ size_t *size) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+
+ const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
+ FileID fid = SM.translateFile(static_cast<FileEntry *>(file));
+ llvm::Optional<llvm::MemoryBufferRef> buf = SM.getBufferOrNone(fid);
+ if (!buf) {
+ if (size)
+ *size = 0;
+ return nullptr;
+ }
+ if (size)
+ *size = buf->getBufferSize();
+ return buf->getBufferStart();
+}
+
+unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU, CXFile file) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return 0;
+ }
+
+ if (!file)
+ return 0;
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ FileEntry *FEnt = static_cast<FileEntry *>(file);
+ return CXXUnit->getPreprocessor()
+ .getHeaderSearchInfo()
+ .isFileMultipleIncludeGuarded(FEnt);
+}
+
+int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID) {
+ if (!file || !outID)
+ return 1;
+
+ FileEntry *FEnt = static_cast<FileEntry *>(file);
+ const llvm::sys::fs::UniqueID &ID = FEnt->getUniqueID();
+ outID->data[0] = ID.getDevice();
+ outID->data[1] = ID.getFile();
+ outID->data[2] = FEnt->getModificationTime();
+ return 0;
+}
+
+int clang_File_isEqual(CXFile file1, CXFile file2) {
+ if (file1 == file2)
+ return true;
+
+ if (!file1 || !file2)
+ return false;
+
+ FileEntry *FEnt1 = static_cast<FileEntry *>(file1);
+ FileEntry *FEnt2 = static_cast<FileEntry *>(file2);
+ return FEnt1->getUniqueID() == FEnt2->getUniqueID();
+}
+
+CXString clang_File_tryGetRealPathName(CXFile SFile) {
+ if (!SFile)
+ return cxstring::createNull();
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return cxstring::createRef(FEnt->tryGetRealPathName());
+}
+
+//===----------------------------------------------------------------------===//
+// CXCursor Operations.
+//===----------------------------------------------------------------------===//
+
+static const Decl *getDeclFromExpr(const Stmt *E) {
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ return getDeclFromExpr(CE->getSubExpr());
+
+ if (const DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
+ return RefExpr->getDecl();
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ if (const ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
+ return RE->getDecl();
+ if (const ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (PRE->isExplicitProperty())
+ return PRE->getExplicitProperty();
+ // It could be messaging both getter and setter as in:
+ // ++myobj.myprop;
+ // in which case prefer to associate the setter since it is less obvious
+ // from inspecting the source that the setter is going to get called.
+ if (PRE->isMessagingSetter())
+ return PRE->getImplicitPropertySetter();
+ return PRE->getImplicitPropertyGetter();
+ }
+ if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
+ return getDeclFromExpr(POE->getSyntacticForm());
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+ if (Expr *Src = OVE->getSourceExpr())
+ return getDeclFromExpr(Src);
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+ return getDeclFromExpr(CE->getCallee());
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E))
+ if (!CE->isElidable())
+ return CE->getConstructor();
+ if (const CXXInheritedCtorInitExpr *CE =
+ dyn_cast<CXXInheritedCtorInitExpr>(E))
+ return CE->getConstructor();
+ if (const ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
+ return OME->getMethodDecl();
+
+ if (const ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
+ return PE->getProtocol();
+ if (const SubstNonTypeTemplateParmPackExpr *NTTP =
+ dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
+ return NTTP->getParameterPack();
+ if (const SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
+ if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) ||
+ isa<ParmVarDecl>(SizeOfPack->getPack()))
+ return SizeOfPack->getPack();
+
+ return nullptr;
+}
+
+static SourceLocation getLocationFromExpr(const Expr *E) {
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ return getLocationFromExpr(CE->getSubExpr());
+
+ if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
+ return /*FIXME:*/ Msg->getLeftLoc();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getLocation();
+ if (const MemberExpr *Member = dyn_cast<MemberExpr>(E))
+ return Member->getMemberLoc();
+ if (const ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
+ return Ivar->getLocation();
+ if (const SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
+ return SizeOfPack->getPackLoc();
+ if (const ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E))
+ return PropRef->getLocation();
+
+ return E->getBeginLoc();
+}
+
+extern "C" {
+
+unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor,
+ CXClientData client_data) {
+ CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
+ /*VisitPreprocessorLast=*/false);
+ return CursorVis.VisitChildren(parent);
+}
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+#if __has_feature(blocks)
+typedef enum CXChildVisitResult (^CXCursorVisitorBlock)(CXCursor cursor,
+ CXCursor parent);
+
+static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
+ return block(cursor, parent);
+}
+#else
+// If we are compiled with a compiler that doesn't have native blocks support,
+// define and call the block manually, so the
+typedef struct _CXChildVisitResult {
+ void *isa;
+ int flags;
+ int reserved;
+ enum CXChildVisitResult (*invoke)(struct _CXChildVisitResult *, CXCursor,
+ CXCursor);
+} * CXCursorVisitorBlock;
+
+static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
+ return block->invoke(block, cursor, parent);
+}
+#endif
+
+unsigned clang_visitChildrenWithBlock(CXCursor parent,
+ CXCursorVisitorBlock block) {
+ return clang_visitChildren(parent, visitWithBlock, block);
+}
+
+static CXString getDeclSpelling(const Decl *D) {
+ if (!D)
+ return cxstring::createEmpty();
+
+ const NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND) {
+ if (const ObjCPropertyImplDecl *PropImpl =
+ dyn_cast<ObjCPropertyImplDecl>(D))
+ if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
+ return cxstring::createDup(Property->getIdentifier()->getName());
+
+ if (const ImportDecl *ImportD = dyn_cast<ImportDecl>(D))
+ if (Module *Mod = ImportD->getImportedModule())
+ return cxstring::createDup(Mod->getFullModuleName());
+
+ return cxstring::createEmpty();
+ }
+
+ if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return cxstring::createDup(OMD->getSelector().getAsString());
+
+ if (const ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+ // No, this isn't the same as the code below. getIdentifier() is non-virtual
+ // and returns different names. NamedDecl returns the class name and
+ // ObjCCategoryImplDecl returns the category name.
+ return cxstring::createRef(CIMP->getIdentifier()->getNameStart());
+
+ if (isa<UsingDirectiveDecl>(D))
+ return cxstring::createEmpty();
+
+ SmallString<1024> S;
+ llvm::raw_svector_ostream os(S);
+ ND->printName(os);
+
+ return cxstring::createDup(os.str());
+}
+
+CXString clang_getCursorSpelling(CXCursor C) {
+ if (clang_isTranslationUnit(C.kind))
+ return clang_getTranslationUnitSpelling(getCursorTU(C));
+
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ const ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
+ return cxstring::createRef(Super->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCClassRef: {
+ const ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ return cxstring::createRef(Class->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCProtocolRef: {
+ const ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
+ assert(OID && "getCursorSpelling(): Missing protocol decl");
+ return cxstring::createRef(OID->getIdentifier()->getNameStart());
+ }
+ case CXCursor_CXXBaseSpecifier: {
+ const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return cxstring::createDup(B->getType().getAsString());
+ }
+ case CXCursor_TypeRef: {
+ const TypeDecl *Type = getCursorTypeRef(C).first;
+ assert(Type && "Missing type decl");
+
+ return cxstring::createDup(
+ getCursorContext(C).getTypeDeclType(Type).getAsString());
+ }
+ case CXCursor_TemplateRef: {
+ const TemplateDecl *Template = getCursorTemplateRef(C).first;
+ assert(Template && "Missing template decl");
+
+ return cxstring::createDup(Template->getNameAsString());
+ }
+
+ case CXCursor_NamespaceRef: {
+ const NamedDecl *NS = getCursorNamespaceRef(C).first;
+ assert(NS && "Missing namespace decl");
+
+ return cxstring::createDup(NS->getNameAsString());
+ }
+
+ case CXCursor_MemberRef: {
+ const FieldDecl *Field = getCursorMemberRef(C).first;
+ assert(Field && "Missing member decl");
+
+ return cxstring::createDup(Field->getNameAsString());
+ }
+
+ case CXCursor_LabelRef: {
+ const LabelStmt *Label = getCursorLabelRef(C).first;
+ assert(Label && "Missing label");
+
+ return cxstring::createRef(Label->getName());
+ }
+
+ case CXCursor_OverloadedDeclRef: {
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
+ if (const Decl *D = Storage.dyn_cast<const Decl *>()) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ return cxstring::createDup(ND->getNameAsString());
+ return cxstring::createEmpty();
+ }
+ if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
+ return cxstring::createDup(E->getName().getAsString());
+ OverloadedTemplateStorage *Ovl =
+ Storage.get<OverloadedTemplateStorage *>();
+ if (Ovl->size() == 0)
+ return cxstring::createEmpty();
+ return cxstring::createDup((*Ovl->begin())->getNameAsString());
+ }
+
+ case CXCursor_VariableRef: {
+ const VarDecl *Var = getCursorVariableRef(C).first;
+ assert(Var && "Missing variable decl");
+
+ return cxstring::createDup(Var->getNameAsString());
+ }
+
+ default:
+ return cxstring::createRef("<not implemented>");
+ }
+ }
+
+ if (clang_isExpression(C.kind)) {
+ const Expr *E = getCursorExpr(C);
+
+ if (C.kind == CXCursor_ObjCStringLiteral ||
+ C.kind == CXCursor_StringLiteral) {
+ const StringLiteral *SLit;
+ if (const ObjCStringLiteral *OSL = dyn_cast<ObjCStringLiteral>(E)) {
+ SLit = OSL->getString();
+ } else {
+ SLit = cast<StringLiteral>(E);
+ }
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ SLit->outputString(OS);
+ return cxstring::createDup(OS.str());
+ }
+
+ const Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return getDeclSpelling(D);
+ return cxstring::createEmpty();
+ }
+
+ if (clang_isStatement(C.kind)) {
+ const Stmt *S = getCursorStmt(C);
+ if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
+ return cxstring::createRef(Label->getName());
+
+ return cxstring::createEmpty();
+ }
+
+ if (C.kind == CXCursor_MacroExpansion)
+ return cxstring::createRef(
+ getCursorMacroExpansion(C).getName()->getNameStart());
+
+ if (C.kind == CXCursor_MacroDefinition)
+ return cxstring::createRef(
+ getCursorMacroDefinition(C)->getName()->getNameStart());
+
+ if (C.kind == CXCursor_InclusionDirective)
+ return cxstring::createDup(getCursorInclusionDirective(C)->getFileName());
+
+ if (clang_isDeclaration(C.kind))
+ return getDeclSpelling(getCursorDecl(C));
+
+ if (C.kind == CXCursor_AnnotateAttr) {
+ const AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));
+ return cxstring::createDup(AA->getAnnotation());
+ }
+
+ if (C.kind == CXCursor_AsmLabelAttr) {
+ const AsmLabelAttr *AA = cast<AsmLabelAttr>(cxcursor::getCursorAttr(C));
+ return cxstring::createDup(AA->getLabel());
+ }
+
+ if (C.kind == CXCursor_PackedAttr) {
+ return cxstring::createRef("packed");
+ }
+
+ if (C.kind == CXCursor_VisibilityAttr) {
+ const VisibilityAttr *AA = cast<VisibilityAttr>(cxcursor::getCursorAttr(C));
+ switch (AA->getVisibility()) {
+ case VisibilityAttr::VisibilityType::Default:
+ return cxstring::createRef("default");
+ case VisibilityAttr::VisibilityType::Hidden:
+ return cxstring::createRef("hidden");
+ case VisibilityAttr::VisibilityType::Protected:
+ return cxstring::createRef("protected");
+ }
+ llvm_unreachable("unknown visibility type");
+ }
+
+ return cxstring::createEmpty();
+}
+
+CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C, unsigned pieceIndex,
+ unsigned options) {
+ if (clang_Cursor_isNull(C))
+ return clang_getNullRange();
+
+ ASTContext &Ctx = getCursorContext(C);
+
+ if (clang_isStatement(C.kind)) {
+ const Stmt *S = getCursorStmt(C);
+ if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, Label->getIdentLoc());
+ }
+
+ return clang_getNullRange();
+ }
+
+ if (C.kind == CXCursor_ObjCMessageExpr) {
+ if (const ObjCMessageExpr *ME =
+ dyn_cast_or_null<ObjCMessageExpr>(getCursorExpr(C))) {
+ if (pieceIndex >= ME->getNumSelectorLocs())
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, ME->getSelectorLoc(pieceIndex));
+ }
+ }
+
+ if (C.kind == CXCursor_ObjCInstanceMethodDecl ||
+ C.kind == CXCursor_ObjCClassMethodDecl) {
+ if (const ObjCMethodDecl *MD =
+ dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(C))) {
+ if (pieceIndex >= MD->getNumSelectorLocs())
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, MD->getSelectorLoc(pieceIndex));
+ }
+ }
+
+ if (C.kind == CXCursor_ObjCCategoryDecl ||
+ C.kind == CXCursor_ObjCCategoryImplDecl) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ if (const ObjCCategoryDecl *CD =
+ dyn_cast_or_null<ObjCCategoryDecl>(getCursorDecl(C)))
+ return cxloc::translateSourceRange(Ctx, CD->getCategoryNameLoc());
+ if (const ObjCCategoryImplDecl *CID =
+ dyn_cast_or_null<ObjCCategoryImplDecl>(getCursorDecl(C)))
+ return cxloc::translateSourceRange(Ctx, CID->getCategoryNameLoc());
+ }
+
+ if (C.kind == CXCursor_ModuleImportDecl) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ if (const ImportDecl *ImportD =
+ dyn_cast_or_null<ImportDecl>(getCursorDecl(C))) {
+ ArrayRef<SourceLocation> Locs = ImportD->getIdentifierLocs();
+ if (!Locs.empty())
+ return cxloc::translateSourceRange(
+ Ctx, SourceRange(Locs.front(), Locs.back()));
+ }
+ return clang_getNullRange();
+ }
+
+ if (C.kind == CXCursor_CXXMethod || C.kind == CXCursor_Destructor ||
+ C.kind == CXCursor_ConversionFunction ||
+ C.kind == CXCursor_FunctionDecl) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ if (const FunctionDecl *FD =
+ dyn_cast_or_null<FunctionDecl>(getCursorDecl(C))) {
+ DeclarationNameInfo FunctionName = FD->getNameInfo();
+ return cxloc::translateSourceRange(Ctx, FunctionName.getSourceRange());
+ }
+ return clang_getNullRange();
+ }
+
+ // FIXME: A CXCursor_InclusionDirective should give the location of the
+ // filename, but we don't keep track of this.
+
+ // FIXME: A CXCursor_AnnotateAttr should give the location of the annotation
+ // but we don't keep track of this.
+
+ // FIXME: A CXCursor_AsmLabelAttr should give the location of the label
+ // but we don't keep track of this.
+
+ // Default handling, give the location of the cursor.
+
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+
+ CXSourceLocation CXLoc = clang_getCursorLocation(C);
+ SourceLocation Loc = cxloc::translateSourceLocation(CXLoc);
+ return cxloc::translateSourceRange(Ctx, Loc);
+}
+
+CXString clang_Cursor_getMangling(CXCursor C) {
+ if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
+ return cxstring::createEmpty();
+
+ // Mangling only works for functions and variables.
+ const Decl *D = getCursorDecl(C);
+ if (!D || !(isa<FunctionDecl>(D) || isa<VarDecl>(D)))
+ return cxstring::createEmpty();
+
+ ASTContext &Ctx = D->getASTContext();
+ ASTNameGenerator ASTNameGen(Ctx);
+ return cxstring::createDup(ASTNameGen.getName(D));
+}
+
+CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
+ if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
+ return nullptr;
+
+ const Decl *D = getCursorDecl(C);
+ if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
+ return nullptr;
+
+ ASTContext &Ctx = D->getASTContext();
+ ASTNameGenerator ASTNameGen(Ctx);
+ std::vector<std::string> Manglings = ASTNameGen.getAllManglings(D);
+ return cxstring::createSet(Manglings);
+}
+
+CXStringSet *clang_Cursor_getObjCManglings(CXCursor C) {
+ if (clang_isInvalid(C.kind) || !clang_isDeclaration(C.kind))
+ return nullptr;
+
+ const Decl *D = getCursorDecl(C);
+ if (!(isa<ObjCInterfaceDecl>(D) || isa<ObjCImplementationDecl>(D)))
+ return nullptr;
+
+ ASTContext &Ctx = D->getASTContext();
+ ASTNameGenerator ASTNameGen(Ctx);
+ std::vector<std::string> Manglings = ASTNameGen.getAllManglings(D);
+ return cxstring::createSet(Manglings);
+}
+
+CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
+ if (clang_Cursor_isNull(C))
+ return nullptr;
+ return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
+}
+
+void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
+ if (Policy)
+ delete static_cast<PrintingPolicy *>(Policy);
+}
+
+unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property) {
+ if (!Policy)
+ return 0;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ return P->Indentation;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ return P->SuppressSpecifiers;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ return P->SuppressTagKeyword;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ return P->IncludeTagDefinition;
+ case CXPrintingPolicy_SuppressScope:
+ return P->SuppressScope;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ return P->SuppressUnwrittenScope;
+ case CXPrintingPolicy_SuppressInitializers:
+ return P->SuppressInitializers;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ return P->ConstantArraySizeAsWritten;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ return P->AnonymousTagLocations;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ return P->SuppressStrongLifetime;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ return P->SuppressLifetimeQualifiers;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ return P->SuppressTemplateArgsInCXXConstructors;
+ case CXPrintingPolicy_Bool:
+ return P->Bool;
+ case CXPrintingPolicy_Restrict:
+ return P->Restrict;
+ case CXPrintingPolicy_Alignof:
+ return P->Alignof;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ return P->UnderscoreAlignof;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ return P->UseVoidForZeroParams;
+ case CXPrintingPolicy_TerseOutput:
+ return P->TerseOutput;
+ case CXPrintingPolicy_PolishForDeclaration:
+ return P->PolishForDeclaration;
+ case CXPrintingPolicy_Half:
+ return P->Half;
+ case CXPrintingPolicy_MSWChar:
+ return P->MSWChar;
+ case CXPrintingPolicy_IncludeNewlines:
+ return P->IncludeNewlines;
+ case CXPrintingPolicy_MSVCFormatting:
+ return P->MSVCFormatting;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ return P->ConstantsAsWritten;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ return P->SuppressImplicitBase;
+ case CXPrintingPolicy_FullyQualifiedName:
+ return P->FullyQualifiedName;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+ return 0;
+}
+
+void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property,
+ unsigned Value) {
+ if (!Policy)
+ return;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ P->Indentation = Value;
+ return;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ P->SuppressSpecifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ P->SuppressTagKeyword = Value;
+ return;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ P->IncludeTagDefinition = Value;
+ return;
+ case CXPrintingPolicy_SuppressScope:
+ P->SuppressScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ P->SuppressUnwrittenScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressInitializers:
+ P->SuppressInitializers = Value;
+ return;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ P->ConstantArraySizeAsWritten = Value;
+ return;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ P->AnonymousTagLocations = Value;
+ return;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ P->SuppressStrongLifetime = Value;
+ return;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ P->SuppressLifetimeQualifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ P->SuppressTemplateArgsInCXXConstructors = Value;
+ return;
+ case CXPrintingPolicy_Bool:
+ P->Bool = Value;
+ return;
+ case CXPrintingPolicy_Restrict:
+ P->Restrict = Value;
+ return;
+ case CXPrintingPolicy_Alignof:
+ P->Alignof = Value;
+ return;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ P->UnderscoreAlignof = Value;
+ return;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ P->UseVoidForZeroParams = Value;
+ return;
+ case CXPrintingPolicy_TerseOutput:
+ P->TerseOutput = Value;
+ return;
+ case CXPrintingPolicy_PolishForDeclaration:
+ P->PolishForDeclaration = Value;
+ return;
+ case CXPrintingPolicy_Half:
+ P->Half = Value;
+ return;
+ case CXPrintingPolicy_MSWChar:
+ P->MSWChar = Value;
+ return;
+ case CXPrintingPolicy_IncludeNewlines:
+ P->IncludeNewlines = Value;
+ return;
+ case CXPrintingPolicy_MSVCFormatting:
+ P->MSVCFormatting = Value;
+ return;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ P->ConstantsAsWritten = Value;
+ return;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ P->SuppressImplicitBase = Value;
+ return;
+ case CXPrintingPolicy_FullyQualifiedName:
+ P->FullyQualifiedName = Value;
+ return;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+}
+
+CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
+ if (clang_Cursor_isNull(C))
+ return cxstring::createEmpty();
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return cxstring::createEmpty();
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
+ D->print(OS, UserPolicy ? *UserPolicy
+ : getCursorContext(C).getPrintingPolicy());
+
+ return cxstring::createDup(OS.str());
+ }
+
+ return cxstring::createEmpty();
+}
+
+CXString clang_getCursorDisplayName(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getCursorSpelling(C);
+
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return cxstring::createEmpty();
+
+ PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy();
+ if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+ D = FunTmpl->getTemplatedDecl();
+
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *Function;
+ if (Function->getPrimaryTemplate())
+ OS << "<>";
+ OS << "(";
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+ OS << Function->getParamDecl(I)->getType().getAsString(Policy);
+ }
+
+ if (Function->isVariadic()) {
+ if (Function->getNumParams())
+ OS << ", ";
+ OS << "...";
+ }
+ OS << ")";
+ return cxstring::createDup(OS.str());
+ }
+
+ if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *ClassTemplate;
+ OS << "<";
+ TemplateParameterList *Params = ClassTemplate->getTemplateParameters();
+ for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+
+ NamedDecl *Param = Params->getParam(I);
+ if (Param->getIdentifier()) {
+ OS << Param->getIdentifier()->getName();
+ continue;
+ }
+
+ // There is no parameter name, which makes this tricky. Try to come up
+ // with something useful that isn't too long.
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ if (const auto *TC = TTP->getTypeConstraint()) {
+ TC->getConceptNameInfo().printName(OS, Policy);
+ if (TC->hasExplicitTemplateArgs())
+ OS << "<...>";
+ } else
+ OS << (TTP->wasDeclaredWithTypename() ? "typename" : "class");
+ else if (NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(Param))
+ OS << NTTP->getType().getAsString(Policy);
+ else
+ OS << "template<...> class";
+ }
+
+ OS << ">";
+ return cxstring::createDup(OS.str());
+ }
+
+ if (const ClassTemplateSpecializationDecl *ClassSpec =
+ dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ // If the type was explicitly written, use that.
+ if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
+ return cxstring::createDup(TSInfo->getType().getAsString(Policy));
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *ClassSpec;
+ printTemplateArgumentList(
+ OS, ClassSpec->getTemplateArgs().asArray(), Policy,
+ ClassSpec->getSpecializedTemplate()->getTemplateParameters());
+ return cxstring::createDup(OS.str());
+ }
+
+ return clang_getCursorSpelling(C);
+}
+
+CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
+ switch (Kind) {
+ case CXCursor_FunctionDecl:
+ return cxstring::createRef("FunctionDecl");
+ case CXCursor_TypedefDecl:
+ return cxstring::createRef("TypedefDecl");
+ case CXCursor_EnumDecl:
+ return cxstring::createRef("EnumDecl");
+ case CXCursor_EnumConstantDecl:
+ return cxstring::createRef("EnumConstantDecl");
+ case CXCursor_StructDecl:
+ return cxstring::createRef("StructDecl");
+ case CXCursor_UnionDecl:
+ return cxstring::createRef("UnionDecl");
+ case CXCursor_ClassDecl:
+ return cxstring::createRef("ClassDecl");
+ case CXCursor_FieldDecl:
+ return cxstring::createRef("FieldDecl");
+ case CXCursor_VarDecl:
+ return cxstring::createRef("VarDecl");
+ case CXCursor_ParmDecl:
+ return cxstring::createRef("ParmDecl");
+ case CXCursor_ObjCInterfaceDecl:
+ return cxstring::createRef("ObjCInterfaceDecl");
+ case CXCursor_ObjCCategoryDecl:
+ return cxstring::createRef("ObjCCategoryDecl");
+ case CXCursor_ObjCProtocolDecl:
+ return cxstring::createRef("ObjCProtocolDecl");
+ case CXCursor_ObjCPropertyDecl:
+ return cxstring::createRef("ObjCPropertyDecl");
+ case CXCursor_ObjCIvarDecl:
+ return cxstring::createRef("ObjCIvarDecl");
+ case CXCursor_ObjCInstanceMethodDecl:
+ return cxstring::createRef("ObjCInstanceMethodDecl");
+ case CXCursor_ObjCClassMethodDecl:
+ return cxstring::createRef("ObjCClassMethodDecl");
+ case CXCursor_ObjCImplementationDecl:
+ return cxstring::createRef("ObjCImplementationDecl");
+ case CXCursor_ObjCCategoryImplDecl:
+ return cxstring::createRef("ObjCCategoryImplDecl");
+ case CXCursor_CXXMethod:
+ return cxstring::createRef("CXXMethod");
+ case CXCursor_UnexposedDecl:
+ return cxstring::createRef("UnexposedDecl");
+ case CXCursor_ObjCSuperClassRef:
+ return cxstring::createRef("ObjCSuperClassRef");
+ case CXCursor_ObjCProtocolRef:
+ return cxstring::createRef("ObjCProtocolRef");
+ case CXCursor_ObjCClassRef:
+ return cxstring::createRef("ObjCClassRef");
+ case CXCursor_TypeRef:
+ return cxstring::createRef("TypeRef");
+ case CXCursor_TemplateRef:
+ return cxstring::createRef("TemplateRef");
+ case CXCursor_NamespaceRef:
+ return cxstring::createRef("NamespaceRef");
+ case CXCursor_MemberRef:
+ return cxstring::createRef("MemberRef");
+ case CXCursor_LabelRef:
+ return cxstring::createRef("LabelRef");
+ case CXCursor_OverloadedDeclRef:
+ return cxstring::createRef("OverloadedDeclRef");
+ case CXCursor_VariableRef:
+ return cxstring::createRef("VariableRef");
+ case CXCursor_IntegerLiteral:
+ return cxstring::createRef("IntegerLiteral");
+ case CXCursor_FixedPointLiteral:
+ return cxstring::createRef("FixedPointLiteral");
+ case CXCursor_FloatingLiteral:
+ return cxstring::createRef("FloatingLiteral");
+ case CXCursor_ImaginaryLiteral:
+ return cxstring::createRef("ImaginaryLiteral");
+ case CXCursor_StringLiteral:
+ return cxstring::createRef("StringLiteral");
+ case CXCursor_CharacterLiteral:
+ return cxstring::createRef("CharacterLiteral");
+ case CXCursor_ParenExpr:
+ return cxstring::createRef("ParenExpr");
+ case CXCursor_UnaryOperator:
+ return cxstring::createRef("UnaryOperator");
+ case CXCursor_ArraySubscriptExpr:
+ return cxstring::createRef("ArraySubscriptExpr");
+ case CXCursor_OMPArraySectionExpr:
+ return cxstring::createRef("OMPArraySectionExpr");
+ case CXCursor_OMPArrayShapingExpr:
+ return cxstring::createRef("OMPArrayShapingExpr");
+ case CXCursor_OMPIteratorExpr:
+ return cxstring::createRef("OMPIteratorExpr");
+ case CXCursor_BinaryOperator:
+ return cxstring::createRef("BinaryOperator");
+ case CXCursor_CompoundAssignOperator:
+ return cxstring::createRef("CompoundAssignOperator");
+ case CXCursor_ConditionalOperator:
+ return cxstring::createRef("ConditionalOperator");
+ case CXCursor_CStyleCastExpr:
+ return cxstring::createRef("CStyleCastExpr");
+ case CXCursor_CompoundLiteralExpr:
+ return cxstring::createRef("CompoundLiteralExpr");
+ case CXCursor_InitListExpr:
+ return cxstring::createRef("InitListExpr");
+ case CXCursor_AddrLabelExpr:
+ return cxstring::createRef("AddrLabelExpr");
+ case CXCursor_StmtExpr:
+ return cxstring::createRef("StmtExpr");
+ case CXCursor_GenericSelectionExpr:
+ return cxstring::createRef("GenericSelectionExpr");
+ case CXCursor_GNUNullExpr:
+ return cxstring::createRef("GNUNullExpr");
+ case CXCursor_CXXStaticCastExpr:
+ return cxstring::createRef("CXXStaticCastExpr");
+ case CXCursor_CXXDynamicCastExpr:
+ return cxstring::createRef("CXXDynamicCastExpr");
+ case CXCursor_CXXReinterpretCastExpr:
+ return cxstring::createRef("CXXReinterpretCastExpr");
+ case CXCursor_CXXConstCastExpr:
+ return cxstring::createRef("CXXConstCastExpr");
+ case CXCursor_CXXFunctionalCastExpr:
+ return cxstring::createRef("CXXFunctionalCastExpr");
+ case CXCursor_CXXAddrspaceCastExpr:
+ return cxstring::createRef("CXXAddrspaceCastExpr");
+ case CXCursor_CXXTypeidExpr:
+ return cxstring::createRef("CXXTypeidExpr");
+ case CXCursor_CXXBoolLiteralExpr:
+ return cxstring::createRef("CXXBoolLiteralExpr");
+ case CXCursor_CXXNullPtrLiteralExpr:
+ return cxstring::createRef("CXXNullPtrLiteralExpr");
+ case CXCursor_CXXThisExpr:
+ return cxstring::createRef("CXXThisExpr");
+ case CXCursor_CXXThrowExpr:
+ return cxstring::createRef("CXXThrowExpr");
+ case CXCursor_CXXNewExpr:
+ return cxstring::createRef("CXXNewExpr");
+ case CXCursor_CXXDeleteExpr:
+ return cxstring::createRef("CXXDeleteExpr");
+ case CXCursor_UnaryExpr:
+ return cxstring::createRef("UnaryExpr");
+ case CXCursor_ObjCStringLiteral:
+ return cxstring::createRef("ObjCStringLiteral");
+ case CXCursor_ObjCBoolLiteralExpr:
+ return cxstring::createRef("ObjCBoolLiteralExpr");
+ case CXCursor_ObjCAvailabilityCheckExpr:
+ return cxstring::createRef("ObjCAvailabilityCheckExpr");
+ case CXCursor_ObjCSelfExpr:
+ return cxstring::createRef("ObjCSelfExpr");
+ case CXCursor_ObjCEncodeExpr:
+ return cxstring::createRef("ObjCEncodeExpr");
+ case CXCursor_ObjCSelectorExpr:
+ return cxstring::createRef("ObjCSelectorExpr");
+ case CXCursor_ObjCProtocolExpr:
+ return cxstring::createRef("ObjCProtocolExpr");
+ case CXCursor_ObjCBridgedCastExpr:
+ return cxstring::createRef("ObjCBridgedCastExpr");
+ case CXCursor_BlockExpr:
+ return cxstring::createRef("BlockExpr");
+ case CXCursor_PackExpansionExpr:
+ return cxstring::createRef("PackExpansionExpr");
+ case CXCursor_SizeOfPackExpr:
+ return cxstring::createRef("SizeOfPackExpr");
+ case CXCursor_LambdaExpr:
+ return cxstring::createRef("LambdaExpr");
+ case CXCursor_UnexposedExpr:
+ return cxstring::createRef("UnexposedExpr");
+ case CXCursor_DeclRefExpr:
+ return cxstring::createRef("DeclRefExpr");
+ case CXCursor_MemberRefExpr:
+ return cxstring::createRef("MemberRefExpr");
+ case CXCursor_CallExpr:
+ return cxstring::createRef("CallExpr");
+ case CXCursor_ObjCMessageExpr:
+ return cxstring::createRef("ObjCMessageExpr");
+ case CXCursor_BuiltinBitCastExpr:
+ return cxstring::createRef("BuiltinBitCastExpr");
+ case CXCursor_UnexposedStmt:
+ return cxstring::createRef("UnexposedStmt");
+ case CXCursor_DeclStmt:
+ return cxstring::createRef("DeclStmt");
+ case CXCursor_LabelStmt:
+ return cxstring::createRef("LabelStmt");
+ case CXCursor_CompoundStmt:
+ return cxstring::createRef("CompoundStmt");
+ case CXCursor_CaseStmt:
+ return cxstring::createRef("CaseStmt");
+ case CXCursor_DefaultStmt:
+ return cxstring::createRef("DefaultStmt");
+ case CXCursor_IfStmt:
+ return cxstring::createRef("IfStmt");
+ case CXCursor_SwitchStmt:
+ return cxstring::createRef("SwitchStmt");
+ case CXCursor_WhileStmt:
+ return cxstring::createRef("WhileStmt");
+ case CXCursor_DoStmt:
+ return cxstring::createRef("DoStmt");
+ case CXCursor_ForStmt:
+ return cxstring::createRef("ForStmt");
+ case CXCursor_GotoStmt:
+ return cxstring::createRef("GotoStmt");
+ case CXCursor_IndirectGotoStmt:
+ return cxstring::createRef("IndirectGotoStmt");
+ case CXCursor_ContinueStmt:
+ return cxstring::createRef("ContinueStmt");
+ case CXCursor_BreakStmt:
+ return cxstring::createRef("BreakStmt");
+ case CXCursor_ReturnStmt:
+ return cxstring::createRef("ReturnStmt");
+ case CXCursor_GCCAsmStmt:
+ return cxstring::createRef("GCCAsmStmt");
+ case CXCursor_MSAsmStmt:
+ return cxstring::createRef("MSAsmStmt");
+ case CXCursor_ObjCAtTryStmt:
+ return cxstring::createRef("ObjCAtTryStmt");
+ case CXCursor_ObjCAtCatchStmt:
+ return cxstring::createRef("ObjCAtCatchStmt");
+ case CXCursor_ObjCAtFinallyStmt:
+ return cxstring::createRef("ObjCAtFinallyStmt");
+ case CXCursor_ObjCAtThrowStmt:
+ return cxstring::createRef("ObjCAtThrowStmt");
+ case CXCursor_ObjCAtSynchronizedStmt:
+ return cxstring::createRef("ObjCAtSynchronizedStmt");
+ case CXCursor_ObjCAutoreleasePoolStmt:
+ return cxstring::createRef("ObjCAutoreleasePoolStmt");
+ case CXCursor_ObjCForCollectionStmt:
+ return cxstring::createRef("ObjCForCollectionStmt");
+ case CXCursor_CXXCatchStmt:
+ return cxstring::createRef("CXXCatchStmt");
+ case CXCursor_CXXTryStmt:
+ return cxstring::createRef("CXXTryStmt");
+ case CXCursor_CXXForRangeStmt:
+ return cxstring::createRef("CXXForRangeStmt");
+ case CXCursor_SEHTryStmt:
+ return cxstring::createRef("SEHTryStmt");
+ case CXCursor_SEHExceptStmt:
+ return cxstring::createRef("SEHExceptStmt");
+ case CXCursor_SEHFinallyStmt:
+ return cxstring::createRef("SEHFinallyStmt");
+ case CXCursor_SEHLeaveStmt:
+ return cxstring::createRef("SEHLeaveStmt");
+ case CXCursor_NullStmt:
+ return cxstring::createRef("NullStmt");
+ case CXCursor_InvalidFile:
+ return cxstring::createRef("InvalidFile");
+ case CXCursor_InvalidCode:
+ return cxstring::createRef("InvalidCode");
+ case CXCursor_NoDeclFound:
+ return cxstring::createRef("NoDeclFound");
+ case CXCursor_NotImplemented:
+ return cxstring::createRef("NotImplemented");
+ case CXCursor_TranslationUnit:
+ return cxstring::createRef("TranslationUnit");
+ case CXCursor_UnexposedAttr:
+ return cxstring::createRef("UnexposedAttr");
+ case CXCursor_IBActionAttr:
+ return cxstring::createRef("attribute(ibaction)");
+ case CXCursor_IBOutletAttr:
+ return cxstring::createRef("attribute(iboutlet)");
+ case CXCursor_IBOutletCollectionAttr:
+ return cxstring::createRef("attribute(iboutletcollection)");
+ case CXCursor_CXXFinalAttr:
+ return cxstring::createRef("attribute(final)");
+ case CXCursor_CXXOverrideAttr:
+ return cxstring::createRef("attribute(override)");
+ case CXCursor_AnnotateAttr:
+ return cxstring::createRef("attribute(annotate)");
+ case CXCursor_AsmLabelAttr:
+ return cxstring::createRef("asm label");
+ case CXCursor_PackedAttr:
+ return cxstring::createRef("attribute(packed)");
+ case CXCursor_PureAttr:
+ return cxstring::createRef("attribute(pure)");
+ case CXCursor_ConstAttr:
+ return cxstring::createRef("attribute(const)");
+ case CXCursor_NoDuplicateAttr:
+ return cxstring::createRef("attribute(noduplicate)");
+ case CXCursor_CUDAConstantAttr:
+ return cxstring::createRef("attribute(constant)");
+ case CXCursor_CUDADeviceAttr:
+ return cxstring::createRef("attribute(device)");
+ case CXCursor_CUDAGlobalAttr:
+ return cxstring::createRef("attribute(global)");
+ case CXCursor_CUDAHostAttr:
+ return cxstring::createRef("attribute(host)");
+ case CXCursor_CUDASharedAttr:
+ return cxstring::createRef("attribute(shared)");
+ case CXCursor_VisibilityAttr:
+ return cxstring::createRef("attribute(visibility)");
+ case CXCursor_DLLExport:
+ return cxstring::createRef("attribute(dllexport)");
+ case CXCursor_DLLImport:
+ return cxstring::createRef("attribute(dllimport)");
+ case CXCursor_NSReturnsRetained:
+ return cxstring::createRef("attribute(ns_returns_retained)");
+ case CXCursor_NSReturnsNotRetained:
+ return cxstring::createRef("attribute(ns_returns_not_retained)");
+ case CXCursor_NSReturnsAutoreleased:
+ return cxstring::createRef("attribute(ns_returns_autoreleased)");
+ case CXCursor_NSConsumesSelf:
+ return cxstring::createRef("attribute(ns_consumes_self)");
+ case CXCursor_NSConsumed:
+ return cxstring::createRef("attribute(ns_consumed)");
+ case CXCursor_ObjCException:
+ return cxstring::createRef("attribute(objc_exception)");
+ case CXCursor_ObjCNSObject:
+ return cxstring::createRef("attribute(NSObject)");
+ case CXCursor_ObjCIndependentClass:
+ return cxstring::createRef("attribute(objc_independent_class)");
+ case CXCursor_ObjCPreciseLifetime:
+ return cxstring::createRef("attribute(objc_precise_lifetime)");
+ case CXCursor_ObjCReturnsInnerPointer:
+ return cxstring::createRef("attribute(objc_returns_inner_pointer)");
+ case CXCursor_ObjCRequiresSuper:
+ return cxstring::createRef("attribute(objc_requires_super)");
+ case CXCursor_ObjCRootClass:
+ return cxstring::createRef("attribute(objc_root_class)");
+ case CXCursor_ObjCSubclassingRestricted:
+ return cxstring::createRef("attribute(objc_subclassing_restricted)");
+ case CXCursor_ObjCExplicitProtocolImpl:
+ return cxstring::createRef(
+ "attribute(objc_protocol_requires_explicit_implementation)");
+ case CXCursor_ObjCDesignatedInitializer:
+ return cxstring::createRef("attribute(objc_designated_initializer)");
+ case CXCursor_ObjCRuntimeVisible:
+ return cxstring::createRef("attribute(objc_runtime_visible)");
+ case CXCursor_ObjCBoxable:
+ return cxstring::createRef("attribute(objc_boxable)");
+ case CXCursor_FlagEnum:
+ return cxstring::createRef("attribute(flag_enum)");
+ case CXCursor_PreprocessingDirective:
+ return cxstring::createRef("preprocessing directive");
+ case CXCursor_MacroDefinition:
+ return cxstring::createRef("macro definition");
+ case CXCursor_MacroExpansion:
+ return cxstring::createRef("macro expansion");
+ case CXCursor_InclusionDirective:
+ return cxstring::createRef("inclusion directive");
+ case CXCursor_Namespace:
+ return cxstring::createRef("Namespace");
+ case CXCursor_LinkageSpec:
+ return cxstring::createRef("LinkageSpec");
+ case CXCursor_CXXBaseSpecifier:
+ return cxstring::createRef("C++ base class specifier");
+ case CXCursor_Constructor:
+ return cxstring::createRef("CXXConstructor");
+ case CXCursor_Destructor:
+ return cxstring::createRef("CXXDestructor");
+ case CXCursor_ConversionFunction:
+ return cxstring::createRef("CXXConversion");
+ case CXCursor_TemplateTypeParameter:
+ return cxstring::createRef("TemplateTypeParameter");
+ case CXCursor_NonTypeTemplateParameter:
+ return cxstring::createRef("NonTypeTemplateParameter");
+ case CXCursor_TemplateTemplateParameter:
+ return cxstring::createRef("TemplateTemplateParameter");
+ case CXCursor_FunctionTemplate:
+ return cxstring::createRef("FunctionTemplate");
+ case CXCursor_ClassTemplate:
+ return cxstring::createRef("ClassTemplate");
+ case CXCursor_ClassTemplatePartialSpecialization:
+ return cxstring::createRef("ClassTemplatePartialSpecialization");
+ case CXCursor_NamespaceAlias:
+ return cxstring::createRef("NamespaceAlias");
+ case CXCursor_UsingDirective:
+ return cxstring::createRef("UsingDirective");
+ case CXCursor_UsingDeclaration:
+ return cxstring::createRef("UsingDeclaration");
+ case CXCursor_TypeAliasDecl:
+ return cxstring::createRef("TypeAliasDecl");
+ case CXCursor_ObjCSynthesizeDecl:
+ return cxstring::createRef("ObjCSynthesizeDecl");
+ case CXCursor_ObjCDynamicDecl:
+ return cxstring::createRef("ObjCDynamicDecl");
+ case CXCursor_CXXAccessSpecifier:
+ return cxstring::createRef("CXXAccessSpecifier");
+ case CXCursor_ModuleImportDecl:
+ return cxstring::createRef("ModuleImport");
+ case CXCursor_OMPCanonicalLoop:
+ return cxstring::createRef("OMPCanonicalLoop");
+ case CXCursor_OMPMetaDirective:
+ return cxstring::createRef("OMPMetaDirective");
+ case CXCursor_OMPParallelDirective:
+ return cxstring::createRef("OMPParallelDirective");
+ case CXCursor_OMPSimdDirective:
+ return cxstring::createRef("OMPSimdDirective");
+ case CXCursor_OMPTileDirective:
+ return cxstring::createRef("OMPTileDirective");
+ case CXCursor_OMPUnrollDirective:
+ return cxstring::createRef("OMPUnrollDirective");
+ case CXCursor_OMPForDirective:
+ return cxstring::createRef("OMPForDirective");
+ case CXCursor_OMPForSimdDirective:
+ return cxstring::createRef("OMPForSimdDirective");
+ case CXCursor_OMPSectionsDirective:
+ return cxstring::createRef("OMPSectionsDirective");
+ case CXCursor_OMPSectionDirective:
+ return cxstring::createRef("OMPSectionDirective");
+ case CXCursor_OMPSingleDirective:
+ return cxstring::createRef("OMPSingleDirective");
+ case CXCursor_OMPMasterDirective:
+ return cxstring::createRef("OMPMasterDirective");
+ case CXCursor_OMPCriticalDirective:
+ return cxstring::createRef("OMPCriticalDirective");
+ case CXCursor_OMPParallelForDirective:
+ return cxstring::createRef("OMPParallelForDirective");
+ case CXCursor_OMPParallelForSimdDirective:
+ return cxstring::createRef("OMPParallelForSimdDirective");
+ case CXCursor_OMPParallelMasterDirective:
+ return cxstring::createRef("OMPParallelMasterDirective");
+ case CXCursor_OMPParallelSectionsDirective:
+ return cxstring::createRef("OMPParallelSectionsDirective");
+ case CXCursor_OMPTaskDirective:
+ return cxstring::createRef("OMPTaskDirective");
+ case CXCursor_OMPTaskyieldDirective:
+ return cxstring::createRef("OMPTaskyieldDirective");
+ case CXCursor_OMPBarrierDirective:
+ return cxstring::createRef("OMPBarrierDirective");
+ case CXCursor_OMPTaskwaitDirective:
+ return cxstring::createRef("OMPTaskwaitDirective");
+ case CXCursor_OMPTaskgroupDirective:
+ return cxstring::createRef("OMPTaskgroupDirective");
+ case CXCursor_OMPFlushDirective:
+ return cxstring::createRef("OMPFlushDirective");
+ case CXCursor_OMPDepobjDirective:
+ return cxstring::createRef("OMPDepobjDirective");
+ case CXCursor_OMPScanDirective:
+ return cxstring::createRef("OMPScanDirective");
+ case CXCursor_OMPOrderedDirective:
+ return cxstring::createRef("OMPOrderedDirective");
+ case CXCursor_OMPAtomicDirective:
+ return cxstring::createRef("OMPAtomicDirective");
+ case CXCursor_OMPTargetDirective:
+ return cxstring::createRef("OMPTargetDirective");
+ case CXCursor_OMPTargetDataDirective:
+ return cxstring::createRef("OMPTargetDataDirective");
+ case CXCursor_OMPTargetEnterDataDirective:
+ return cxstring::createRef("OMPTargetEnterDataDirective");
+ case CXCursor_OMPTargetExitDataDirective:
+ return cxstring::createRef("OMPTargetExitDataDirective");
+ case CXCursor_OMPTargetParallelDirective:
+ return cxstring::createRef("OMPTargetParallelDirective");
+ case CXCursor_OMPTargetParallelForDirective:
+ return cxstring::createRef("OMPTargetParallelForDirective");
+ case CXCursor_OMPTargetUpdateDirective:
+ return cxstring::createRef("OMPTargetUpdateDirective");
+ case CXCursor_OMPTeamsDirective:
+ return cxstring::createRef("OMPTeamsDirective");
+ case CXCursor_OMPCancellationPointDirective:
+ return cxstring::createRef("OMPCancellationPointDirective");
+ case CXCursor_OMPCancelDirective:
+ return cxstring::createRef("OMPCancelDirective");
+ case CXCursor_OMPTaskLoopDirective:
+ return cxstring::createRef("OMPTaskLoopDirective");
+ case CXCursor_OMPTaskLoopSimdDirective:
+ return cxstring::createRef("OMPTaskLoopSimdDirective");
+ case CXCursor_OMPMasterTaskLoopDirective:
+ return cxstring::createRef("OMPMasterTaskLoopDirective");
+ case CXCursor_OMPMasterTaskLoopSimdDirective:
+ return cxstring::createRef("OMPMasterTaskLoopSimdDirective");
+ case CXCursor_OMPParallelMasterTaskLoopDirective:
+ return cxstring::createRef("OMPParallelMasterTaskLoopDirective");
+ case CXCursor_OMPParallelMasterTaskLoopSimdDirective:
+ return cxstring::createRef("OMPParallelMasterTaskLoopSimdDirective");
+ case CXCursor_OMPDistributeDirective:
+ return cxstring::createRef("OMPDistributeDirective");
+ case CXCursor_OMPDistributeParallelForDirective:
+ return cxstring::createRef("OMPDistributeParallelForDirective");
+ case CXCursor_OMPDistributeParallelForSimdDirective:
+ return cxstring::createRef("OMPDistributeParallelForSimdDirective");
+ case CXCursor_OMPDistributeSimdDirective:
+ return cxstring::createRef("OMPDistributeSimdDirective");
+ case CXCursor_OMPTargetParallelForSimdDirective:
+ return cxstring::createRef("OMPTargetParallelForSimdDirective");
+ case CXCursor_OMPTargetSimdDirective:
+ return cxstring::createRef("OMPTargetSimdDirective");
+ case CXCursor_OMPTeamsDistributeDirective:
+ return cxstring::createRef("OMPTeamsDistributeDirective");
+ case CXCursor_OMPTeamsDistributeSimdDirective:
+ return cxstring::createRef("OMPTeamsDistributeSimdDirective");
+ case CXCursor_OMPTeamsDistributeParallelForSimdDirective:
+ return cxstring::createRef("OMPTeamsDistributeParallelForSimdDirective");
+ case CXCursor_OMPTeamsDistributeParallelForDirective:
+ return cxstring::createRef("OMPTeamsDistributeParallelForDirective");
+ case CXCursor_OMPTargetTeamsDirective:
+ return cxstring::createRef("OMPTargetTeamsDirective");
+ case CXCursor_OMPTargetTeamsDistributeDirective:
+ return cxstring::createRef("OMPTargetTeamsDistributeDirective");
+ case CXCursor_OMPTargetTeamsDistributeParallelForDirective:
+ return cxstring::createRef("OMPTargetTeamsDistributeParallelForDirective");
+ case CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective:
+ return cxstring::createRef(
+ "OMPTargetTeamsDistributeParallelForSimdDirective");
+ case CXCursor_OMPTargetTeamsDistributeSimdDirective:
+ return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective");
+ case CXCursor_OMPInteropDirective:
+ return cxstring::createRef("OMPInteropDirective");
+ case CXCursor_OMPDispatchDirective:
+ return cxstring::createRef("OMPDispatchDirective");
+ case CXCursor_OMPMaskedDirective:
+ return cxstring::createRef("OMPMaskedDirective");
+ case CXCursor_OMPGenericLoopDirective:
+ return cxstring::createRef("OMPGenericLoopDirective");
+ case CXCursor_OverloadCandidate:
+ return cxstring::createRef("OverloadCandidate");
+ case CXCursor_TypeAliasTemplateDecl:
+ return cxstring::createRef("TypeAliasTemplateDecl");
+ case CXCursor_StaticAssert:
+ return cxstring::createRef("StaticAssert");
+ case CXCursor_FriendDecl:
+ return cxstring::createRef("FriendDecl");
+ case CXCursor_ConvergentAttr:
+ return cxstring::createRef("attribute(convergent)");
+ case CXCursor_WarnUnusedAttr:
+ return cxstring::createRef("attribute(warn_unused)");
+ case CXCursor_WarnUnusedResultAttr:
+ return cxstring::createRef("attribute(warn_unused_result)");
+ case CXCursor_AlignedAttr:
+ return cxstring::createRef("attribute(aligned)");
+ }
+
+ llvm_unreachable("Unhandled CXCursorKind");
+}
+
+struct GetCursorData {
+ SourceLocation TokenBeginLoc;
+ bool PointsAtMacroArgExpansion;
+ bool VisitedObjCPropertyImplDecl;
+ SourceLocation VisitedDeclaratorDeclStartLoc;
+ CXCursor &BestCursor;
+
+ GetCursorData(SourceManager &SM, SourceLocation tokenBegin,
+ CXCursor &outputCursor)
+ : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) {
+ PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin);
+ VisitedObjCPropertyImplDecl = false;
+ }
+};
+
+static enum CXChildVisitResult
+GetCursorVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
+ GetCursorData *Data = static_cast<GetCursorData *>(client_data);
+ CXCursor *BestCursor = &Data->BestCursor;
+
+ // If we point inside a macro argument we should provide info of what the
+ // token is so use the actual cursor, don't replace it with a macro expansion
+ // cursor.
+ if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion)
+ return CXChildVisit_Recurse;
+
+ if (clang_isDeclaration(cursor.kind)) {
+ // Avoid having the implicit methods override the property decls.
+ if (const ObjCMethodDecl *MD =
+ dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+ if (MD->isImplicit())
+ return CXChildVisit_Break;
+
+ } else if (const ObjCInterfaceDecl *ID =
+ dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(cursor))) {
+ // Check that when we have multiple @class references in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // @class Foo, Bar;
+ // source ranges for both start at '@', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (BestCursor->kind == CXCursor_ObjCInterfaceDecl ||
+ BestCursor->kind == CXCursor_ObjCClassRef)
+ if (const ObjCInterfaceDecl *PrevID =
+ dyn_cast_or_null<ObjCInterfaceDecl>(
+ getCursorDecl(*BestCursor))) {
+ if (PrevID != ID && !PrevID->isThisDeclarationADefinition() &&
+ !ID->isThisDeclarationADefinition())
+ return CXChildVisit_Break;
+ }
+
+ } else if (const DeclaratorDecl *DD =
+ dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) {
+ SourceLocation StartLoc = DD->getSourceRange().getBegin();
+ // Check that when we have multiple declarators in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // int Foo, Bar;
+ // source ranges for both start at 'int', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedDeclaratorDeclStartLoc == StartLoc)
+ return CXChildVisit_Break;
+ Data->VisitedDeclaratorDeclStartLoc = StartLoc;
+
+ } else if (const ObjCPropertyImplDecl *PropImp =
+ dyn_cast_or_null<ObjCPropertyImplDecl>(
+ getCursorDecl(cursor))) {
+ (void)PropImp;
+ // Check that when we have multiple @synthesize in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // @synthesize Foo, Bar;
+ // source ranges for both start at '@', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedObjCPropertyImplDecl)
+ return CXChildVisit_Break;
+ Data->VisitedObjCPropertyImplDecl = true;
+ }
+ }
+
+ if (clang_isExpression(cursor.kind) &&
+ clang_isDeclaration(BestCursor->kind)) {
+ if (const Decl *D = getCursorDecl(*BestCursor)) {
+ // Avoid having the cursor of an expression replace the declaration cursor
+ // when the expression source range overlaps the declaration range.
+ // This can happen for C++ constructor expressions whose range generally
+ // include the variable declaration, e.g.:
+ // MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl
+ // cursor.
+ if (D->getLocation().isValid() && Data->TokenBeginLoc.isValid() &&
+ D->getLocation() == Data->TokenBeginLoc)
+ return CXChildVisit_Break;
+ }
+ }
+
+ // If our current best cursor is the construction of a temporary object,
+ // don't replace that cursor with a type reference, because we want
+ // clang_getCursor() to point at the constructor.
+ if (clang_isExpression(BestCursor->kind) &&
+ isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
+ cursor.kind == CXCursor_TypeRef) {
+ // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it
+ // as having the actual point on the type reference.
+ *BestCursor = getTypeRefedCallExprCursor(*BestCursor);
+ return CXChildVisit_Recurse;
+ }
+
+ // If we already have an Objective-C superclass reference, don't
+ // update it further.
+ if (BestCursor->kind == CXCursor_ObjCSuperClassRef)
+ return CXChildVisit_Break;
+
+ *BestCursor = cursor;
+ return CXChildVisit_Recurse;
+}
+
+CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullCursor();
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
+ CXCursor Result = cxcursor::getCursor(TU, SLoc);
+
+ LOG_FUNC_SECTION {
+ CXFile SearchFile;
+ unsigned SearchLine, SearchColumn;
+ CXFile ResultFile;
+ unsigned ResultLine, ResultColumn;
+ CXString SearchFileName, ResultFileName, KindSpelling, USR;
+ const char *IsDef = clang_isCursorDefinition(Result) ? " (Definition)" : "";
+ CXSourceLocation ResultLoc = clang_getCursorLocation(Result);
+
+ clang_getFileLocation(Loc, &SearchFile, &SearchLine, &SearchColumn,
+ nullptr);
+ clang_getFileLocation(ResultLoc, &ResultFile, &ResultLine, &ResultColumn,
+ nullptr);
+ SearchFileName = clang_getFileName(SearchFile);
+ ResultFileName = clang_getFileName(ResultFile);
+ KindSpelling = clang_getCursorKindSpelling(Result.kind);
+ USR = clang_getCursorUSR(Result);
+ *Log << llvm::format("(%s:%d:%d) = %s", clang_getCString(SearchFileName),
+ SearchLine, SearchColumn,
+ clang_getCString(KindSpelling))
+ << llvm::format("(%s:%d:%d):%s%s", clang_getCString(ResultFileName),
+ ResultLine, ResultColumn, clang_getCString(USR),
+ IsDef);
+ clang_disposeString(SearchFileName);
+ clang_disposeString(ResultFileName);
+ clang_disposeString(KindSpelling);
+ clang_disposeString(USR);
+
+ CXCursor Definition = clang_getCursorDefinition(Result);
+ if (!clang_equalCursors(Definition, clang_getNullCursor())) {
+ CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);
+ CXString DefinitionKindSpelling =
+ clang_getCursorKindSpelling(Definition.kind);
+ CXFile DefinitionFile;
+ unsigned DefinitionLine, DefinitionColumn;
+ clang_getFileLocation(DefinitionLoc, &DefinitionFile, &DefinitionLine,
+ &DefinitionColumn, nullptr);
+ CXString DefinitionFileName = clang_getFileName(DefinitionFile);
+ *Log << llvm::format(" -> %s(%s:%d:%d)",
+ clang_getCString(DefinitionKindSpelling),
+ clang_getCString(DefinitionFileName), DefinitionLine,
+ DefinitionColumn);
+ clang_disposeString(DefinitionFileName);
+ clang_disposeString(DefinitionKindSpelling);
+ }
+ }
+
+ return Result;
+}
+
+CXCursor clang_getNullCursor(void) {
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
+}
+
+unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
+ // Clear out the "FirstInDeclGroup" part in a declaration cursor, since we
+ // can't set consistently. For example, when visiting a DeclStmt we will set
+ // it but we don't set it on the result of clang_getCursorDefinition for
+ // a reference of the same declaration.
+ // FIXME: Setting "FirstInDeclGroup" in CXCursors is a hack that only works
+ // when visiting a DeclStmt currently, the AST should be enhanced to be able
+ // to provide that kind of info.
+ if (clang_isDeclaration(X.kind))
+ X.data[1] = nullptr;
+ if (clang_isDeclaration(Y.kind))
+ Y.data[1] = nullptr;
+
+ return X == Y;
+}
+
+unsigned clang_hashCursor(CXCursor C) {
+ unsigned Index = 0;
+ if (clang_isExpression(C.kind) || clang_isStatement(C.kind))
+ Index = 1;
+
+ return llvm::DenseMapInfo<std::pair<unsigned, const void *>>::getHashValue(
+ std::make_pair(C.kind, C.data[Index]));
+}
+
+unsigned clang_isInvalid(enum CXCursorKind K) {
+ return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
+}
+
+unsigned clang_isDeclaration(enum CXCursorKind K) {
+ return (K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl) ||
+ (K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
+}
+
+unsigned clang_isInvalidDeclaration(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ if (const Decl *D = getCursorDecl(C))
+ return D->isInvalidDecl();
+ }
+
+ return 0;
+}
+
+unsigned clang_isReference(enum CXCursorKind K) {
+ return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
+}
+
+unsigned clang_isExpression(enum CXCursorKind K) {
+ return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
+}
+
+unsigned clang_isStatement(enum CXCursorKind K) {
+ return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
+}
+
+unsigned clang_isAttribute(enum CXCursorKind K) {
+ return K >= CXCursor_FirstAttr && K <= CXCursor_LastAttr;
+}
+
+unsigned clang_isTranslationUnit(enum CXCursorKind K) {
+ return K == CXCursor_TranslationUnit;
+}
+
+unsigned clang_isPreprocessing(enum CXCursorKind K) {
+ return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
+}
+
+unsigned clang_isUnexposed(enum CXCursorKind K) {
+ switch (K) {
+ case CXCursor_UnexposedDecl:
+ case CXCursor_UnexposedExpr:
+ case CXCursor_UnexposedStmt:
+ case CXCursor_UnexposedAttr:
+ return true;
+ default:
+ return false;
+ }
+}
+
+CXCursorKind clang_getCursorKind(CXCursor C) { return C.kind; }
+
+CXSourceLocation clang_getCursorLocation(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<const ObjCInterfaceDecl *, SourceLocation> P =
+ getCursorObjCSuperClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<const ObjCProtocolDecl *, SourceLocation> P =
+ getCursorObjCProtocolRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<const ObjCInterfaceDecl *, SourceLocation> P =
+ getCursorObjCClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<const TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TemplateRef: {
+ std::pair<const TemplateDecl *, SourceLocation> P =
+ getCursorTemplateRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_NamespaceRef: {
+ std::pair<const NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_MemberRef: {
+ std::pair<const FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_VariableRef: {
+ std::pair<const VarDecl *, SourceLocation> P = getCursorVariableRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_CXXBaseSpecifier: {
+ const CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);
+ if (!BaseSpec)
+ return clang_getNullLocation();
+
+ if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
+ return cxloc::translateSourceLocation(
+ getCursorContext(C), TSInfo->getTypeLoc().getBeginLoc());
+
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ BaseSpec->getBeginLoc());
+ }
+
+ case CXCursor_LabelRef: {
+ std::pair<const LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
+ return cxloc::translateSourceLocation(getCursorContext(C), P.second);
+ }
+
+ case CXCursor_OverloadedDeclRef:
+ return cxloc::translateSourceLocation(
+ getCursorContext(C), getCursorOverloadedDeclRef(C).second);
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return cxloc::translateSourceLocation(
+ getCursorContext(C), getLocationFromExpr(getCursorExpr(C)));
+
+ if (clang_isStatement(C.kind))
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ getCursorStmt(C)->getBeginLoc());
+
+ if (C.kind == CXCursor_PreprocessingDirective) {
+ SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ SourceLocation L =
+ cxcursor::getCursorMacroExpansion(C).getSourceRange().getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_InclusionDirective) {
+ SourceLocation L =
+ cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (clang_isAttribute(C.kind)) {
+ SourceLocation L = cxcursor::getCursorAttr(C)->getLocation();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullLocation();
+
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullLocation();
+
+ SourceLocation Loc = D->getLocation();
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ Loc = VD->getLocation();
+ }
+
+ // For ObjC methods, give the start location of the method name.
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ Loc = MD->getSelectorStartLoc();
+
+ return cxloc::translateSourceLocation(getCursorContext(C), Loc);
+}
+
+} // end extern "C"
+
+CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) {
+ assert(TU);
+
+ // Guard against an invalid SourceLocation, or we may assert in one
+ // of the following calls.
+ if (SLoc.isInvalid())
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+
+ // Translate the given source location to make it point at the beginning of
+ // the token under the cursor.
+ SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
+ CXXUnit->getASTContext().getLangOpts());
+
+ CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ if (SLoc.isValid()) {
+ GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result);
+ CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false,
+ SourceLocation(SLoc));
+ CursorVis.visitFileRegion();
+ }
+
+ return Result;
+}
+
+static SourceRange getRawCursorExtent(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return getCursorObjCSuperClassRef(C).second;
+
+ case CXCursor_ObjCProtocolRef:
+ return getCursorObjCProtocolRef(C).second;
+
+ case CXCursor_ObjCClassRef:
+ return getCursorObjCClassRef(C).second;
+
+ case CXCursor_TypeRef:
+ return getCursorTypeRef(C).second;
+
+ case CXCursor_TemplateRef:
+ return getCursorTemplateRef(C).second;
+
+ case CXCursor_NamespaceRef:
+ return getCursorNamespaceRef(C).second;
+
+ case CXCursor_MemberRef:
+ return getCursorMemberRef(C).second;
+
+ case CXCursor_CXXBaseSpecifier:
+ return getCursorCXXBaseSpecifier(C)->getSourceRange();
+
+ case CXCursor_LabelRef:
+ return getCursorLabelRef(C).second;
+
+ case CXCursor_OverloadedDeclRef:
+ return getCursorOverloadedDeclRef(C).second;
+
+ case CXCursor_VariableRef:
+ return getCursorVariableRef(C).second;
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return getCursorExpr(C)->getSourceRange();
+
+ if (clang_isStatement(C.kind))
+ return getCursorStmt(C)->getSourceRange();
+
+ if (clang_isAttribute(C.kind))
+ return getCursorAttr(C)->getRange();
+
+ if (C.kind == CXCursor_PreprocessingDirective)
+ return cxcursor::getCursorPreprocessingDirective(C);
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range = cxcursor::getCursorMacroExpansion(C).getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_InclusionDirective) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range =
+ cxcursor::getCursorInclusionDirective(C)->getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_TranslationUnit) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ FileID MainID = TU->getSourceManager().getMainFileID();
+ SourceLocation Start = TU->getSourceManager().getLocForStartOfFile(MainID);
+ SourceLocation End = TU->getSourceManager().getLocForEndOfFile(MainID);
+ return SourceRange(Start, End);
+ }
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return SourceRange();
+
+ SourceRange R = D->getSourceRange();
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ R.setBegin(VD->getLocation());
+ }
+ return R;
+ }
+ return SourceRange();
+}
+
+/// Retrieves the "raw" cursor extent, which is then extended to include
+/// the decl-specifier-seq for declarations.
+static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return SourceRange();
+
+ SourceRange R = D->getSourceRange();
+
+ // Adjust the start of the location for declarations preceded by
+ // declaration specifiers.
+ SourceLocation StartLoc;
+ if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getBeginLoc();
+ } else if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
+ if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getBeginLoc();
+ }
+
+ if (StartLoc.isValid() && R.getBegin().isValid() &&
+ SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
+ R.setBegin(StartLoc);
+
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ R.setBegin(VD->getLocation());
+ }
+
+ return R;
+ }
+
+ return getRawCursorExtent(C);
+}
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ SourceRange R = getRawCursorExtent(C);
+ if (R.isInvalid())
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+}
+
+CXCursor clang_getCursorReferenced(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ CXTranslationUnit tu = getCursorTU(C);
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+ if (const UsingDecl *Using = dyn_cast<UsingDecl>(D))
+ return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);
+ if (const ObjCPropertyImplDecl *PropImpl =
+ dyn_cast<ObjCPropertyImplDecl>(D))
+ if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
+ return MakeCXCursor(Property, tu);
+
+ return C;
+ }
+
+ if (clang_isExpression(C.kind)) {
+ const Expr *E = getCursorExpr(C);
+ const Decl *D = getDeclFromExpr(E);
+ if (D) {
+ CXCursor declCursor = MakeCXCursor(D, tu);
+ declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C),
+ declCursor);
+ return declCursor;
+ }
+
+ if (const OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
+ return MakeCursorOverloadedDeclRef(Ovl, tu);
+
+ return clang_getNullCursor();
+ }
+
+ if (clang_isStatement(C.kind)) {
+ const Stmt *S = getCursorStmt(C);
+ if (const GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
+ if (LabelDecl *label = Goto->getLabel())
+ if (LabelStmt *labelS = label->getStmt())
+ return MakeCXCursor(labelS, getCursorDecl(C), tu);
+
+ return clang_getNullCursor();
+ }
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ if (const MacroDefinitionRecord *Def =
+ getCursorMacroExpansion(C).getDefinition())
+ return MakeMacroDefinitionCursor(Def, tu);
+ }
+
+ if (!clang_isReference(C.kind))
+ return clang_getNullCursor();
+
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);
+
+ case CXCursor_ObjCProtocolRef: {
+ const ObjCProtocolDecl *Prot = getCursorObjCProtocolRef(C).first;
+ if (const ObjCProtocolDecl *Def = Prot->getDefinition())
+ return MakeCXCursor(Def, tu);
+
+ return MakeCXCursor(Prot, tu);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ const ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ if (const ObjCInterfaceDecl *Def = Class->getDefinition())
+ return MakeCXCursor(Def, tu);
+
+ return MakeCXCursor(Class, tu);
+ }
+
+ case CXCursor_TypeRef:
+ return MakeCXCursor(getCursorTypeRef(C).first, tu);
+
+ case CXCursor_TemplateRef:
+ return MakeCXCursor(getCursorTemplateRef(C).first, tu);
+
+ case CXCursor_NamespaceRef:
+ return MakeCXCursor(getCursorNamespaceRef(C).first, tu);
+
+ case CXCursor_MemberRef:
+ return MakeCXCursor(getCursorMemberRef(C).first, tu);
+
+ case CXCursor_CXXBaseSpecifier: {
+ const CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
+ return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(), tu));
+ }
+
+ case CXCursor_LabelRef:
+ // FIXME: We end up faking the "parent" declaration here because we
+ // don't want to make CXCursor larger.
+ return MakeCXCursor(
+ getCursorLabelRef(C).first,
+ cxtu::getASTUnit(tu)->getASTContext().getTranslationUnitDecl(), tu);
+
+ case CXCursor_OverloadedDeclRef:
+ return C;
+
+ case CXCursor_VariableRef:
+ return MakeCXCursor(getCursorVariableRef(C).first, tu);
+
+ default:
+ // We would prefer to enumerate all non-reference cursor kinds here.
+ llvm_unreachable("Unhandled reference cursor kind");
+ }
+}
+
+CXCursor clang_getCursorDefinition(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ CXTranslationUnit TU = getCursorTU(C);
+
+ bool WasReference = false;
+ if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
+ C = clang_getCursorReferenced(C);
+ WasReference = true;
+ }
+
+ if (C.kind == CXCursor_MacroExpansion)
+ return clang_getCursorReferenced(C);
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ switch (D->getKind()) {
+ // Declaration kinds that don't really separate the notions of
+ // declaration and definition.
+ case Decl::Namespace:
+ case Decl::Typedef:
+ case Decl::TypeAlias:
+ case Decl::TypeAliasTemplate:
+ case Decl::TemplateTypeParm:
+ case Decl::EnumConstant:
+ case Decl::Field:
+ case Decl::Binding:
+ case Decl::MSProperty:
+ case Decl::MSGuid:
+ case Decl::TemplateParamObject:
+ case Decl::IndirectField:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ case Decl::NonTypeTemplateParm:
+ case Decl::TemplateTemplateParm:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::AccessSpec:
+ case Decl::LinkageSpec:
+ case Decl::Export:
+ case Decl::ObjCPropertyImpl:
+ case Decl::FileScopeAsm:
+ case Decl::StaticAssert:
+ case Decl::Block:
+ case Decl::Captured:
+ case Decl::OMPCapturedExpr:
+ case Decl::Label: // FIXME: Is this right??
+ case Decl::ClassScopeFunctionSpecialization:
+ case Decl::CXXDeductionGuide:
+ case Decl::Import:
+ case Decl::OMPThreadPrivate:
+ case Decl::OMPAllocate:
+ case Decl::OMPDeclareReduction:
+ case Decl::OMPDeclareMapper:
+ case Decl::OMPRequires:
+ case Decl::ObjCTypeParam:
+ case Decl::BuiltinTemplate:
+ case Decl::PragmaComment:
+ case Decl::PragmaDetectMismatch:
+ case Decl::UsingPack:
+ case Decl::Concept:
+ case Decl::LifetimeExtendedTemporary:
+ case Decl::RequiresExprBody:
+ case Decl::UnresolvedUsingIfExists:
+ return C;
+
+ // Declaration kinds that don't make any sense here, but are
+ // nonetheless harmless.
+ case Decl::Empty:
+ case Decl::TranslationUnit:
+ case Decl::ExternCContext:
+ break;
+
+ // Declaration kinds for which the definition is not resolvable.
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ break;
+
+ case Decl::UsingDirective:
+ return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
+ TU);
+
+ case Decl::NamespaceAlias:
+ return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);
+
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion: {
+ const FunctionDecl *Def = nullptr;
+ if (cast<FunctionDecl>(D)->getBody(Def))
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Var:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization:
+ case Decl::Decomposition: {
+ // Ask the variable if it has a definition.
+ if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::FunctionTemplate: {
+ const FunctionDecl *Def = nullptr;
+ if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
+ return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ClassTemplate: {
+ if (RecordDecl *Def =
+ cast<ClassTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
+ return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::VarTemplate: {
+ if (VarDecl *Def =
+ cast<VarTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
+ return MakeCXCursor(cast<VarDecl>(Def)->getDescribedVarTemplate(), TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Using:
+ case Decl::UsingEnum:
+ return MakeCursorOverloadedDeclRef(cast<BaseUsingDecl>(D), D->getLocation(),
+ TU);
+
+ case Decl::UsingShadow:
+ case Decl::ConstructorUsingShadow:
+ return clang_getCursorDefinition(
+ MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(), TU));
+
+ case Decl::ObjCMethod: {
+ const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+ if (Method->isThisDeclarationADefinition())
+ return C;
+
+ // Dig out the method definition in the associated
+ // @implementation, if we have it.
+ // FIXME: The ASTs should make finding the definition easier.
+ if (const ObjCInterfaceDecl *Class =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
+ if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
+ if (ObjCMethodDecl *Def = ClassImpl->getMethod(
+ Method->getSelector(), Method->isInstanceMethod()))
+ if (Def->isThisDeclarationADefinition())
+ return MakeCXCursor(Def, TU);
+
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCCategory:
+ if (ObjCCategoryImplDecl *Impl =
+ cast<ObjCCategoryDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, TU);
+ return clang_getNullCursor();
+
+ case Decl::ObjCProtocol:
+ if (const ObjCProtocolDecl *Def =
+ cast<ObjCProtocolDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+
+ case Decl::ObjCInterface: {
+ // There are two notions of a "definition" for an Objective-C
+ // class: the interface and its implementation. When we resolved a
+ // reference to an Objective-C class, produce the @interface as
+ // the definition; when we were provided with the interface,
+ // produce the @implementation as the definition.
+ const ObjCInterfaceDecl *IFace = cast<ObjCInterfaceDecl>(D);
+ if (WasReference) {
+ if (const ObjCInterfaceDecl *Def = IFace->getDefinition())
+ return MakeCXCursor(Def, TU);
+ } else if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+ return MakeCXCursor(Impl, TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCProperty:
+ // FIXME: We don't really know where to find the
+ // ObjCPropertyImplDecls that implement this property.
+ return clang_getNullCursor();
+
+ case Decl::ObjCCompatibleAlias:
+ if (const ObjCInterfaceDecl *Class =
+ cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
+ if (const ObjCInterfaceDecl *Def = Class->getDefinition())
+ return MakeCXCursor(Def, TU);
+
+ return clang_getNullCursor();
+
+ case Decl::Friend:
+ if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
+ return clang_getNullCursor();
+
+ case Decl::FriendTemplate:
+ if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
+ return clang_getNullCursor();
+ }
+
+ return clang_getNullCursor();
+}
+
+unsigned clang_isCursorDefinition(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ return clang_getCursorDefinition(C) == C;
+}
+
+CXCursor clang_getCanonicalCursor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return C;
+
+ if (const Decl *D = getCursorDecl(C)) {
+ if (const ObjCCategoryImplDecl *CatImplD =
+ dyn_cast<ObjCCategoryImplDecl>(D))
+ if (ObjCCategoryDecl *CatD = CatImplD->getCategoryDecl())
+ return MakeCXCursor(CatD, getCursorTU(C));
+
+ if (const ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
+ if (const ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
+ return MakeCXCursor(IFD, getCursorTU(C));
+
+ return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));
+ }
+
+ return C;
+}
+
+int clang_Cursor_getObjCSelectorIndex(CXCursor cursor) {
+ return cxcursor::getSelectorIdentifierIndexAndLoc(cursor).first;
+}
+
+unsigned clang_getNumOverloadedDecls(CXCursor C) {
+ if (C.kind != CXCursor_OverloadedDeclRef)
+ return 0;
+
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
+ if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
+ return E->getNumDecls();
+
+ if (OverloadedTemplateStorage *S =
+ Storage.dyn_cast<OverloadedTemplateStorage *>())
+ return S->size();
+
+ const Decl *D = Storage.get<const Decl *>();
+ if (const UsingDecl *Using = dyn_cast<UsingDecl>(D))
+ return Using->shadow_size();
+
+ return 0;
+}
+
+CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {
+ if (cursor.kind != CXCursor_OverloadedDeclRef)
+ return clang_getNullCursor();
+
+ if (index >= clang_getNumOverloadedDecls(cursor))
+ return clang_getNullCursor();
+
+ CXTranslationUnit TU = getCursorTU(cursor);
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;
+ if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
+ return MakeCXCursor(E->decls_begin()[index], TU);
+
+ if (OverloadedTemplateStorage *S =
+ Storage.dyn_cast<OverloadedTemplateStorage *>())
+ return MakeCXCursor(S->begin()[index], TU);
+
+ const Decl *D = Storage.get<const Decl *>();
+ if (const UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
+ // FIXME: This is, unfortunately, linear time.
+ UsingDecl::shadow_iterator Pos = Using->shadow_begin();
+ std::advance(Pos, index);
+ return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
+ }
+
+ return clang_getNullCursor();
+}
+
+void clang_getDefinitionSpellingAndExtent(
+ CXCursor C, const char **startBuf, const char **endBuf, unsigned *startLine,
+ unsigned *startColumn, unsigned *endLine, unsigned *endColumn) {
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(getCursorDecl(C));
+ CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
+
+ SourceManager &SM = FD->getASTContext().getSourceManager();
+ *startBuf = SM.getCharacterData(Body->getLBracLoc());
+ *endBuf = SM.getCharacterData(Body->getRBracLoc());
+ *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
+ *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
+ *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
+ *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
+}
+
+CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
+ unsigned PieceIndex) {
+ RefNamePieces Pieces;
+
+ switch (C.kind) {
+ case CXCursor_MemberRefExpr:
+ if (const MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C)))
+ Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(),
+ E->getQualifierLoc().getSourceRange());
+ break;
+
+ case CXCursor_DeclRefExpr:
+ if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) {
+ SourceRange TemplateArgLoc(E->getLAngleLoc(), E->getRAngleLoc());
+ Pieces =
+ buildPieces(NameFlags, false, E->getNameInfo(),
+ E->getQualifierLoc().getSourceRange(), &TemplateArgLoc);
+ }
+ break;
+
+ case CXCursor_CallExpr:
+ if (const CXXOperatorCallExpr *OCE =
+ dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) {
+ const Expr *Callee = OCE->getCallee();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee))
+ Callee = ICE->getSubExpr();
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee))
+ Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(),
+ DRE->getQualifierLoc().getSourceRange());
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (Pieces.empty()) {
+ if (PieceIndex == 0)
+ return clang_getCursorExtent(C);
+ } else if (PieceIndex < Pieces.size()) {
+ SourceRange R = Pieces[PieceIndex];
+ if (R.isValid())
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ return clang_getNullRange();
+}
+
+void clang_enableStackTraces(void) {
+ // FIXME: Provide an argv0 here so we can find llvm-symbolizer.
+ llvm::sys::PrintStackTraceOnErrorSignal(StringRef());
+}
+
+void clang_executeOnThread(void (*fn)(void *), void *user_data,
+ unsigned stack_size) {
+ llvm::thread Thread(stack_size == 0 ? clang::DesiredStackSize
+ : llvm::Optional<unsigned>(stack_size),
+ fn, user_data);
+ Thread.join();
+}
+
+//===----------------------------------------------------------------------===//
+// Token-based Operations.
+//===----------------------------------------------------------------------===//
+
+/* CXToken layout:
+ * int_data[0]: a CXTokenKind
+ * int_data[1]: starting token location
+ * int_data[2]: token length
+ * int_data[3]: reserved
+ * ptr_data: for identifiers and keywords, an IdentifierInfo*.
+ * otherwise unused.
+ */
+CXTokenKind clang_getTokenKind(CXToken CXTok) {
+ return static_cast<CXTokenKind>(CXTok.int_data[0]);
+}
+
+CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
+ switch (clang_getTokenKind(CXTok)) {
+ case CXToken_Identifier:
+ case CXToken_Keyword:
+ // We know we have an IdentifierInfo*, so use that.
+ return cxstring::createRef(
+ static_cast<IdentifierInfo *>(CXTok.ptr_data)->getNameStart());
+
+ case CXToken_Literal: {
+ // We have stashed the starting pointer in the ptr_data field. Use it.
+ const char *Text = static_cast<const char *>(CXTok.ptr_data);
+ return cxstring::createDup(StringRef(Text, CXTok.int_data[2]));
+ }
+
+ case CXToken_Punctuation:
+ case CXToken_Comment:
+ break;
+ }
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return cxstring::createEmpty();
+ }
+
+ // We have to find the starting buffer pointer the hard way, by
+ // deconstructing the source location.
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return cxstring::createEmpty();
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
+ std::pair<FileID, unsigned> LocInfo =
+ CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc);
+ bool Invalid = false;
+ StringRef Buffer =
+ CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return cxstring::createEmpty();
+
+ return cxstring::createDup(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
+}
+
+CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullLocation();
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return clang_getNullLocation();
+
+ return cxloc::translateSourceLocation(
+ CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullRange();
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(
+ CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
+ SmallVectorImpl<CXToken> &CXTokens) {
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo =
+ SourceMgr.getDecomposedSpellingLoc(Range.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo =
+ SourceMgr.getDecomposedSpellingLoc(Range.getEnd());
+
+ // Cannot tokenize across files.
+ if (BeginLocInfo.first != EndLocInfo.first)
+ return;
+
+ // Create a lexer
+ bool Invalid = false;
+ StringRef Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
+ if (Invalid)
+ return;
+
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOpts(), Buffer.begin(),
+ Buffer.data() + BeginLocInfo.second, Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ // Lex tokens until we hit the end of the range.
+ const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
+ Token Tok;
+ bool previousWasAt = false;
+ do {
+ // Lex the next token
+ Lex.LexFromRawLexer(Tok);
+ if (Tok.is(tok::eof))
+ break;
+
+ // Initialize the CXToken.
+ CXToken CXTok;
+
+ // - Common fields
+ CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
+ CXTok.int_data[2] = Tok.getLength();
+ CXTok.int_data[3] = 0;
+
+ // - Kind-specific fields
+ if (Tok.isLiteral()) {
+ CXTok.int_data[0] = CXToken_Literal;
+ CXTok.ptr_data = const_cast<char *>(Tok.getLiteralData());
+ } else if (Tok.is(tok::raw_identifier)) {
+ // Lookup the identifier to determine whether we have a keyword.
+ IdentifierInfo *II = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);
+
+ if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {
+ CXTok.int_data[0] = CXToken_Keyword;
+ } else {
+ CXTok.int_data[0] =
+ Tok.is(tok::identifier) ? CXToken_Identifier : CXToken_Keyword;
+ }
+ CXTok.ptr_data = II;
+ } else if (Tok.is(tok::comment)) {
+ CXTok.int_data[0] = CXToken_Comment;
+ CXTok.ptr_data = nullptr;
+ } else {
+ CXTok.int_data[0] = CXToken_Punctuation;
+ CXTok.ptr_data = nullptr;
+ }
+ CXTokens.push_back(CXTok);
+ previousWasAt = Tok.is(tok::at);
+ } while (Lex.getBufferLocation() < EffectiveBufferEnd);
+}
+
+CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) {
+ LOG_FUNC_SECTION { *Log << TU << ' ' << Location; }
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return nullptr;
+
+ SourceLocation Begin = cxloc::translateSourceLocation(Location);
+ if (Begin.isInvalid())
+ return nullptr;
+ SourceManager &SM = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> DecomposedEnd = SM.getDecomposedLoc(Begin);
+ DecomposedEnd.second +=
+ Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts());
+
+ SourceLocation End =
+ SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second);
+
+ SmallVector<CXToken, 32> CXTokens;
+ getTokens(CXXUnit, SourceRange(Begin, End), CXTokens);
+
+ if (CXTokens.empty())
+ return nullptr;
+
+ CXTokens.resize(1);
+ CXToken *Token = static_cast<CXToken *>(llvm::safe_malloc(sizeof(CXToken)));
+
+ memmove(Token, CXTokens.data(), sizeof(CXToken));
+ return Token;
+}
+
+void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens,
+ unsigned *NumTokens) {
+ LOG_FUNC_SECTION { *Log << TU << ' ' << Range; }
+
+ if (Tokens)
+ *Tokens = nullptr;
+ if (NumTokens)
+ *NumTokens = 0;
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return;
+ }
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit || !Tokens || !NumTokens)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceRange R = cxloc::translateCXSourceRange(Range);
+ if (R.isInvalid())
+ return;
+
+ SmallVector<CXToken, 32> CXTokens;
+ getTokens(CXXUnit, R, CXTokens);
+
+ if (CXTokens.empty())
+ return;
+
+ *Tokens = static_cast<CXToken *>(
+ llvm::safe_malloc(sizeof(CXToken) * CXTokens.size()));
+ memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
+ *NumTokens = CXTokens.size();
+}
+
+void clang_disposeTokens(CXTranslationUnit TU, CXToken *Tokens,
+ unsigned NumTokens) {
+ free(Tokens);
+}
+
+//===----------------------------------------------------------------------===//
+// Token annotation APIs.
+//===----------------------------------------------------------------------===//
+
+static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data);
+static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
+ CXClientData client_data);
+
+namespace {
+class AnnotateTokensWorker {
+ CXToken *Tokens;
+ CXCursor *Cursors;
+ unsigned NumTokens;
+ unsigned TokIdx;
+ unsigned PreprocessingTokIdx;
+ CursorVisitor AnnotateVis;
+ SourceManager &SrcMgr;
+ bool HasContextSensitiveKeywords;
+
+ struct PostChildrenAction {
+ CXCursor cursor;
+ enum Action { Invalid, Ignore, Postpone } action;
+ };
+ using PostChildrenActions = SmallVector<PostChildrenAction, 0>;
+
+ struct PostChildrenInfo {
+ CXCursor Cursor;
+ SourceRange CursorRange;
+ unsigned BeforeReachingCursorIdx;
+ unsigned BeforeChildrenTokenIdx;
+ PostChildrenActions ChildActions;
+ };
+ SmallVector<PostChildrenInfo, 8> PostChildrenInfos;
+
+ CXToken &getTok(unsigned Idx) {
+ assert(Idx < NumTokens);
+ return Tokens[Idx];
+ }
+ const CXToken &getTok(unsigned Idx) const {
+ assert(Idx < NumTokens);
+ return Tokens[Idx];
+ }
+ bool MoreTokens() const { return TokIdx < NumTokens; }
+ unsigned NextToken() const { return TokIdx; }
+ void AdvanceToken() { ++TokIdx; }
+ SourceLocation GetTokenLoc(unsigned tokI) {
+ return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]);
+ }
+ bool isFunctionMacroToken(unsigned tokI) const {
+ return getTok(tokI).int_data[3] != 0;
+ }
+ SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const {
+ return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[3]);
+ }
+
+ void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange);
+ bool annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult,
+ SourceRange);
+
+public:
+ AnnotateTokensWorker(CXToken *tokens, CXCursor *cursors, unsigned numTokens,
+ CXTranslationUnit TU, SourceRange RegionOfInterest)
+ : Tokens(tokens), Cursors(cursors), NumTokens(numTokens), TokIdx(0),
+ PreprocessingTokIdx(0),
+ AnnotateVis(TU, AnnotateTokensVisitor, this,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false, RegionOfInterest,
+ /*VisitDeclsOnly=*/false,
+ AnnotateTokensPostChildrenVisitor),
+ SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()),
+ HasContextSensitiveKeywords(false) {}
+
+ void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
+ enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
+ bool IsIgnoredChildCursor(CXCursor cursor) const;
+ PostChildrenActions DetermineChildActions(CXCursor Cursor) const;
+
+ bool postVisitChildren(CXCursor cursor);
+ void HandlePostPonedChildCursors(const PostChildrenInfo &Info);
+ void HandlePostPonedChildCursor(CXCursor Cursor, unsigned StartTokenIndex);
+
+ void AnnotateTokens();
+
+ /// Determine whether the annotator saw any cursors that have
+ /// context-sensitive keywords.
+ bool hasContextSensitiveKeywords() const {
+ return HasContextSensitiveKeywords;
+ }
+
+ ~AnnotateTokensWorker() { assert(PostChildrenInfos.empty()); }
+};
+} // namespace
+
+void AnnotateTokensWorker::AnnotateTokens() {
+ // Walk the AST within the region of interest, annotating tokens
+ // along the way.
+ AnnotateVis.visitFileRegion();
+}
+
+bool AnnotateTokensWorker::IsIgnoredChildCursor(CXCursor cursor) const {
+ if (PostChildrenInfos.empty())
+ return false;
+
+ for (const auto &ChildAction : PostChildrenInfos.back().ChildActions) {
+ if (ChildAction.cursor == cursor &&
+ ChildAction.action == PostChildrenAction::Ignore) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const CXXOperatorCallExpr *GetSubscriptOrCallOperator(CXCursor Cursor) {
+ if (!clang_isExpression(Cursor.kind))
+ return nullptr;
+
+ const Expr *E = getCursorExpr(Cursor);
+ if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
+ const OverloadedOperatorKind Kind = OCE->getOperator();
+ if (Kind == OO_Call || Kind == OO_Subscript)
+ return OCE;
+ }
+
+ return nullptr;
+}
+
+AnnotateTokensWorker::PostChildrenActions
+AnnotateTokensWorker::DetermineChildActions(CXCursor Cursor) const {
+ PostChildrenActions actions;
+
+ // The DeclRefExpr of CXXOperatorCallExpr refering to the custom operator is
+ // visited before the arguments to the operator call. For the Call and
+ // Subscript operator the range of this DeclRefExpr includes the whole call
+ // expression, so that all tokens in that range would be mapped to the
+ // operator function, including the tokens of the arguments. To avoid that,
+ // ensure to visit this DeclRefExpr as last node.
+ if (const auto *OCE = GetSubscriptOrCallOperator(Cursor)) {
+ const Expr *Callee = OCE->getCallee();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) {
+ const Expr *SubExpr = ICE->getSubExpr();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
+ const Decl *parentDecl = getCursorDecl(Cursor);
+ CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
+
+ // Visit the DeclRefExpr as last.
+ CXCursor cxChild = MakeCXCursor(DRE, parentDecl, TU);
+ actions.push_back({cxChild, PostChildrenAction::Postpone});
+
+ // The parent of the DeclRefExpr, an ImplicitCastExpr, has an equally
+ // wide range as the DeclRefExpr. We can skip visiting this entirely.
+ cxChild = MakeCXCursor(ICE, parentDecl, TU);
+ actions.push_back({cxChild, PostChildrenAction::Ignore});
+ }
+ }
+ }
+
+ return actions;
+}
+
+static inline void updateCursorAnnotation(CXCursor &Cursor,
+ const CXCursor &updateC) {
+ if (clang_isInvalid(updateC.kind) || !clang_isInvalid(Cursor.kind))
+ return;
+ Cursor = updateC;
+}
+
+/// It annotates and advances tokens with a cursor until the comparison
+//// between the cursor location and the source range is the same as
+/// \arg compResult.
+///
+/// Pass RangeBefore to annotate tokens with a cursor until a range is reached.
+/// Pass RangeOverlap to annotate tokens inside a range.
+void AnnotateTokensWorker::annotateAndAdvanceTokens(
+ CXCursor updateC, RangeComparisonResult compResult, SourceRange range) {
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ if (isFunctionMacroToken(I))
+ if (!annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range))
+ return;
+
+ SourceLocation TokLoc = GetTokenLoc(I);
+ if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
+ updateCursorAnnotation(Cursors[I], updateC);
+ AdvanceToken();
+ continue;
+ }
+ break;
+ }
+}
+
+/// Special annotation handling for macro argument tokens.
+/// \returns true if it advanced beyond all macro tokens, false otherwise.
+bool AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens(
+ CXCursor updateC, RangeComparisonResult compResult, SourceRange range) {
+ assert(MoreTokens());
+ assert(isFunctionMacroToken(NextToken()) &&
+ "Should be called only for macro arg tokens");
+
+ // This works differently than annotateAndAdvanceTokens; because expanded
+ // macro arguments can have arbitrary translation-unit source order, we do not
+ // advance the token index one by one until a token fails the range test.
+ // We only advance once past all of the macro arg tokens if all of them
+ // pass the range test. If one of them fails we keep the token index pointing
+ // at the start of the macro arg tokens so that the failing token will be
+ // annotated by a subsequent annotation try.
+
+ bool atLeastOneCompFail = false;
+
+ unsigned I = NextToken();
+ for (; I < NumTokens && isFunctionMacroToken(I); ++I) {
+ SourceLocation TokLoc = getFunctionMacroTokenLoc(I);
+ if (TokLoc.isFileID())
+ continue; // not macro arg token, it's parens or comma.
+ if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
+ if (clang_isInvalid(clang_getCursorKind(Cursors[I])))
+ Cursors[I] = updateC;
+ } else
+ atLeastOneCompFail = true;
+ }
+
+ if (atLeastOneCompFail)
+ return false;
+
+ TokIdx = I; // All of the tokens were handled, advance beyond all of them.
+ return true;
+}
+
+enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
+ CXCursor parent) {
+ SourceRange cursorRange = getRawCursorExtent(cursor);
+ if (cursorRange.isInvalid())
+ return CXChildVisit_Recurse;
+
+ if (IsIgnoredChildCursor(cursor))
+ return CXChildVisit_Continue;
+
+ if (!HasContextSensitiveKeywords) {
+ // Objective-C properties can have context-sensitive keywords.
+ if (cursor.kind == CXCursor_ObjCPropertyDecl) {
+ if (const ObjCPropertyDecl *Property =
+ dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
+ HasContextSensitiveKeywords =
+ Property->getPropertyAttributesAsWritten() != 0;
+ }
+ // Objective-C methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
+ cursor.kind == CXCursor_ObjCClassMethodDecl) {
+ if (const ObjCMethodDecl *Method =
+ dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->getObjCDeclQualifier())
+ HasContextSensitiveKeywords = true;
+ else {
+ for (const auto *P : Method->parameters()) {
+ if (P->getObjCDeclQualifier()) {
+ HasContextSensitiveKeywords = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // C++ methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_CXXMethod) {
+ if (const CXXMethodDecl *Method =
+ dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+ // C++ classes can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_StructDecl ||
+ cursor.kind == CXCursor_ClassDecl ||
+ cursor.kind == CXCursor_ClassTemplate ||
+ cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
+ if (const Decl *D = getCursorDecl(cursor))
+ if (D->hasAttr<FinalAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+
+ // Don't override a property annotation with its getter/setter method.
+ if (cursor.kind == CXCursor_ObjCInstanceMethodDecl &&
+ parent.kind == CXCursor_ObjCPropertyDecl)
+ return CXChildVisit_Continue;
+
+ if (clang_isPreprocessing(cursor.kind)) {
+ // Items in the preprocessing record are kept separate from items in
+ // declarations, so we keep a separate token index.
+ unsigned SavedTokIdx = TokIdx;
+ TokIdx = PreprocessingTokIdx;
+
+ // Skip tokens up until we catch up to the beginning of the preprocessing
+ // entry.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ AdvanceToken();
+ continue;
+ case RangeAfter:
+ case RangeOverlap:
+ break;
+ }
+ break;
+ }
+
+ // Look at all of the tokens within this range.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ llvm_unreachable("Infeasible");
+ case RangeAfter:
+ break;
+ case RangeOverlap:
+ // For macro expansions, just note where the beginning of the macro
+ // expansion occurs.
+ if (cursor.kind == CXCursor_MacroExpansion) {
+ if (TokLoc == cursorRange.getBegin())
+ Cursors[I] = cursor;
+ AdvanceToken();
+ break;
+ }
+ // We may have already annotated macro names inside macro definitions.
+ if (Cursors[I].kind != CXCursor_MacroExpansion)
+ Cursors[I] = cursor;
+ AdvanceToken();
+ continue;
+ }
+ break;
+ }
+
+ // Save the preprocessing token index; restore the non-preprocessing
+ // token index.
+ PreprocessingTokIdx = TokIdx;
+ TokIdx = SavedTokIdx;
+ return CXChildVisit_Recurse;
+ }
+
+ if (cursorRange.isInvalid())
+ return CXChildVisit_Continue;
+
+ unsigned BeforeReachingCursorIdx = NextToken();
+ const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
+ const enum CXCursorKind K = clang_getCursorKind(parent);
+ const CXCursor updateC =
+ (clang_isInvalid(K) || K == CXCursor_TranslationUnit ||
+ // Attributes are annotated out-of-order, skip tokens until we reach it.
+ clang_isAttribute(cursor.kind))
+ ? clang_getNullCursor()
+ : parent;
+
+ annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange);
+
+ // Avoid having the cursor of an expression "overwrite" the annotation of the
+ // variable declaration that it belongs to.
+ // This can happen for C++ constructor expressions whose range generally
+ // include the variable declaration, e.g.:
+ // MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor.
+ if (clang_isExpression(cursorK) && MoreTokens()) {
+ const Expr *E = getCursorExpr(cursor);
+ if (const Decl *D = getCursorDecl(cursor)) {
+ const unsigned I = NextToken();
+ if (E->getBeginLoc().isValid() && D->getLocation().isValid() &&
+ E->getBeginLoc() == D->getLocation() &&
+ E->getBeginLoc() == GetTokenLoc(I)) {
+ updateCursorAnnotation(Cursors[I], updateC);
+ AdvanceToken();
+ }
+ }
+ }
+
+ // Before recursing into the children keep some state that we are going
+ // to use in the AnnotateTokensWorker::postVisitChildren callback to do some
+ // extra work after the child nodes are visited.
+ // Note that we don't call VisitChildren here to avoid traversing statements
+ // code-recursively which can blow the stack.
+
+ PostChildrenInfo Info;
+ Info.Cursor = cursor;
+ Info.CursorRange = cursorRange;
+ Info.BeforeReachingCursorIdx = BeforeReachingCursorIdx;
+ Info.BeforeChildrenTokenIdx = NextToken();
+ Info.ChildActions = DetermineChildActions(cursor);
+ PostChildrenInfos.push_back(Info);
+
+ return CXChildVisit_Recurse;
+}
+
+bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
+ if (PostChildrenInfos.empty())
+ return false;
+ const PostChildrenInfo &Info = PostChildrenInfos.back();
+ if (!clang_equalCursors(Info.Cursor, cursor))
+ return false;
+
+ HandlePostPonedChildCursors(Info);
+
+ const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx;
+ const unsigned AfterChildren = NextToken();
+ SourceRange cursorRange = Info.CursorRange;
+
+ // Scan the tokens that are at the end of the cursor, but are not captured
+ // but the child cursors.
+ annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange);
+
+ // Scan the tokens that are at the beginning of the cursor, but are not
+ // capture by the child cursors.
+ for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
+ if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
+ break;
+
+ Cursors[I] = cursor;
+ }
+
+ // Attributes are annotated out-of-order, rewind TokIdx to when we first
+ // encountered the attribute cursor.
+ if (clang_isAttribute(cursor.kind))
+ TokIdx = Info.BeforeReachingCursorIdx;
+
+ PostChildrenInfos.pop_back();
+ return false;
+}
+
+void AnnotateTokensWorker::HandlePostPonedChildCursors(
+ const PostChildrenInfo &Info) {
+ for (const auto &ChildAction : Info.ChildActions) {
+ if (ChildAction.action == PostChildrenAction::Postpone) {
+ HandlePostPonedChildCursor(ChildAction.cursor,
+ Info.BeforeChildrenTokenIdx);
+ }
+ }
+}
+
+void AnnotateTokensWorker::HandlePostPonedChildCursor(
+ CXCursor Cursor, unsigned StartTokenIndex) {
+ unsigned I = StartTokenIndex;
+
+ // The bracket tokens of a Call or Subscript operator are mapped to
+ // CallExpr/CXXOperatorCallExpr because we skipped visiting the corresponding
+ // DeclRefExpr. Remap these tokens to the DeclRefExpr cursors.
+ for (unsigned RefNameRangeNr = 0; I < NumTokens; RefNameRangeNr++) {
+ const CXSourceRange CXRefNameRange = clang_getCursorReferenceNameRange(
+ Cursor, CXNameRange_WantQualifier, RefNameRangeNr);
+ if (clang_Range_isNull(CXRefNameRange))
+ break; // All ranges handled.
+
+ SourceRange RefNameRange = cxloc::translateCXSourceRange(CXRefNameRange);
+ while (I < NumTokens) {
+ const SourceLocation TokenLocation = GetTokenLoc(I);
+ if (!TokenLocation.isValid())
+ break;
+
+ // Adapt the end range, because LocationCompare() reports
+ // RangeOverlap even for the not-inclusive end location.
+ const SourceLocation fixedEnd =
+ RefNameRange.getEnd().getLocWithOffset(-1);
+ RefNameRange = SourceRange(RefNameRange.getBegin(), fixedEnd);
+
+ const RangeComparisonResult ComparisonResult =
+ LocationCompare(SrcMgr, TokenLocation, RefNameRange);
+
+ if (ComparisonResult == RangeOverlap) {
+ Cursors[I++] = Cursor;
+ } else if (ComparisonResult == RangeBefore) {
+ ++I; // Not relevant token, check next one.
+ } else if (ComparisonResult == RangeAfter) {
+ break; // All tokens updated for current range, check next.
+ }
+ }
+ }
+}
+
+static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<AnnotateTokensWorker *>(client_data)
+ ->Visit(cursor, parent);
+}
+
+static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
+ CXClientData client_data) {
+ return static_cast<AnnotateTokensWorker *>(client_data)
+ ->postVisitChildren(cursor);
+}
+
+namespace {
+
+/// Uses the macro expansions in the preprocessing record to find
+/// and mark tokens that are macro arguments. This info is used by the
+/// AnnotateTokensWorker.
+class MarkMacroArgTokensVisitor {
+ SourceManager &SM;
+ CXToken *Tokens;
+ unsigned NumTokens;
+ unsigned CurIdx;
+
+public:
+ MarkMacroArgTokensVisitor(SourceManager &SM, CXToken *tokens,
+ unsigned numTokens)
+ : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) {}
+
+ CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
+ if (cursor.kind != CXCursor_MacroExpansion)
+ return CXChildVisit_Continue;
+
+ SourceRange macroRange = getCursorMacroExpansion(cursor).getSourceRange();
+ if (macroRange.getBegin() == macroRange.getEnd())
+ return CXChildVisit_Continue; // it's not a function macro.
+
+ for (; CurIdx < NumTokens; ++CurIdx) {
+ if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx),
+ macroRange.getBegin()))
+ break;
+ }
+
+ if (CurIdx == NumTokens)
+ return CXChildVisit_Break;
+
+ for (; CurIdx < NumTokens; ++CurIdx) {
+ SourceLocation tokLoc = getTokenLoc(CurIdx);
+ if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd()))
+ break;
+
+ setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc));
+ }
+
+ if (CurIdx == NumTokens)
+ return CXChildVisit_Break;
+
+ return CXChildVisit_Continue;
+ }
+
+private:
+ CXToken &getTok(unsigned Idx) {
+ assert(Idx < NumTokens);
+ return Tokens[Idx];
+ }
+ const CXToken &getTok(unsigned Idx) const {
+ assert(Idx < NumTokens);
+ return Tokens[Idx];
+ }
+
+ SourceLocation getTokenLoc(unsigned tokI) {
+ return SourceLocation::getFromRawEncoding(getTok(tokI).int_data[1]);
+ }
+
+ void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) {
+ // The third field is reserved and currently not used. Use it here
+ // to mark macro arg expanded tokens with their expanded locations.
+ getTok(tokI).int_data[3] = loc.getRawEncoding();
+ }
+};
+
+} // end anonymous namespace
+
+static CXChildVisitResult
+MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<MarkMacroArgTokensVisitor *>(client_data)
+ ->visit(cursor, parent);
+}
+
+/// Used by \c annotatePreprocessorTokens.
+/// \returns true if lexing was finished, false otherwise.
+static bool lexNext(Lexer &Lex, Token &Tok, unsigned &NextIdx,
+ unsigned NumTokens) {
+ if (NextIdx >= NumTokens)
+ return true;
+
+ ++NextIdx;
+ Lex.LexFromRawLexer(Tok);
+ return Tok.is(tok::eof);
+}
+
+static void annotatePreprocessorTokens(CXTranslationUnit TU,
+ SourceRange RegionOfInterest,
+ CXCursor *Cursors, CXToken *Tokens,
+ unsigned NumTokens) {
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+
+ Preprocessor &PP = CXXUnit->getPreprocessor();
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo =
+ SourceMgr.getDecomposedSpellingLoc(RegionOfInterest.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo =
+ SourceMgr.getDecomposedSpellingLoc(RegionOfInterest.getEnd());
+
+ if (BeginLocInfo.first != EndLocInfo.first)
+ return;
+
+ StringRef Buffer;
+ bool Invalid = false;
+ Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
+ if (Buffer.empty() || Invalid)
+ return;
+
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOpts(), Buffer.begin(),
+ Buffer.data() + BeginLocInfo.second, Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ unsigned NextIdx = 0;
+ // Lex tokens in raw mode until we hit the end of the range, to avoid
+ // entering #includes or expanding macros.
+ while (true) {
+ Token Tok;
+ if (lexNext(Lex, Tok, NextIdx, NumTokens))
+ break;
+ unsigned TokIdx = NextIdx - 1;
+ assert(Tok.getLocation() ==
+ SourceLocation::getFromRawEncoding(Tokens[TokIdx].int_data[1]));
+
+ reprocess:
+ if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
+ // We have found a preprocessing directive. Annotate the tokens
+ // appropriately.
+ //
+ // FIXME: Some simple tests here could identify macro definitions and
+ // #undefs, to provide specific cursor kinds for those.
+
+ SourceLocation BeginLoc = Tok.getLocation();
+ if (lexNext(Lex, Tok, NextIdx, NumTokens))
+ break;
+
+ MacroInfo *MI = nullptr;
+ if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "define") {
+ if (lexNext(Lex, Tok, NextIdx, NumTokens))
+ break;
+
+ if (Tok.is(tok::raw_identifier)) {
+ IdentifierInfo &II =
+ PP.getIdentifierTable().get(Tok.getRawIdentifier());
+ SourceLocation MappedTokLoc =
+ CXXUnit->mapLocationToPreamble(Tok.getLocation());
+ MI = getMacroInfo(II, MappedTokLoc, TU);
+ }
+ }
+
+ bool finished = false;
+ do {
+ if (lexNext(Lex, Tok, NextIdx, NumTokens)) {
+ finished = true;
+ break;
+ }
+ // If we are in a macro definition, check if the token was ever a
+ // macro name and annotate it if that's the case.
+ if (MI) {
+ SourceLocation SaveLoc = Tok.getLocation();
+ Tok.setLocation(CXXUnit->mapLocationToPreamble(SaveLoc));
+ MacroDefinitionRecord *MacroDef =
+ checkForMacroInMacroDefinition(MI, Tok, TU);
+ Tok.setLocation(SaveLoc);
+ if (MacroDef)
+ Cursors[NextIdx - 1] =
+ MakeMacroExpansionCursor(MacroDef, Tok.getLocation(), TU);
+ }
+ } while (!Tok.isAtStartOfLine());
+
+ unsigned LastIdx = finished ? NextIdx - 1 : NextIdx - 2;
+ assert(TokIdx <= LastIdx);
+ SourceLocation EndLoc =
+ SourceLocation::getFromRawEncoding(Tokens[LastIdx].int_data[1]);
+ CXCursor Cursor =
+ MakePreprocessingDirectiveCursor(SourceRange(BeginLoc, EndLoc), TU);
+
+ for (; TokIdx <= LastIdx; ++TokIdx)
+ updateCursorAnnotation(Cursors[TokIdx], Cursor);
+
+ if (finished)
+ break;
+ goto reprocess;
+ }
+ }
+}
+
+// This gets run a separate thread to avoid stack blowout.
+static void clang_annotateTokensImpl(CXTranslationUnit TU, ASTUnit *CXXUnit,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors) {
+ CIndexer *CXXIdx = TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
+ setThreadBackgroundPriority();
+
+ // Determine the region of interest, which contains all of the tokens.
+ SourceRange RegionOfInterest;
+ RegionOfInterest.setBegin(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
+ RegionOfInterest.setEnd(cxloc::translateSourceLocation(
+ clang_getTokenLocation(TU, Tokens[NumTokens - 1])));
+
+ // Relex the tokens within the source range to look for preprocessing
+ // directives.
+ annotatePreprocessorTokens(TU, RegionOfInterest, Cursors, Tokens, NumTokens);
+
+ // If begin location points inside a macro argument, set it to the expansion
+ // location so we can have the full context when annotating semantically.
+ {
+ SourceManager &SM = CXXUnit->getSourceManager();
+ SourceLocation Loc =
+ SM.getMacroArgExpandedLocation(RegionOfInterest.getBegin());
+ if (Loc.isMacroID())
+ RegionOfInterest.setBegin(SM.getExpansionLoc(Loc));
+ }
+
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
+ // Search and mark tokens that are macro argument expansions.
+ MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(), Tokens,
+ NumTokens);
+ CursorVisitor MacroArgMarker(
+ TU, MarkMacroArgTokensVisitorDelegate, &Visitor,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false, RegionOfInterest);
+ MacroArgMarker.visitPreprocessedEntitiesInRegion();
+ }
+
+ // Annotate all of the source locations in the region of interest that map to
+ // a specific cursor.
+ AnnotateTokensWorker W(Tokens, Cursors, NumTokens, TU, RegionOfInterest);
+
+ // FIXME: We use a ridiculous stack size here because the data-recursion
+ // algorithm uses a large stack frame than the non-data recursive version,
+ // and AnnotationTokensWorker currently transforms the data-recursion
+ // algorithm back into a traditional recursion by explicitly calling
+ // VisitChildren(). We will need to remove this explicit recursive call.
+ W.AnnotateTokens();
+
+ // If we ran into any entities that involve context-sensitive keywords,
+ // take another pass through the tokens to mark them as such.
+ if (W.hasContextSensitiveKeywords()) {
+ for (unsigned I = 0; I != NumTokens; ++I) {
+ if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
+ continue;
+
+ if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (const ObjCPropertyDecl *Property =
+ dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
+ if (Property->getPropertyAttributesAsWritten() != 0 &&
+ llvm::StringSwitch<bool>(II->getName())
+ .Case("readonly", true)
+ .Case("assign", true)
+ .Case("unsafe_unretained", true)
+ .Case("readwrite", true)
+ .Case("retain", true)
+ .Case("copy", true)
+ .Case("nonatomic", true)
+ .Case("atomic", true)
+ .Case("getter", true)
+ .Case("setter", true)
+ .Case("strong", true)
+ .Case("weak", true)
+ .Case("class", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ }
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
+ Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (llvm::StringSwitch<bool>(II->getName())
+ .Case("in", true)
+ .Case("out", true)
+ .Case("inout", true)
+ .Case("oneway", true)
+ .Case("bycopy", true)
+ .Case("byref", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_CXXFinalAttr ||
+ Cursors[I].kind == CXCursor_CXXOverrideAttr) {
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ continue;
+ }
+ }
+ }
+}
+
+void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens,
+ unsigned NumTokens, CXCursor *Cursors) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return;
+ }
+ if (NumTokens == 0 || !Tokens || !Cursors) {
+ LOG_FUNC_SECTION { *Log << "<null input>"; }
+ return;
+ }
+
+ LOG_FUNC_SECTION {
+ *Log << TU << ' ';
+ CXSourceLocation bloc = clang_getTokenLocation(TU, Tokens[0]);
+ CXSourceLocation eloc = clang_getTokenLocation(TU, Tokens[NumTokens - 1]);
+ *Log << clang_getRange(bloc, eloc);
+ }
+
+ // Any token we don't specifically annotate will have a NULL cursor.
+ CXCursor C = clang_getNullCursor();
+ for (unsigned I = 0; I != NumTokens; ++I)
+ Cursors[I] = C;
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ auto AnnotateTokensImpl = [=]() {
+ clang_annotateTokensImpl(TU, CXXUnit, Tokens, NumTokens, Cursors);
+ };
+ llvm::CrashRecoveryContext CRC;
+ if (!RunSafely(CRC, AnnotateTokensImpl, GetSafetyThreadStackSize() * 2)) {
+ fprintf(stderr, "libclang: crash detected while annotating tokens\n");
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Operations for querying linkage of a cursor.
+//===----------------------------------------------------------------------===//
+
+CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXLinkage_Invalid;
+
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getLinkageInternal()) {
+ case NoLinkage:
+ case VisibleNoLinkage:
+ return CXLinkage_NoLinkage;
+ case ModuleInternalLinkage:
+ case InternalLinkage:
+ return CXLinkage_Internal;
+ case UniqueExternalLinkage:
+ return CXLinkage_UniqueExternal;
+ case ModuleLinkage:
+ case ExternalLinkage:
+ return CXLinkage_External;
+ };
+
+ return CXLinkage_Invalid;
+}
+
+//===----------------------------------------------------------------------===//
+// Operations for querying visibility of a cursor.
+//===----------------------------------------------------------------------===//
+
+CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXVisibility_Invalid;
+
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getVisibility()) {
+ case HiddenVisibility:
+ return CXVisibility_Hidden;
+ case ProtectedVisibility:
+ return CXVisibility_Protected;
+ case DefaultVisibility:
+ return CXVisibility_Default;
+ };
+
+ return CXVisibility_Invalid;
+}
+
+//===----------------------------------------------------------------------===//
+// Operations for querying language of a cursor.
+//===----------------------------------------------------------------------===//
+
+static CXLanguageKind getDeclLanguage(const Decl *D) {
+ if (!D)
+ return CXLanguage_C;
+
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::ImplicitParam:
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCIvar:
+ case Decl::ObjCMethod:
+ case Decl::ObjCProperty:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCProtocol:
+ case Decl::ObjCTypeParam:
+ return CXLanguage_ObjC;
+ case Decl::CXXConstructor:
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXMethod:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplate:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::LinkageSpec:
+ case Decl::Namespace:
+ case Decl::NamespaceAlias:
+ case Decl::NonTypeTemplateParm:
+ case Decl::StaticAssert:
+ case Decl::TemplateTemplateParm:
+ case Decl::TemplateTypeParm:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ case Decl::Using:
+ case Decl::UsingDirective:
+ case Decl::UsingShadow:
+ return CXLanguage_CPlusPlus;
+ }
+
+ return CXLanguage_C;
+}
+
+static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) {
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
+ return CXAvailability_NotAvailable;
+
+ switch (D->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
+ return getCursorAvailabilityForDecl(
+ cast<Decl>(EnumConst->getDeclContext()));
+ return CXAvailability_Available;
+
+ case AR_Deprecated:
+ return CXAvailability_Deprecated;
+
+ case AR_Unavailable:
+ return CXAvailability_NotAvailable;
+ }
+
+ llvm_unreachable("Unknown availability kind!");
+}
+
+enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ if (const Decl *D = cxcursor::getCursorDecl(cursor))
+ return getCursorAvailabilityForDecl(D);
+
+ return CXAvailability_Available;
+}
+
+static CXVersion convertVersion(VersionTuple In) {
+ CXVersion Out = {-1, -1, -1};
+ if (In.empty())
+ return Out;
+
+ Out.Major = In.getMajor();
+
+ Optional<unsigned> Minor = In.getMinor();
+ if (Minor.hasValue())
+ Out.Minor = *Minor;
+ else
+ return Out;
+
+ Optional<unsigned> Subminor = In.getSubminor();
+ if (Subminor.hasValue())
+ Out.Subminor = *Subminor;
+
+ return Out;
+}
+
+static void getCursorPlatformAvailabilityForDecl(
+ const Decl *D, int *always_deprecated, CXString *deprecated_message,
+ int *always_unavailable, CXString *unavailable_message,
+ SmallVectorImpl<AvailabilityAttr *> &AvailabilityAttrs) {
+ bool HadAvailAttr = false;
+ for (auto A : D->attrs()) {
+ if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(A)) {
+ HadAvailAttr = true;
+ if (always_deprecated)
+ *always_deprecated = 1;
+ if (deprecated_message) {
+ clang_disposeString(*deprecated_message);
+ *deprecated_message = cxstring::createDup(Deprecated->getMessage());
+ }
+ continue;
+ }
+
+ if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(A)) {
+ HadAvailAttr = true;
+ if (always_unavailable)
+ *always_unavailable = 1;
+ if (unavailable_message) {
+ clang_disposeString(*unavailable_message);
+ *unavailable_message = cxstring::createDup(Unavailable->getMessage());
+ }
+ continue;
+ }
+
+ if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(A)) {
+ AvailabilityAttrs.push_back(Avail);
+ HadAvailAttr = true;
+ }
+ }
+
+ if (!HadAvailAttr)
+ if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
+ return getCursorPlatformAvailabilityForDecl(
+ cast<Decl>(EnumConst->getDeclContext()), always_deprecated,
+ deprecated_message, always_unavailable, unavailable_message,
+ AvailabilityAttrs);
+
+ if (AvailabilityAttrs.empty())
+ return;
+
+ llvm::sort(
+ AvailabilityAttrs, [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+ return LHS->getPlatform()->getName() < RHS->getPlatform()->getName();
+ });
+ ASTContext &Ctx = D->getASTContext();
+ auto It = std::unique(
+ AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+ [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+ if (LHS->getPlatform() != RHS->getPlatform())
+ return false;
+
+ if (LHS->getIntroduced() == RHS->getIntroduced() &&
+ LHS->getDeprecated() == RHS->getDeprecated() &&
+ LHS->getObsoleted() == RHS->getObsoleted() &&
+ LHS->getMessage() == RHS->getMessage() &&
+ LHS->getReplacement() == RHS->getReplacement())
+ return true;
+
+ if ((!LHS->getIntroduced().empty() && !RHS->getIntroduced().empty()) ||
+ (!LHS->getDeprecated().empty() && !RHS->getDeprecated().empty()) ||
+ (!LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()))
+ return false;
+
+ if (LHS->getIntroduced().empty() && !RHS->getIntroduced().empty())
+ LHS->setIntroduced(Ctx, RHS->getIntroduced());
+
+ if (LHS->getDeprecated().empty() && !RHS->getDeprecated().empty()) {
+ LHS->setDeprecated(Ctx, RHS->getDeprecated());
+ if (LHS->getMessage().empty())
+ LHS->setMessage(Ctx, RHS->getMessage());
+ if (LHS->getReplacement().empty())
+ LHS->setReplacement(Ctx, RHS->getReplacement());
+ }
+
+ if (LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()) {
+ LHS->setObsoleted(Ctx, RHS->getObsoleted());
+ if (LHS->getMessage().empty())
+ LHS->setMessage(Ctx, RHS->getMessage());
+ if (LHS->getReplacement().empty())
+ LHS->setReplacement(Ctx, RHS->getReplacement());
+ }
+
+ return true;
+ });
+ AvailabilityAttrs.erase(It, AvailabilityAttrs.end());
+}
+
+int clang_getCursorPlatformAvailability(CXCursor cursor, int *always_deprecated,
+ CXString *deprecated_message,
+ int *always_unavailable,
+ CXString *unavailable_message,
+ CXPlatformAvailability *availability,
+ int availability_size) {
+ if (always_deprecated)
+ *always_deprecated = 0;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createEmpty();
+ if (always_unavailable)
+ *always_unavailable = 0;
+ if (unavailable_message)
+ *unavailable_message = cxstring::createEmpty();
+
+ if (!clang_isDeclaration(cursor.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (!D)
+ return 0;
+
+ SmallVector<AvailabilityAttr *, 8> AvailabilityAttrs;
+ getCursorPlatformAvailabilityForDecl(D, always_deprecated, deprecated_message,
+ always_unavailable, unavailable_message,
+ AvailabilityAttrs);
+ for (const auto &Avail :
+ llvm::enumerate(llvm::makeArrayRef(AvailabilityAttrs)
+ .take_front(availability_size))) {
+ availability[Avail.index()].Platform =
+ cxstring::createDup(Avail.value()->getPlatform()->getName());
+ availability[Avail.index()].Introduced =
+ convertVersion(Avail.value()->getIntroduced());
+ availability[Avail.index()].Deprecated =
+ convertVersion(Avail.value()->getDeprecated());
+ availability[Avail.index()].Obsoleted =
+ convertVersion(Avail.value()->getObsoleted());
+ availability[Avail.index()].Unavailable = Avail.value()->getUnavailable();
+ availability[Avail.index()].Message =
+ cxstring::createDup(Avail.value()->getMessage());
+ }
+
+ return AvailabilityAttrs.size();
+}
+
+void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
+ clang_disposeString(availability->Platform);
+ clang_disposeString(availability->Message);
+}
+
+CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ return getDeclLanguage(cxcursor::getCursorDecl(cursor));
+
+ return CXLanguage_Invalid;
+}
+
+CXTLSKind clang_getCursorTLSKind(CXCursor cursor) {
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ switch (VD->getTLSKind()) {
+ case VarDecl::TLS_None:
+ return CXTLS_None;
+ case VarDecl::TLS_Dynamic:
+ return CXTLS_Dynamic;
+ case VarDecl::TLS_Static:
+ return CXTLS_Static;
+ }
+ }
+
+ return CXTLS_None;
+}
+
+/// If the given cursor is the "templated" declaration
+/// describing a class or function template, return the class or
+/// function template.
+static const Decl *maybeGetTemplateCursor(const Decl *D) {
+ if (!D)
+ return nullptr;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())
+ return FunTmpl;
+
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+ if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())
+ return ClassTmpl;
+
+ return D;
+}
+
+enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor C) {
+ StorageClass sc = SC_None;
+ const Decl *D = getCursorDecl(C);
+ if (D) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ sc = FD->getStorageClass();
+ } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ sc = VD->getStorageClass();
+ } else {
+ return CX_SC_Invalid;
+ }
+ } else {
+ return CX_SC_Invalid;
+ }
+ switch (sc) {
+ case SC_None:
+ return CX_SC_None;
+ case SC_Extern:
+ return CX_SC_Extern;
+ case SC_Static:
+ return CX_SC_Static;
+ case SC_PrivateExtern:
+ return CX_SC_PrivateExtern;
+ case SC_Auto:
+ return CX_SC_Auto;
+ case SC_Register:
+ return CX_SC_Register;
+ }
+ llvm_unreachable("Unhandled storage class!");
+}
+
+CXCursor clang_getCursorSemanticParent(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind)) {
+ if (const Decl *D = getCursorDecl(cursor)) {
+ const DeclContext *DC = D->getDeclContext();
+ if (!DC)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
+ getCursorTU(cursor));
+ }
+ }
+
+ if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {
+ if (const Decl *D = getCursorDecl(cursor))
+ return MakeCXCursor(D, getCursorTU(cursor));
+ }
+
+ return clang_getNullCursor();
+}
+
+CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind)) {
+ if (const Decl *D = getCursorDecl(cursor)) {
+ const DeclContext *DC = D->getLexicalDeclContext();
+ if (!DC)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
+ getCursorTU(cursor));
+ }
+ }
+
+ // FIXME: Note that we can't easily compute the lexical context of a
+ // statement or expression, so we return nothing.
+ return clang_getNullCursor();
+}
+
+CXFile clang_getIncludedFile(CXCursor cursor) {
+ if (cursor.kind != CXCursor_InclusionDirective)
+ return nullptr;
+
+ const InclusionDirective *ID = getCursorInclusionDirective(cursor);
+ return const_cast<FileEntry *>(ID->getFile());
+}
+
+unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return CXObjCPropertyAttr_noattr;
+
+ unsigned Result = CXObjCPropertyAttr_noattr;
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ ObjCPropertyAttribute::Kind Attr = PD->getPropertyAttributesAsWritten();
+
+#define SET_CXOBJCPROP_ATTR(A) \
+ if (Attr & ObjCPropertyAttribute::kind_##A) \
+ Result |= CXObjCPropertyAttr_##A
+ SET_CXOBJCPROP_ATTR(readonly);
+ SET_CXOBJCPROP_ATTR(getter);
+ SET_CXOBJCPROP_ATTR(assign);
+ SET_CXOBJCPROP_ATTR(readwrite);
+ SET_CXOBJCPROP_ATTR(retain);
+ SET_CXOBJCPROP_ATTR(copy);
+ SET_CXOBJCPROP_ATTR(nonatomic);
+ SET_CXOBJCPROP_ATTR(setter);
+ SET_CXOBJCPROP_ATTR(atomic);
+ SET_CXOBJCPROP_ATTR(weak);
+ SET_CXOBJCPROP_ATTR(strong);
+ SET_CXOBJCPROP_ATTR(unsafe_unretained);
+ SET_CXOBJCPROP_ATTR(class);
+#undef SET_CXOBJCPROP_ATTR
+
+ return Result;
+}
+
+CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return cxstring::createNull();
+
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ Selector sel = PD->getGetterName();
+ if (sel.isNull())
+ return cxstring::createNull();
+
+ return cxstring::createDup(sel.getAsString());
+}
+
+CXString clang_Cursor_getObjCPropertySetterName(CXCursor C) {
+ if (C.kind != CXCursor_ObjCPropertyDecl)
+ return cxstring::createNull();
+
+ const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(getCursorDecl(C));
+ Selector sel = PD->getSetterName();
+ if (sel.isNull())
+ return cxstring::createNull();
+
+ return cxstring::createDup(sel.getAsString());
+}
+
+unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return CXObjCDeclQualifier_None;
+
+ Decl::ObjCDeclQualifier QT = Decl::OBJC_TQ_None;
+ const Decl *D = getCursorDecl(C);
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ QT = MD->getObjCDeclQualifier();
+ else if (const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
+ QT = PD->getObjCDeclQualifier();
+ if (QT == Decl::OBJC_TQ_None)
+ return CXObjCDeclQualifier_None;
+
+ unsigned Result = CXObjCDeclQualifier_None;
+ if (QT & Decl::OBJC_TQ_In)
+ Result |= CXObjCDeclQualifier_In;
+ if (QT & Decl::OBJC_TQ_Inout)
+ Result |= CXObjCDeclQualifier_Inout;
+ if (QT & Decl::OBJC_TQ_Out)
+ Result |= CXObjCDeclQualifier_Out;
+ if (QT & Decl::OBJC_TQ_Bycopy)
+ Result |= CXObjCDeclQualifier_Bycopy;
+ if (QT & Decl::OBJC_TQ_Byref)
+ Result |= CXObjCDeclQualifier_Byref;
+ if (QT & Decl::OBJC_TQ_Oneway)
+ Result |= CXObjCDeclQualifier_Oneway;
+
+ return Result;
+}
+
+unsigned clang_Cursor_isObjCOptional(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = getCursorDecl(C);
+ if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
+ return PD->getPropertyImplementation() == ObjCPropertyDecl::Optional;
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getImplementationControl() == ObjCMethodDecl::Optional;
+
+ return 0;
+}
+
+unsigned clang_Cursor_isVariadic(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = getCursorDecl(C);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isVariadic();
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->isVariadic();
+
+ return 0;
+}
+
+unsigned clang_Cursor_isExternalSymbol(CXCursor C, CXString *language,
+ CXString *definedIn,
+ unsigned *isGenerated) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = getCursorDecl(C);
+
+ if (auto *attr = D->getExternalSourceSymbolAttr()) {
+ if (language)
+ *language = cxstring::createDup(attr->getLanguage());
+ if (definedIn)
+ *definedIn = cxstring::createDup(attr->getDefinedIn());
+ if (isGenerated)
+ *isGenerated = attr->getGeneratedDeclaration();
+ return 1;
+ }
+ return 0;
+}
+
+CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullRange();
+
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ if (!RC)
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(Context, RC->getSourceRange());
+}
+
+CXString clang_Cursor_getRawCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return cxstring::createNull();
+
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ StringRef RawText =
+ RC ? RC->getRawText(Context.getSourceManager()) : StringRef();
+
+ // Don't duplicate the string because RawText points directly into source
+ // code.
+ return cxstring::createRef(RawText);
+}
+
+CXString clang_Cursor_getBriefCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return cxstring::createNull();
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+
+ if (RC) {
+ StringRef BriefText = RC->getBriefText(Context);
+
+ // Don't duplicate the string because RawComment ensures that this memory
+ // will not go away.
+ return cxstring::createRef(BriefText);
+ }
+
+ return cxstring::createNull();
+}
+
+CXModule clang_Cursor_getModule(CXCursor C) {
+ if (C.kind == CXCursor_ModuleImportDecl) {
+ if (const ImportDecl *ImportD =
+ dyn_cast_or_null<ImportDecl>(getCursorDecl(C)))
+ return ImportD->getImportedModule();
+ }
+
+ return nullptr;
+}
+
+CXModule clang_getModuleForFile(CXTranslationUnit TU, CXFile File) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+ if (!File)
+ return nullptr;
+ FileEntry *FE = static_cast<FileEntry *>(File);
+
+ ASTUnit &Unit = *cxtu::getASTUnit(TU);
+ HeaderSearch &HS = Unit.getPreprocessor().getHeaderSearchInfo();
+ ModuleMap::KnownHeader Header = HS.findModuleForHeader(FE);
+
+ return Header.getModule();
+}
+
+CXFile clang_Module_getASTFile(CXModule CXMod) {
+ if (!CXMod)
+ return nullptr;
+ Module *Mod = static_cast<Module *>(CXMod);
+ if (auto File = Mod->getASTFile())
+ return const_cast<FileEntry *>(&File->getFileEntry());
+ return nullptr;
+}
+
+CXModule clang_Module_getParent(CXModule CXMod) {
+ if (!CXMod)
+ return nullptr;
+ Module *Mod = static_cast<Module *>(CXMod);
+ return Mod->Parent;
+}
+
+CXString clang_Module_getName(CXModule CXMod) {
+ if (!CXMod)
+ return cxstring::createEmpty();
+ Module *Mod = static_cast<Module *>(CXMod);
+ return cxstring::createDup(Mod->Name);
+}
+
+CXString clang_Module_getFullName(CXModule CXMod) {
+ if (!CXMod)
+ return cxstring::createEmpty();
+ Module *Mod = static_cast<Module *>(CXMod);
+ return cxstring::createDup(Mod->getFullModuleName());
+}
+
+int clang_Module_isSystem(CXModule CXMod) {
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module *>(CXMod);
+ return Mod->IsSystem;
+}
+
+unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit TU,
+ CXModule CXMod) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return 0;
+ }
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module *>(CXMod);
+ FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager();
+ ArrayRef<const FileEntry *> TopHeaders = Mod->getTopHeaders(FileMgr);
+ return TopHeaders.size();
+}
+
+CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU, CXModule CXMod,
+ unsigned Index) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+ if (!CXMod)
+ return nullptr;
+ Module *Mod = static_cast<Module *>(CXMod);
+ FileManager &FileMgr = cxtu::getASTUnit(TU)->getFileManager();
+
+ ArrayRef<const FileEntry *> TopHeaders = Mod->getTopHeaders(FileMgr);
+ if (Index < TopHeaders.size())
+ return const_cast<FileEntry *>(TopHeaders[Index]);
+
+ return nullptr;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ AST instrospection.
+//===----------------------------------------------------------------------===//
+
+unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXConstructorDecl *Constructor =
+ D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
+ return (Constructor && Constructor->isDefaultConstructor()) ? 1 : 0;
+}
+
+unsigned clang_CXXConstructor_isCopyConstructor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXConstructorDecl *Constructor =
+ D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
+ return (Constructor && Constructor->isCopyConstructor()) ? 1 : 0;
+}
+
+unsigned clang_CXXConstructor_isMoveConstructor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXConstructorDecl *Constructor =
+ D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
+ return (Constructor && Constructor->isMoveConstructor()) ? 1 : 0;
+}
+
+unsigned clang_CXXConstructor_isConvertingConstructor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXConstructorDecl *Constructor =
+ D ? dyn_cast_or_null<CXXConstructorDecl>(D->getAsFunction()) : nullptr;
+ // Passing 'false' excludes constructors marked 'explicit'.
+ return (Constructor && Constructor->isConvertingConstructor(false)) ? 1 : 0;
+}
+
+unsigned clang_CXXField_isMutable(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ if (const auto D = cxcursor::getCursorDecl(C))
+ if (const auto FD = dyn_cast_or_null<FieldDecl>(D))
+ return FD->isMutable() ? 1 : 0;
+ return 0;
+}
+
+unsigned clang_CXXMethod_isPureVirtual(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXMethodDecl *Method =
+ D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
+ return (Method && Method->isVirtual() && Method->isPure()) ? 1 : 0;
+}
+
+unsigned clang_CXXMethod_isConst(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXMethodDecl *Method =
+ D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
+ return (Method && Method->getMethodQualifiers().hasConst()) ? 1 : 0;
+}
+
+unsigned clang_CXXMethod_isDefaulted(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXMethodDecl *Method =
+ D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
+ return (Method && Method->isDefaulted()) ? 1 : 0;
+}
+
+unsigned clang_CXXMethod_isStatic(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXMethodDecl *Method =
+ D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
+ return (Method && Method->isStatic()) ? 1 : 0;
+}
+
+unsigned clang_CXXMethod_isVirtual(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const CXXMethodDecl *Method =
+ D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
+ return (Method && Method->isVirtual()) ? 1 : 0;
+}
+
+unsigned clang_CXXRecord_isAbstract(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const auto *D = cxcursor::getCursorDecl(C);
+ const auto *RD = dyn_cast_or_null<CXXRecordDecl>(D);
+ if (RD)
+ RD = RD->getDefinition();
+ return (RD && RD->isAbstract()) ? 1 : 0;
+}
+
+unsigned clang_EnumDecl_isScoped(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ auto *Enum = dyn_cast_or_null<EnumDecl>(D);
+ return (Enum && Enum->isScoped()) ? 1 : 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute introspection.
+//===----------------------------------------------------------------------===//
+
+CXType clang_getIBOutletCollectionType(CXCursor C) {
+ if (C.kind != CXCursor_IBOutletCollectionAttr)
+ return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
+
+ const IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
+
+ return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C));
+}
+
+//===----------------------------------------------------------------------===//
+// Inspecting memory usage.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
+
+static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
+ enum CXTUResourceUsageKind k,
+ unsigned long amount) {
+ CXTUResourceUsageEntry entry = {k, amount};
+ entries.push_back(entry);
+}
+
+const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
+ const char *str = "";
+ switch (kind) {
+ case CXTUResourceUsage_AST:
+ str = "ASTContext: expressions, declarations, and types";
+ break;
+ case CXTUResourceUsage_Identifiers:
+ str = "ASTContext: identifiers";
+ break;
+ case CXTUResourceUsage_Selectors:
+ str = "ASTContext: selectors";
+ break;
+ case CXTUResourceUsage_GlobalCompletionResults:
+ str = "Code completion: cached global results";
+ break;
+ case CXTUResourceUsage_SourceManagerContentCache:
+ str = "SourceManager: content cache allocator";
+ break;
+ case CXTUResourceUsage_AST_SideTables:
+ str = "ASTContext: side tables";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_Malloc:
+ str = "SourceManager: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_MMap:
+ str = "SourceManager: mmap'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
+ str = "ExternalASTSource: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:
+ str = "ExternalASTSource: mmap'ed memory buffers";
+ break;
+ case CXTUResourceUsage_Preprocessor:
+ str = "Preprocessor: malloc'ed memory";
+ break;
+ case CXTUResourceUsage_PreprocessingRecord:
+ str = "Preprocessor: PreprocessingRecord";
+ break;
+ case CXTUResourceUsage_SourceManager_DataStructures:
+ str = "SourceManager: data structures and tables";
+ break;
+ case CXTUResourceUsage_Preprocessor_HeaderSearch:
+ str = "Preprocessor: header search tables";
+ break;
+ }
+ return str;
+}
+
+CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ CXTUResourceUsage usage = {(void *)nullptr, 0, nullptr};
+ return usage;
+ }
+
+ ASTUnit *astUnit = cxtu::getASTUnit(TU);
+ std::unique_ptr<MemUsageEntries> entries(new MemUsageEntries());
+ ASTContext &astContext = astUnit->getASTContext();
+
+ // How much memory is used by AST nodes and types?
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_AST,
+ (unsigned long)astContext.getASTAllocatedMemory());
+
+ // How much memory is used by identifiers?
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_Identifiers,
+ (unsigned long)astContext.Idents.getAllocator().getTotalMemory());
+
+ // How much memory is used for selectors?
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_Selectors,
+ (unsigned long)astContext.Selectors.getTotalMemory());
+
+ // How much memory is used by ASTContext's side tables?
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_AST_SideTables,
+ (unsigned long)astContext.getSideTableAllocatedMemory());
+
+ // How much memory is used for caching global code completion results?
+ unsigned long completionBytes = 0;
+ if (GlobalCodeCompletionAllocator *completionAllocator =
+ astUnit->getCachedCompletionAllocator().get()) {
+ completionBytes = completionAllocator->getTotalMemory();
+ }
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_GlobalCompletionResults, completionBytes);
+
+ // How much memory is being used by SourceManager's content cache?
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_SourceManagerContentCache,
+ (unsigned long)astContext.getSourceManager().getContentCacheSize());
+
+ // How much memory is being used by the MemoryBuffer's in SourceManager?
+ const SourceManager::MemoryBufferSizes &srcBufs =
+ astUnit->getSourceManager().getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_Malloc,
+ (unsigned long)srcBufs.malloc_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_MMap,
+ (unsigned long)srcBufs.mmap_bytes);
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_SourceManager_DataStructures,
+ (unsigned long)astContext.getSourceManager().getDataStructureSizes());
+
+ // How much memory is being used by the ExternalASTSource?
+ if (ExternalASTSource *esrc = astContext.getExternalSource()) {
+ const ExternalASTSource::MemoryBufferSizes &sizes =
+ esrc->getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,
+ (unsigned long)sizes.malloc_bytes);
+ createCXTUResourceUsageEntry(
+ *entries, CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
+ (unsigned long)sizes.mmap_bytes);
+ }
+
+ // How much memory is being used by the Preprocessor?
+ Preprocessor &pp = astUnit->getPreprocessor();
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Preprocessor,
+ pp.getTotalMemory());
+
+ if (PreprocessingRecord *pRec = pp.getPreprocessingRecord()) {
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_PreprocessingRecord,
+ pRec->getTotalMemory());
+ }
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_Preprocessor_HeaderSearch,
+ pp.getHeaderSearchInfo().getTotalMemory());
+
+ CXTUResourceUsage usage = {(void *)entries.get(), (unsigned)entries->size(),
+ !entries->empty() ? &(*entries)[0] : nullptr};
+ (void)entries.release();
+ return usage;
+}
+
+void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
+ if (usage.data)
+ delete (MemUsageEntries *)usage.data;
+}
+
+CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
+ CXSourceRangeList *skipped = new CXSourceRangeList;
+ skipped->count = 0;
+ skipped->ranges = nullptr;
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return skipped;
+ }
+
+ if (!file)
+ return skipped;
+
+ ASTUnit *astUnit = cxtu::getASTUnit(TU);
+ PreprocessingRecord *ppRec =
+ astUnit->getPreprocessor().getPreprocessingRecord();
+ if (!ppRec)
+ return skipped;
+
+ ASTContext &Ctx = astUnit->getASTContext();
+ SourceManager &sm = Ctx.getSourceManager();
+ FileEntry *fileEntry = static_cast<FileEntry *>(file);
+ FileID wantedFileID = sm.translateFile(fileEntry);
+ bool isMainFile = wantedFileID == sm.getMainFileID();
+
+ const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
+ std::vector<SourceRange> wantedRanges;
+ for (std::vector<SourceRange>::const_iterator i = SkippedRanges.begin(),
+ ei = SkippedRanges.end();
+ i != ei; ++i) {
+ if (sm.getFileID(i->getBegin()) == wantedFileID ||
+ sm.getFileID(i->getEnd()) == wantedFileID)
+ wantedRanges.push_back(*i);
+ else if (isMainFile && (astUnit->isInPreambleFileID(i->getBegin()) ||
+ astUnit->isInPreambleFileID(i->getEnd())))
+ wantedRanges.push_back(*i);
+ }
+
+ skipped->count = wantedRanges.size();
+ skipped->ranges = new CXSourceRange[skipped->count];
+ for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
+ skipped->ranges[i] = cxloc::translateSourceRange(Ctx, wantedRanges[i]);
+
+ return skipped;
+}
+
+CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit TU) {
+ CXSourceRangeList *skipped = new CXSourceRangeList;
+ skipped->count = 0;
+ skipped->ranges = nullptr;
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return skipped;
+ }
+
+ ASTUnit *astUnit = cxtu::getASTUnit(TU);
+ PreprocessingRecord *ppRec =
+ astUnit->getPreprocessor().getPreprocessingRecord();
+ if (!ppRec)
+ return skipped;
+
+ ASTContext &Ctx = astUnit->getASTContext();
+
+ const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
+
+ skipped->count = SkippedRanges.size();
+ skipped->ranges = new CXSourceRange[skipped->count];
+ for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
+ skipped->ranges[i] = cxloc::translateSourceRange(Ctx, SkippedRanges[i]);
+
+ return skipped;
+}
+
+void clang_disposeSourceRangeList(CXSourceRangeList *ranges) {
+ if (ranges) {
+ delete[] ranges->ranges;
+ delete ranges;
+ }
+}
+
+void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
+ CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);
+ for (unsigned I = 0; I != Usage.numEntries; ++I)
+ fprintf(stderr, " %s: %lu\n",
+ clang_getTUResourceUsageName(Usage.entries[I].kind),
+ Usage.entries[I].amount);
+
+ clang_disposeCXTUResourceUsage(Usage);
+}
+
+CXCursor clang_Cursor_getVarDeclInitializer(CXCursor cursor) {
+ const Decl *const D = getCursorDecl(cursor);
+ if (!D)
+ return clang_getNullCursor();
+ const auto *const VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return clang_getNullCursor();
+ const Expr *const Init = VD->getInit();
+ if (!Init)
+ return clang_getNullCursor();
+
+ return cxcursor::MakeCXCursor(Init, VD, cxcursor::getCursorTU(cursor));
+}
+
+int clang_Cursor_hasVarDeclGlobalStorage(CXCursor cursor) {
+ const Decl *const D = getCursorDecl(cursor);
+ if (!D)
+ return -1;
+ const auto *const VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return -1;
+
+ return VD->hasGlobalStorage();
+}
+
+int clang_Cursor_hasVarDeclExternalStorage(CXCursor cursor) {
+ const Decl *const D = getCursorDecl(cursor);
+ if (!D)
+ return -1;
+ const auto *const VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return -1;
+
+ return VD->hasExternalStorage();
+}
+
+//===----------------------------------------------------------------------===//
+// Misc. utility functions.
+//===----------------------------------------------------------------------===//
+
+/// Default to using our desired 8 MB stack size on "safety" threads.
+static unsigned SafetyStackThreadSize = DesiredStackSize;
+
+namespace clang {
+
+bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
+ unsigned Size) {
+ if (!Size)
+ Size = GetSafetyThreadStackSize();
+ if (Size && !getenv("LIBCLANG_NOTHREADS"))
+ return CRC.RunSafelyOnThread(Fn, Size);
+ return CRC.RunSafely(Fn);
+}
+
+unsigned GetSafetyThreadStackSize() { return SafetyStackThreadSize; }
+
+void SetSafetyThreadStackSize(unsigned Value) { SafetyStackThreadSize = Value; }
+
+} // namespace clang
+
+void clang::setThreadBackgroundPriority() {
+ if (getenv("LIBCLANG_BGPRIO_DISABLE"))
+ return;
+
+#if LLVM_ENABLE_THREADS
+ llvm::set_thread_priority(llvm::ThreadPriority::Background);
+#endif
+}
+
+void cxindex::printDiagsToStderr(ASTUnit *Unit) {
+ if (!Unit)
+ return;
+
+ for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
+ DEnd = Unit->stored_diag_end();
+ D != DEnd; ++D) {
+ CXStoredDiagnostic Diag(*D, Unit->getLangOpts());
+ CXString Msg =
+ clang_formatDiagnostic(&Diag, clang_defaultDiagnosticDisplayOptions());
+ fprintf(stderr, "%s\n", clang_getCString(Msg));
+ clang_disposeString(Msg);
+ }
+#ifdef _WIN32
+ // On Windows, force a flush, since there may be multiple copies of
+ // stderr and stdout in the file system, all with different buffers
+ // but writing to the same device.
+ fflush(stderr);
+#endif
+}
+
+MacroInfo *cxindex::getMacroInfo(const IdentifierInfo &II,
+ SourceLocation MacroDefLoc,
+ CXTranslationUnit TU) {
+ if (MacroDefLoc.isInvalid() || !TU)
+ return nullptr;
+ if (!II.hadMacroDefinition())
+ return nullptr;
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ Preprocessor &PP = Unit->getPreprocessor();
+ MacroDirective *MD = PP.getLocalMacroDirectiveHistory(&II);
+ if (MD) {
+ for (MacroDirective::DefInfo Def = MD->getDefinition(); Def;
+ Def = Def.getPreviousDefinition()) {
+ if (MacroDefLoc == Def.getMacroInfo()->getDefinitionLoc())
+ return Def.getMacroInfo();
+ }
+ }
+
+ return nullptr;
+}
+
+const MacroInfo *cxindex::getMacroInfo(const MacroDefinitionRecord *MacroDef,
+ CXTranslationUnit TU) {
+ if (!MacroDef || !TU)
+ return nullptr;
+ const IdentifierInfo *II = MacroDef->getName();
+ if (!II)
+ return nullptr;
+
+ return getMacroInfo(*II, MacroDef->getLocation(), TU);
+}
+
+MacroDefinitionRecord *
+cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, const Token &Tok,
+ CXTranslationUnit TU) {
+ if (!MI || !TU)
+ return nullptr;
+ if (Tok.isNot(tok::raw_identifier))
+ return nullptr;
+
+ if (MI->getNumTokens() == 0)
+ return nullptr;
+ SourceRange DefRange(MI->getReplacementToken(0).getLocation(),
+ MI->getDefinitionEndLoc());
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+
+ // Check that the token is inside the definition and not its argument list.
+ SourceManager &SM = Unit->getSourceManager();
+ if (SM.isBeforeInTranslationUnit(Tok.getLocation(), DefRange.getBegin()))
+ return nullptr;
+ if (SM.isBeforeInTranslationUnit(DefRange.getEnd(), Tok.getLocation()))
+ return nullptr;
+
+ Preprocessor &PP = Unit->getPreprocessor();
+ PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
+ if (!PPRec)
+ return nullptr;
+
+ IdentifierInfo &II = PP.getIdentifierTable().get(Tok.getRawIdentifier());
+ if (!II.hadMacroDefinition())
+ return nullptr;
+
+ // Check that the identifier is not one of the macro arguments.
+ if (llvm::is_contained(MI->params(), &II))
+ return nullptr;
+
+ MacroDirective *InnerMD = PP.getLocalMacroDirectiveHistory(&II);
+ if (!InnerMD)
+ return nullptr;
+
+ return PPRec->findMacroDefinition(InnerMD->getMacroInfo());
+}
+
+MacroDefinitionRecord *
+cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, SourceLocation Loc,
+ CXTranslationUnit TU) {
+ if (Loc.isInvalid() || !MI || !TU)
+ return nullptr;
+
+ if (MI->getNumTokens() == 0)
+ return nullptr;
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ Preprocessor &PP = Unit->getPreprocessor();
+ if (!PP.getPreprocessingRecord())
+ return nullptr;
+ Loc = Unit->getSourceManager().getSpellingLoc(Loc);
+ Token Tok;
+ if (PP.getRawToken(Loc, Tok))
+ return nullptr;
+
+ return checkForMacroInMacroDefinition(MI, Tok, TU);
+}
+
+CXString clang_getClangVersion() {
+ return cxstring::createDup(getClangFullVersion());
+}
+
+Logger &cxindex::Logger::operator<<(CXTranslationUnit TU) {
+ if (TU) {
+ if (ASTUnit *Unit = cxtu::getASTUnit(TU)) {
+ LogOS << '<' << Unit->getMainFileName() << '>';
+ if (Unit->isMainFileAST())
+ LogOS << " (" << Unit->getASTFileName() << ')';
+ return *this;
+ }
+ } else {
+ LogOS << "<NULL TU>";
+ }
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(const FileEntry *FE) {
+ *this << FE->getName();
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(CXCursor cursor) {
+ CXString cursorName = clang_getCursorDisplayName(cursor);
+ *this << cursorName << "@" << clang_getCursorLocation(cursor);
+ clang_disposeString(cursorName);
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(CXSourceLocation Loc) {
+ CXFile File;
+ unsigned Line, Column;
+ clang_getFileLocation(Loc, &File, &Line, &Column, nullptr);
+ CXString FileName = clang_getFileName(File);
+ *this << llvm::format("(%s:%d:%d)", clang_getCString(FileName), Line, Column);
+ clang_disposeString(FileName);
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(CXSourceRange range) {
+ CXSourceLocation BLoc = clang_getRangeStart(range);
+ CXSourceLocation ELoc = clang_getRangeEnd(range);
+
+ CXFile BFile;
+ unsigned BLine, BColumn;
+ clang_getFileLocation(BLoc, &BFile, &BLine, &BColumn, nullptr);
+
+ CXFile EFile;
+ unsigned ELine, EColumn;
+ clang_getFileLocation(ELoc, &EFile, &ELine, &EColumn, nullptr);
+
+ CXString BFileName = clang_getFileName(BFile);
+ if (BFile == EFile) {
+ *this << llvm::format("[%s %d:%d-%d:%d]", clang_getCString(BFileName),
+ BLine, BColumn, ELine, EColumn);
+ } else {
+ CXString EFileName = clang_getFileName(EFile);
+ *this << llvm::format("[%s:%d:%d - ", clang_getCString(BFileName), BLine,
+ BColumn)
+ << llvm::format("%s:%d:%d]", clang_getCString(EFileName), ELine,
+ EColumn);
+ clang_disposeString(EFileName);
+ }
+ clang_disposeString(BFileName);
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(CXString Str) {
+ *this << clang_getCString(Str);
+ return *this;
+}
+
+Logger &cxindex::Logger::operator<<(const llvm::format_object_base &Fmt) {
+ LogOS << Fmt;
+ return *this;
+}
+
+static llvm::ManagedStatic<std::mutex> LoggingMutex;
+
+cxindex::Logger::~Logger() {
+ std::lock_guard<std::mutex> L(*LoggingMutex);
+
+ static llvm::TimeRecord sBeginTR = llvm::TimeRecord::getCurrentTime();
+
+ raw_ostream &OS = llvm::errs();
+ OS << "[libclang:" << Name << ':';
+
+#ifdef USE_DARWIN_THREADS
+ // TODO: Portability.
+ mach_port_t tid = pthread_mach_thread_np(pthread_self());
+ OS << tid << ':';
+#endif
+
+ llvm::TimeRecord TR = llvm::TimeRecord::getCurrentTime();
+ OS << llvm::format("%7.4f] ", TR.getWallTime() - sBeginTR.getWallTime());
+ OS << Msg << '\n';
+
+ if (Trace) {
+ llvm::sys::PrintStackTrace(OS);
+ OS << "--------------------------------------------------\n";
+ }
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexCXX.cpp b/contrib/libs/clang14/tools/libclang/CIndexCXX.cpp
new file mode 100644
index 0000000000..a06fe7ba4a
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexCXX.cpp
@@ -0,0 +1,122 @@
+//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the libclang support for C++ cursors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXType.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+using namespace clang;
+using namespace clang::cxcursor;
+
+unsigned clang_isVirtualBase(CXCursor C) {
+ if (C.kind != CXCursor_CXXBaseSpecifier)
+ return 0;
+
+ const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return B->isVirtual();
+}
+
+enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
+ AccessSpecifier spec = AS_none;
+
+ if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
+ spec = getCursorDecl(C)->getAccess();
+ else if (C.kind == CXCursor_CXXBaseSpecifier)
+ spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
+ else
+ return CX_CXXInvalidAccessSpecifier;
+
+ switch (spec) {
+ case AS_public: return CX_CXXPublic;
+ case AS_protected: return CX_CXXProtected;
+ case AS_private: return CX_CXXPrivate;
+ case AS_none: return CX_CXXInvalidAccessSpecifier;
+ }
+
+ llvm_unreachable("Invalid AccessSpecifier!");
+}
+
+enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
+ using namespace clang::cxcursor;
+
+ switch (C.kind) {
+ case CXCursor_ClassTemplate:
+ case CXCursor_FunctionTemplate:
+ if (const TemplateDecl *Template
+ = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
+ return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
+ break;
+
+ case CXCursor_ClassTemplatePartialSpecialization:
+ if (const ClassTemplateSpecializationDecl *PartialSpec
+ = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
+ getCursorDecl(C))) {
+ switch (PartialSpec->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Struct: return CXCursor_StructDecl;
+ case TTK_Class: return CXCursor_ClassDecl;
+ case TTK_Union: return CXCursor_UnionDecl;
+ case TTK_Enum: return CXCursor_NoDeclFound;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return CXCursor_NoDeclFound;
+}
+
+CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ Decl *Template = nullptr;
+ if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
+ if (const ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
+ Template = PartialSpec->getSpecializedTemplate();
+ else if (const ClassTemplateSpecializationDecl *ClassSpec
+ = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> Result
+ = ClassSpec->getSpecializedTemplateOrPartial();
+ if (Result.is<ClassTemplateDecl *>())
+ Template = Result.get<ClassTemplateDecl *>();
+ else
+ Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
+
+ } else
+ Template = CXXRecord->getInstantiatedFromMemberClass();
+ } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ Template = Function->getPrimaryTemplate();
+ if (!Template)
+ Template = Function->getInstantiatedFromMemberFunction();
+ } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (Var->isStaticDataMember())
+ Template = Var->getInstantiatedFromStaticDataMember();
+ } else if (const RedeclarableTemplateDecl *Tmpl
+ = dyn_cast<RedeclarableTemplateDecl>(D))
+ Template = Tmpl->getInstantiatedFromMemberTemplate();
+
+ if (!Template)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(Template, getCursorTU(C));
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexCodeCompletion.cpp b/contrib/libs/clang14/tools/libclang/CIndexCodeCompletion.cpp
new file mode 100644
index 0000000000..0d75970f2f
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexCodeCompletion.cpp
@@ -0,0 +1,1046 @@
+//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Clang-C Source Indexing library hooks for
+// code completion.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CIndexDiagnostic.h"
+#include "CLog.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <atomic>
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#include "clang/Basic/Version.h"
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+using namespace clang;
+using namespace clang::cxindex;
+
+enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return CXCompletionChunk_Text;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ return CXCompletionChunk_TypedText;
+ case CodeCompletionString::CK_Text:
+ return CXCompletionChunk_Text;
+ case CodeCompletionString::CK_Optional:
+ return CXCompletionChunk_Optional;
+ case CodeCompletionString::CK_Placeholder:
+ return CXCompletionChunk_Placeholder;
+ case CodeCompletionString::CK_Informative:
+ return CXCompletionChunk_Informative;
+ case CodeCompletionString::CK_ResultType:
+ return CXCompletionChunk_ResultType;
+ case CodeCompletionString::CK_CurrentParameter:
+ return CXCompletionChunk_CurrentParameter;
+ case CodeCompletionString::CK_LeftParen:
+ return CXCompletionChunk_LeftParen;
+ case CodeCompletionString::CK_RightParen:
+ return CXCompletionChunk_RightParen;
+ case CodeCompletionString::CK_LeftBracket:
+ return CXCompletionChunk_LeftBracket;
+ case CodeCompletionString::CK_RightBracket:
+ return CXCompletionChunk_RightBracket;
+ case CodeCompletionString::CK_LeftBrace:
+ return CXCompletionChunk_LeftBrace;
+ case CodeCompletionString::CK_RightBrace:
+ return CXCompletionChunk_RightBrace;
+ case CodeCompletionString::CK_LeftAngle:
+ return CXCompletionChunk_LeftAngle;
+ case CodeCompletionString::CK_RightAngle:
+ return CXCompletionChunk_RightAngle;
+ case CodeCompletionString::CK_Comma:
+ return CXCompletionChunk_Comma;
+ case CodeCompletionString::CK_Colon:
+ return CXCompletionChunk_Colon;
+ case CodeCompletionString::CK_SemiColon:
+ return CXCompletionChunk_SemiColon;
+ case CodeCompletionString::CK_Equal:
+ return CXCompletionChunk_Equal;
+ case CodeCompletionString::CK_HorizontalSpace:
+ return CXCompletionChunk_HorizontalSpace;
+ case CodeCompletionString::CK_VerticalSpace:
+ return CXCompletionChunk_VerticalSpace;
+ }
+
+ llvm_unreachable("Invalid CompletionKind!");
+}
+
+CXString clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return cxstring::createNull();
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ case CodeCompletionString::CK_ResultType:
+ case CodeCompletionString::CK_Colon:
+ case CodeCompletionString::CK_SemiColon:
+ case CodeCompletionString::CK_Equal:
+ case CodeCompletionString::CK_HorizontalSpace:
+ case CodeCompletionString::CK_VerticalSpace:
+ return cxstring::createRef((*CCStr)[chunk_number].Text);
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return cxstring::createEmpty();
+ }
+
+ llvm_unreachable("Invalid CodeCompletionString Kind!");
+}
+
+
+CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return nullptr;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ case CodeCompletionString::CK_ResultType:
+ case CodeCompletionString::CK_Colon:
+ case CodeCompletionString::CK_SemiColon:
+ case CodeCompletionString::CK_Equal:
+ case CodeCompletionString::CK_HorizontalSpace:
+ case CodeCompletionString::CK_VerticalSpace:
+ return nullptr;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return (*CCStr)[chunk_number].Optional;
+ }
+
+ llvm_unreachable("Invalid CompletionKind!");
+}
+
+unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? CCStr->size() : 0;
+}
+
+unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
+}
+
+enum CXAvailabilityKind
+clang_getCompletionAvailability(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability())
+ : CXAvailability_Available;
+}
+
+unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string)
+{
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr ? CCStr->getAnnotationCount() : 0;
+}
+
+CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
+ unsigned annotation_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr ? cxstring::createRef(CCStr->getAnnotation(annotation_number))
+ : cxstring::createNull();
+}
+
+CXString
+clang_getCompletionParent(CXCompletionString completion_string,
+ CXCursorKind *kind) {
+ if (kind)
+ *kind = CXCursor_NotImplemented;
+
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr)
+ return cxstring::createNull();
+
+ return cxstring::createRef(CCStr->getParentContextName());
+}
+
+CXString
+clang_getCompletionBriefComment(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+
+ if (!CCStr)
+ return cxstring::createNull();
+
+ return cxstring::createRef(CCStr->getBriefComment());
+}
+
+namespace {
+
+/// The CXCodeCompleteResults structure we allocate internally;
+/// the client only sees the initial CXCodeCompleteResults structure.
+///
+/// Normally, clients of CXString shouldn't care whether or not a CXString is
+/// managed by a pool or by explicitly malloc'ed memory. But
+/// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can
+/// not rely on the StringPool in the TU.
+struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
+ AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);
+ ~AllocatedCXCodeCompleteResults();
+
+ /// Diagnostics produced while performing code completion.
+ SmallVector<StoredDiagnostic, 8> Diagnostics;
+
+ /// Allocated API-exposed wrappters for Diagnostics.
+ SmallVector<std::unique_ptr<CXStoredDiagnostic>, 8> DiagnosticsWrappers;
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+
+ /// Diag object
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diag;
+
+ /// Language options used to adjust source locations.
+ LangOptions LangOpts;
+
+ /// File manager, used for diagnostics.
+ IntrusiveRefCntPtr<FileManager> FileMgr;
+
+ /// Source manager, used for diagnostics.
+ IntrusiveRefCntPtr<SourceManager> SourceMgr;
+
+ /// Temporary buffers that will be deleted once we have finished with
+ /// the code-completion results.
+ SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
+
+ /// Allocator used to store globally cached code-completion results.
+ std::shared_ptr<clang::GlobalCodeCompletionAllocator>
+ CachedCompletionAllocator;
+
+ /// Allocator used to store code completion results.
+ std::shared_ptr<clang::GlobalCodeCompletionAllocator> CodeCompletionAllocator;
+
+ /// Context under which completion occurred.
+ enum clang::CodeCompletionContext::Kind ContextKind;
+
+ /// A bitfield representing the acceptable completions for the
+ /// current context.
+ unsigned long long Contexts;
+
+ /// The kind of the container for the current context for completions.
+ enum CXCursorKind ContainerKind;
+
+ /// The USR of the container for the current context for completions.
+ std::string ContainerUSR;
+
+ /// a boolean value indicating whether there is complete information
+ /// about the container
+ unsigned ContainerIsIncomplete;
+
+ /// A string containing the Objective-C selector entered thus far for a
+ /// message send.
+ std::string Selector;
+
+ /// Vector of fix-its for each completion result that *must* be applied
+ /// before that result for the corresponding completion item.
+ std::vector<std::vector<FixItHint>> FixItsVector;
+};
+
+} // end anonymous namespace
+
+unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results,
+ unsigned completion_index) {
+ AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
+
+ if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index)
+ return 0;
+
+ return static_cast<unsigned>(allocated_results->FixItsVector[completion_index].size());
+}
+
+CXString clang_getCompletionFixIt(CXCodeCompleteResults *results,
+ unsigned completion_index,
+ unsigned fixit_index,
+ CXSourceRange *replacement_range) {
+ AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
+
+ if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) {
+ if (replacement_range)
+ *replacement_range = clang_getNullRange();
+ return cxstring::createNull();
+ }
+
+ ArrayRef<FixItHint> FixIts = allocated_results->FixItsVector[completion_index];
+ if (FixIts.size() <= fixit_index) {
+ if (replacement_range)
+ *replacement_range = clang_getNullRange();
+ return cxstring::createNull();
+ }
+
+ const FixItHint &FixIt = FixIts[fixit_index];
+ if (replacement_range) {
+ *replacement_range = cxloc::translateSourceRange(
+ *allocated_results->SourceMgr, allocated_results->LangOpts,
+ FixIt.RemoveRange);
+ }
+
+ return cxstring::createRef(FixIt.CodeToInsert.c_str());
+}
+
+/// Tracks the number of code-completion result objects that are
+/// currently active.
+///
+/// Used for debugging purposes only.
+static std::atomic<unsigned> CodeCompletionResultObjects;
+
+AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
+ IntrusiveRefCntPtr<FileManager> FileMgr)
+ : CXCodeCompleteResults(), DiagOpts(new DiagnosticOptions),
+ Diag(new DiagnosticsEngine(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts)),
+ FileMgr(std::move(FileMgr)),
+ SourceMgr(new SourceManager(*Diag, *this->FileMgr)),
+ CodeCompletionAllocator(
+ std::make_shared<clang::GlobalCodeCompletionAllocator>()),
+ Contexts(CXCompletionContext_Unknown),
+ ContainerKind(CXCursor_InvalidCode), ContainerIsIncomplete(1) {
+ if (getenv("LIBCLANG_OBJTRACKING"))
+ fprintf(stderr, "+++ %u completion results\n",
+ ++CodeCompletionResultObjects);
+}
+
+AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
+ delete [] Results;
+
+ for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
+ delete TemporaryBuffers[I];
+
+ if (getenv("LIBCLANG_OBJTRACKING"))
+ fprintf(stderr, "--- %u completion results\n",
+ --CodeCompletionResultObjects);
+}
+
+static unsigned long long getContextsForContextKind(
+ enum CodeCompletionContext::Kind kind,
+ Sema &S) {
+ unsigned long long contexts = 0;
+ switch (kind) {
+ case CodeCompletionContext::CCC_OtherWithMacros: {
+ //We can allow macros here, but we don't know what else is permissible
+ //So we'll say the only thing permissible are macros
+ contexts = CXCompletionContext_MacroName;
+ break;
+ }
+ case CodeCompletionContext::CCC_TopLevel:
+ case CodeCompletionContext::CCC_ObjCIvarList:
+ case CodeCompletionContext::CCC_ClassStructUnion:
+ case CodeCompletionContext::CCC_Type: {
+ contexts = CXCompletionContext_AnyType |
+ CXCompletionContext_ObjCInterface;
+ if (S.getLangOpts().CPlusPlus) {
+ contexts |= CXCompletionContext_EnumTag |
+ CXCompletionContext_UnionTag |
+ CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ }
+ break;
+ }
+ case CodeCompletionContext::CCC_Statement: {
+ contexts = CXCompletionContext_AnyType |
+ CXCompletionContext_ObjCInterface |
+ CXCompletionContext_AnyValue;
+ if (S.getLangOpts().CPlusPlus) {
+ contexts |= CXCompletionContext_EnumTag |
+ CXCompletionContext_UnionTag |
+ CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ }
+ break;
+ }
+ case CodeCompletionContext::CCC_Expression: {
+ contexts = CXCompletionContext_AnyValue;
+ if (S.getLangOpts().CPlusPlus) {
+ contexts |= CXCompletionContext_AnyType |
+ CXCompletionContext_ObjCInterface |
+ CXCompletionContext_EnumTag |
+ CXCompletionContext_UnionTag |
+ CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ }
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCMessageReceiver: {
+ contexts = CXCompletionContext_ObjCObjectValue |
+ CXCompletionContext_ObjCSelectorValue |
+ CXCompletionContext_ObjCInterface;
+ if (S.getLangOpts().CPlusPlus) {
+ contexts |= CXCompletionContext_CXXClassTypeValue |
+ CXCompletionContext_AnyType |
+ CXCompletionContext_EnumTag |
+ CXCompletionContext_UnionTag |
+ CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ }
+ break;
+ }
+ case CodeCompletionContext::CCC_DotMemberAccess: {
+ contexts = CXCompletionContext_DotMemberAccess;
+ break;
+ }
+ case CodeCompletionContext::CCC_ArrowMemberAccess: {
+ contexts = CXCompletionContext_ArrowMemberAccess;
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCPropertyAccess: {
+ contexts = CXCompletionContext_ObjCPropertyAccess;
+ break;
+ }
+ case CodeCompletionContext::CCC_EnumTag: {
+ contexts = CXCompletionContext_EnumTag |
+ CXCompletionContext_NestedNameSpecifier;
+ break;
+ }
+ case CodeCompletionContext::CCC_UnionTag: {
+ contexts = CXCompletionContext_UnionTag |
+ CXCompletionContext_NestedNameSpecifier;
+ break;
+ }
+ case CodeCompletionContext::CCC_ClassOrStructTag: {
+ contexts = CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCProtocolName: {
+ contexts = CXCompletionContext_ObjCProtocol;
+ break;
+ }
+ case CodeCompletionContext::CCC_Namespace: {
+ contexts = CXCompletionContext_Namespace;
+ break;
+ }
+ case CodeCompletionContext::CCC_SymbolOrNewName:
+ case CodeCompletionContext::CCC_Symbol: {
+ contexts = CXCompletionContext_NestedNameSpecifier;
+ break;
+ }
+ case CodeCompletionContext::CCC_MacroNameUse: {
+ contexts = CXCompletionContext_MacroName;
+ break;
+ }
+ case CodeCompletionContext::CCC_NaturalLanguage: {
+ contexts = CXCompletionContext_NaturalLanguage;
+ break;
+ }
+ case CodeCompletionContext::CCC_IncludedFile: {
+ contexts = CXCompletionContext_IncludedFile;
+ break;
+ }
+ case CodeCompletionContext::CCC_SelectorName: {
+ contexts = CXCompletionContext_ObjCSelectorName;
+ break;
+ }
+ case CodeCompletionContext::CCC_ParenthesizedExpression: {
+ contexts = CXCompletionContext_AnyType |
+ CXCompletionContext_ObjCInterface |
+ CXCompletionContext_AnyValue;
+ if (S.getLangOpts().CPlusPlus) {
+ contexts |= CXCompletionContext_EnumTag |
+ CXCompletionContext_UnionTag |
+ CXCompletionContext_StructTag |
+ CXCompletionContext_ClassTag |
+ CXCompletionContext_NestedNameSpecifier;
+ }
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCInstanceMessage: {
+ contexts = CXCompletionContext_ObjCInstanceMessage;
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCClassMessage: {
+ contexts = CXCompletionContext_ObjCClassMessage;
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCInterfaceName: {
+ contexts = CXCompletionContext_ObjCInterface;
+ break;
+ }
+ case CodeCompletionContext::CCC_ObjCCategoryName: {
+ contexts = CXCompletionContext_ObjCCategory;
+ break;
+ }
+ case CodeCompletionContext::CCC_Other:
+ case CodeCompletionContext::CCC_ObjCInterface:
+ case CodeCompletionContext::CCC_ObjCImplementation:
+ case CodeCompletionContext::CCC_NewName:
+ case CodeCompletionContext::CCC_MacroName:
+ case CodeCompletionContext::CCC_PreprocessorExpression:
+ case CodeCompletionContext::CCC_PreprocessorDirective:
+ case CodeCompletionContext::CCC_Attribute:
+ case CodeCompletionContext::CCC_TypeQualifiers: {
+ //Only Clang results should be accepted, so we'll set all of the other
+ //context bits to 0 (i.e. the empty set)
+ contexts = CXCompletionContext_Unexposed;
+ break;
+ }
+ case CodeCompletionContext::CCC_Recovery: {
+ //We don't know what the current context is, so we'll return unknown
+ //This is the equivalent of setting all of the other context bits
+ contexts = CXCompletionContext_Unknown;
+ break;
+ }
+ }
+ return contexts;
+}
+
+namespace {
+ class CaptureCompletionResults : public CodeCompleteConsumer {
+ AllocatedCXCodeCompleteResults &AllocatedResults;
+ CodeCompletionTUInfo CCTUInfo;
+ SmallVector<CXCompletionResult, 16> StoredResults;
+ CXTranslationUnit *TU;
+ public:
+ CaptureCompletionResults(const CodeCompleteOptions &Opts,
+ AllocatedCXCodeCompleteResults &Results,
+ CXTranslationUnit *TranslationUnit)
+ : CodeCompleteConsumer(Opts), AllocatedResults(Results),
+ CCTUInfo(Results.CodeCompletionAllocator), TU(TranslationUnit) {}
+ ~CaptureCompletionResults() override { Finish(); }
+
+ void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override {
+ StoredResults.reserve(StoredResults.size() + NumResults);
+ if (includeFixIts())
+ AllocatedResults.FixItsVector.reserve(NumResults);
+ for (unsigned I = 0; I != NumResults; ++I) {
+ CodeCompletionString *StoredCompletion
+ = Results[I].CreateCodeCompletionString(S, Context, getAllocator(),
+ getCodeCompletionTUInfo(),
+ includeBriefComments());
+
+ CXCompletionResult R;
+ R.CursorKind = Results[I].CursorKind;
+ R.CompletionString = StoredCompletion;
+ StoredResults.push_back(R);
+ if (includeFixIts())
+ AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts));
+ }
+
+ enum CodeCompletionContext::Kind contextKind = Context.getKind();
+
+ AllocatedResults.ContextKind = contextKind;
+ AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);
+
+ AllocatedResults.Selector = "";
+ ArrayRef<IdentifierInfo *> SelIdents = Context.getSelIdents();
+ for (ArrayRef<IdentifierInfo *>::iterator I = SelIdents.begin(),
+ E = SelIdents.end();
+ I != E; ++I) {
+ if (IdentifierInfo *selIdent = *I)
+ AllocatedResults.Selector += selIdent->getName();
+ AllocatedResults.Selector += ":";
+ }
+
+ QualType baseType = Context.getBaseType();
+ NamedDecl *D = nullptr;
+
+ if (!baseType.isNull()) {
+ // Get the declaration for a class/struct/union/enum type
+ if (const TagType *Tag = baseType->getAs<TagType>())
+ D = Tag->getDecl();
+ // Get the @interface declaration for a (possibly-qualified) Objective-C
+ // object pointer type, e.g., NSString*
+ else if (const ObjCObjectPointerType *ObjPtr =
+ baseType->getAs<ObjCObjectPointerType>())
+ D = ObjPtr->getInterfaceDecl();
+ // Get the @interface declaration for an Objective-C object type
+ else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>())
+ D = Obj->getInterface();
+ // Get the class for a C++ injected-class-name
+ else if (const InjectedClassNameType *Injected =
+ baseType->getAs<InjectedClassNameType>())
+ D = Injected->getDecl();
+ }
+
+ if (D != nullptr) {
+ CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);
+
+ AllocatedResults.ContainerKind = clang_getCursorKind(cursor);
+
+ CXString CursorUSR = clang_getCursorUSR(cursor);
+ AllocatedResults.ContainerUSR = clang_getCString(CursorUSR);
+ clang_disposeString(CursorUSR);
+
+ const Type *type = baseType.getTypePtrOrNull();
+ if (type) {
+ AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();
+ }
+ else {
+ AllocatedResults.ContainerIsIncomplete = 1;
+ }
+ }
+ else {
+ AllocatedResults.ContainerKind = CXCursor_InvalidCode;
+ AllocatedResults.ContainerUSR.clear();
+ AllocatedResults.ContainerIsIncomplete = 1;
+ }
+ }
+
+ void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc,
+ bool Braced) override {
+ StoredResults.reserve(StoredResults.size() + NumCandidates);
+ for (unsigned I = 0; I != NumCandidates; ++I) {
+ CodeCompletionString *StoredCompletion =
+ Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
+ getCodeCompletionTUInfo(),
+ includeBriefComments(), Braced);
+
+ CXCompletionResult R;
+ R.CursorKind = CXCursor_OverloadCandidate;
+ R.CompletionString = StoredCompletion;
+ StoredResults.push_back(R);
+ }
+ }
+
+ CodeCompletionAllocator &getAllocator() override {
+ return *AllocatedResults.CodeCompletionAllocator;
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo;}
+
+ private:
+ void Finish() {
+ AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];
+ AllocatedResults.NumResults = StoredResults.size();
+ std::memcpy(AllocatedResults.Results, StoredResults.data(),
+ StoredResults.size() * sizeof(CXCompletionResult));
+ StoredResults.clear();
+ }
+ };
+}
+
+static CXCodeCompleteResults *
+clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
+ unsigned complete_line, unsigned complete_column,
+ ArrayRef<CXUnsavedFile> unsaved_files,
+ unsigned options) {
+ bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
+ bool SkipPreamble = options & CXCodeComplete_SkipPreamble;
+ bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts;
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
+#endif
+#endif
+ bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;
+
+ if (cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return nullptr;
+ }
+
+ ASTUnit *AST = cxtu::getASTUnit(TU);
+ if (!AST)
+ return nullptr;
+
+ CIndexer *CXXIdx = TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
+ setThreadBackgroundPriority();
+
+ ASTUnit::ConcurrencyCheck Check(*AST);
+
+ // Perform the remapping of source files.
+ SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+
+ for (auto &UF : unsaved_files) {
+ std::unique_ptr<llvm::MemoryBuffer> MB =
+ llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
+ RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));
+ }
+
+ if (EnableLogging) {
+ // FIXME: Add logging.
+ }
+
+ // Parse the resulting source file to find code-completion results.
+ AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults(
+ &AST->getFileManager());
+ Results->Results = nullptr;
+ Results->NumResults = 0;
+
+ // Create a code-completion consumer to capture the results.
+ CodeCompleteOptions Opts;
+ Opts.IncludeBriefComments = IncludeBriefComments;
+ Opts.LoadExternal = !SkipPreamble;
+ Opts.IncludeFixIts = IncludeFixIts;
+ CaptureCompletionResults Capture(Opts, *Results, &TU);
+
+ // Perform completion.
+ std::vector<const char *> CArgs;
+ for (const auto &Arg : TU->Arguments)
+ CArgs.push_back(Arg.c_str());
+ std::string CompletionInvocation =
+ llvm::formatv("-code-completion-at={0}:{1}:{2}", complete_filename,
+ complete_line, complete_column)
+ .str();
+ LibclangInvocationReporter InvocationReporter(
+ *CXXIdx, LibclangInvocationReporter::OperationKind::CompletionOperation,
+ TU->ParsingOptions, CArgs, CompletionInvocation, unsaved_files);
+ AST->CodeComplete(complete_filename, complete_line, complete_column,
+ RemappedFiles, (options & CXCodeComplete_IncludeMacros),
+ (options & CXCodeComplete_IncludeCodePatterns),
+ IncludeBriefComments, Capture,
+ CXXIdx->getPCHContainerOperations(), *Results->Diag,
+ Results->LangOpts, *Results->SourceMgr, *Results->FileMgr,
+ Results->Diagnostics, Results->TemporaryBuffers);
+
+ Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());
+
+ // Keep a reference to the allocator used for cached global completions, so
+ // that we can be sure that the memory used by our code completion strings
+ // doesn't get freed due to subsequent reparses (while the code completion
+ // results are still active).
+ Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();
+
+
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
+ SmallString<256> LogResult;
+ llvm::raw_svector_ostream os(LogResult);
+
+ // Figure out the language and whether or not it uses PCH.
+ const char *lang = 0;
+ bool usesPCH = false;
+
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ if (*I == 0)
+ continue;
+ if (strcmp(*I, "-x") == 0) {
+ if (I + 1 != E) {
+ lang = *(++I);
+ continue;
+ }
+ }
+ else if (strcmp(*I, "-include") == 0) {
+ if (I+1 != E) {
+ const char *arg = *(++I);
+ SmallString<512> pchName;
+ {
+ llvm::raw_svector_ostream os(pchName);
+ os << arg << ".pth";
+ }
+ pchName.push_back('\0');
+ llvm::sys::fs::file_status stat_results;
+ if (!llvm::sys::fs::status(pchName, stat_results))
+ usesPCH = true;
+ continue;
+ }
+ }
+ }
+
+ os << "{ ";
+ os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
+ os << ", \"numRes\": " << Results->NumResults;
+ os << ", \"diags\": " << Results->Diagnostics.size();
+ os << ", \"pch\": " << (usesPCH ? "true" : "false");
+ os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
+ const char *name = getlogin();
+ os << ", \"user\": \"" << (name ? name : "unknown") << '"';
+ os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
+ os << " }";
+
+ StringRef res = os.str();
+ if (res.size() > 0) {
+ do {
+ // Setup the UDP socket.
+ struct sockaddr_in servaddr;
+ bzero(&servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
+ if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
+ &servaddr.sin_addr) <= 0)
+ break;
+
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ break;
+
+ sendto(sockfd, res.data(), res.size(), 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ close(sockfd);
+ }
+ while (false);
+ }
+#endif
+#endif
+ return Results;
+}
+
+CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options) {
+ LOG_FUNC_SECTION {
+ *Log << TU << ' '
+ << complete_filename << ':' << complete_line << ':' << complete_column;
+ }
+
+ if (num_unsaved_files && !unsaved_files)
+ return nullptr;
+
+ CXCodeCompleteResults *result;
+ auto CodeCompleteAtImpl = [=, &result]() {
+ result = clang_codeCompleteAt_Impl(
+ TU, complete_filename, complete_line, complete_column,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
+ };
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, CodeCompleteAtImpl)) {
+ fprintf(stderr, "libclang: crash detected in code completion\n");
+ cxtu::getASTUnit(TU)->setUnsafeToFree(true);
+ return nullptr;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
+ PrintLibclangResourceUsage(TU);
+
+ return result;
+}
+
+unsigned clang_defaultCodeCompleteOptions(void) {
+ return CXCodeComplete_IncludeMacros;
+}
+
+void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
+ if (!ResultsIn)
+ return;
+
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ delete Results;
+}
+
+unsigned
+clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ if (!Results)
+ return 0;
+
+ return Results->Diagnostics.size();
+}
+
+CXDiagnostic
+clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
+ unsigned Index) {
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ if (!Results || Index >= Results->Diagnostics.size())
+ return nullptr;
+
+ CXStoredDiagnostic *Diag = Results->DiagnosticsWrappers[Index].get();
+ if (!Diag)
+ Diag = (Results->DiagnosticsWrappers[Index] =
+ std::make_unique<CXStoredDiagnostic>(
+ Results->Diagnostics[Index], Results->LangOpts))
+ .get();
+ return Diag;
+}
+
+unsigned long long
+clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ if (!Results)
+ return 0;
+
+ return Results->Contexts;
+}
+
+enum CXCursorKind clang_codeCompleteGetContainerKind(
+ CXCodeCompleteResults *ResultsIn,
+ unsigned *IsIncomplete) {
+ AllocatedCXCodeCompleteResults *Results =
+ static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
+ if (!Results)
+ return CXCursor_InvalidCode;
+
+ if (IsIncomplete != nullptr) {
+ *IsIncomplete = Results->ContainerIsIncomplete;
+ }
+
+ return Results->ContainerKind;
+}
+
+CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {
+ AllocatedCXCodeCompleteResults *Results =
+ static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
+ if (!Results)
+ return cxstring::createEmpty();
+
+ return cxstring::createRef(Results->ContainerUSR.c_str());
+}
+
+
+CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {
+ AllocatedCXCodeCompleteResults *Results =
+ static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
+ if (!Results)
+ return cxstring::createEmpty();
+
+ return cxstring::createDup(Results->Selector);
+}
+
+/// Simple utility function that appends a \p New string to the given
+/// \p Old string, using the \p Buffer for storage.
+///
+/// \param Old The string to which we are appending. This parameter will be
+/// updated to reflect the complete string.
+///
+///
+/// \param New The string to append to \p Old.
+///
+/// \param Buffer A buffer that stores the actual, concatenated string. It will
+/// be used if the old string is already-non-empty.
+static void AppendToString(StringRef &Old, StringRef New,
+ SmallString<256> &Buffer) {
+ if (Old.empty()) {
+ Old = New;
+ return;
+ }
+
+ if (Buffer.empty())
+ Buffer.append(Old.begin(), Old.end());
+ Buffer.append(New.begin(), New.end());
+ Old = Buffer.str();
+}
+
+/// Get the typed-text blocks from the given code-completion string
+/// and return them as a single string.
+///
+/// \param String The code-completion string whose typed-text blocks will be
+/// concatenated.
+///
+/// \param Buffer A buffer used for storage of the completed name.
+static StringRef GetTypedName(CodeCompletionString *String,
+ SmallString<256> &Buffer) {
+ StringRef Result;
+ for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end();
+ C != CEnd; ++C) {
+ if (C->Kind == CodeCompletionString::CK_TypedText)
+ AppendToString(Result, C->Text, Buffer);
+ }
+
+ return Result;
+}
+
+namespace {
+ struct OrderCompletionResults {
+ bool operator()(const CXCompletionResult &XR,
+ const CXCompletionResult &YR) const {
+ CodeCompletionString *X
+ = (CodeCompletionString *)XR.CompletionString;
+ CodeCompletionString *Y
+ = (CodeCompletionString *)YR.CompletionString;
+
+ SmallString<256> XBuffer;
+ StringRef XText = GetTypedName(X, XBuffer);
+ SmallString<256> YBuffer;
+ StringRef YText = GetTypedName(Y, YBuffer);
+
+ if (XText.empty() || YText.empty())
+ return !XText.empty();
+
+ int result = XText.compare_insensitive(YText);
+ if (result < 0)
+ return true;
+ if (result > 0)
+ return false;
+
+ result = XText.compare(YText);
+ return result < 0;
+ }
+ };
+}
+
+void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+ unsigned NumResults) {
+ std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.cpp b/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.cpp
new file mode 100644
index 0000000000..34792d5bdf
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.cpp
@@ -0,0 +1,468 @@
+//===- CIndexDiagnostic.cpp - Diagnostics C Interface ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the diagnostic functions of the Clang C interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CXTranslationUnit.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/DiagnosticRenderer.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::cxloc;
+using namespace clang::cxdiag;
+using namespace llvm;
+
+CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {}
+
+void
+CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) {
+ Diagnostics.push_back(std::move(D));
+}
+
+CXDiagnosticImpl::~CXDiagnosticImpl() {}
+
+namespace {
+class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
+ std::string Message;
+ CXSourceLocation Loc;
+public:
+ CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
+ : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)),
+ Loc(L) {}
+
+ ~CXDiagnosticCustomNoteImpl() override {}
+
+ CXDiagnosticSeverity getSeverity() const override {
+ return CXDiagnostic_Note;
+ }
+
+ CXSourceLocation getLocation() const override { return Loc; }
+
+ CXString getSpelling() const override {
+ return cxstring::createRef(Message.c_str());
+ }
+
+ CXString getDiagnosticOption(CXString *Disable) const override {
+ if (Disable)
+ *Disable = cxstring::createEmpty();
+ return cxstring::createEmpty();
+ }
+
+ unsigned getCategory() const override { return 0; }
+ CXString getCategoryText() const override { return cxstring::createEmpty(); }
+
+ unsigned getNumRanges() const override { return 0; }
+ CXSourceRange getRange(unsigned Range) const override {
+ return clang_getNullRange();
+ }
+ unsigned getNumFixIts() const override { return 0; }
+ CXString getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const override {
+ if (ReplacementRange)
+ *ReplacementRange = clang_getNullRange();
+ return cxstring::createEmpty();
+ }
+};
+
+class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
+public:
+ CXDiagnosticRenderer(const LangOptions &LangOpts,
+ DiagnosticOptions *DiagOpts,
+ CXDiagnosticSetImpl *mainSet)
+ : DiagnosticNoteRenderer(LangOpts, DiagOpts),
+ CurrentSet(mainSet), MainSet(mainSet) {}
+
+ ~CXDiagnosticRenderer() override {}
+
+ void beginDiagnostic(DiagOrStoredDiag D,
+ DiagnosticsEngine::Level Level) override {
+
+ const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
+ if (!SD)
+ return;
+
+ if (Level != DiagnosticsEngine::Note)
+ CurrentSet = MainSet;
+
+ auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
+ CXStoredDiagnostic &CD = *Owner;
+ CurrentSet->appendDiagnostic(std::move(Owner));
+
+ if (Level != DiagnosticsEngine::Note)
+ CurrentSet = &CD.getChildDiagnostics();
+ }
+
+ void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level, StringRef Message,
+ ArrayRef<CharSourceRange> Ranges,
+ DiagOrStoredDiag D) override {
+ if (!D.isNull())
+ return;
+
+ CXSourceLocation L;
+ if (Loc.hasManager())
+ L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
+ else
+ L = clang_getNullLocation();
+ CurrentSet->appendDiagnostic(
+ std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
+ }
+
+ void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges) override {}
+
+ void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange> &Ranges,
+ ArrayRef<FixItHint> Hints) override {}
+
+ void emitNote(FullSourceLoc Loc, StringRef Message) override {
+ CXSourceLocation L;
+ if (Loc.hasManager())
+ L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
+ else
+ L = clang_getNullLocation();
+ CurrentSet->appendDiagnostic(
+ std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
+ }
+
+ CXDiagnosticSetImpl *CurrentSet;
+ CXDiagnosticSetImpl *MainSet;
+};
+}
+
+CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
+ bool checkIfChanged) {
+ ASTUnit *AU = cxtu::getASTUnit(TU);
+
+ if (TU->Diagnostics && checkIfChanged) {
+ // In normal use, ASTUnit's diagnostics should not change unless we reparse.
+ // Currently they can only change by using the internal testing flag
+ // '-error-on-deserialized-decl' which will error during deserialization of
+ // a declaration. What will happen is:
+ //
+ // -c-index-test gets a CXTranslationUnit
+ // -checks the diagnostics, the diagnostics set is lazily created,
+ // no errors are reported
+ // -later does an operation, like annotation of tokens, that triggers
+ // -error-on-deserialized-decl, that will emit a diagnostic error,
+ // that ASTUnit will catch and add to its stored diagnostics vector.
+ // -c-index-test wants to check whether an error occurred after performing
+ // the operation but can only query the lazily created set.
+ //
+ // We check here if a new diagnostic was appended since the last time the
+ // diagnostic set was created, in which case we reset it.
+
+ CXDiagnosticSetImpl *
+ Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
+ if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
+ // Diagnostics in the ASTUnit were updated, reset the associated
+ // diagnostics.
+ delete Set;
+ TU->Diagnostics = nullptr;
+ }
+ }
+
+ if (!TU->Diagnostics) {
+ CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
+ TU->Diagnostics = Set;
+ IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
+ CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
+ &*DOpts, Set);
+
+ for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
+ ei = AU->stored_diag_end(); it != ei; ++it) {
+ Renderer.emitStoredDiagnostic(*it);
+ }
+ }
+ return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
+}
+
+//-----------------------------------------------------------------------------
+// C Interface Routines
+//-----------------------------------------------------------------------------
+unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
+ if (cxtu::isNotUsableTU(Unit)) {
+ LOG_BAD_TU(Unit);
+ return 0;
+ }
+ if (!cxtu::getASTUnit(Unit))
+ return 0;
+ return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
+}
+
+CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
+ if (cxtu::isNotUsableTU(Unit)) {
+ LOG_BAD_TU(Unit);
+ return nullptr;
+ }
+
+ CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
+ if (!D)
+ return nullptr;
+
+ CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
+ if (Index >= Diags->getNumDiagnostics())
+ return nullptr;
+
+ return Diags->getDiagnostic(Index);
+}
+
+CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
+ if (cxtu::isNotUsableTU(Unit)) {
+ LOG_BAD_TU(Unit);
+ return nullptr;
+ }
+ if (!cxtu::getASTUnit(Unit))
+ return nullptr;
+ return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
+}
+
+void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
+ // No-op. Kept as a legacy API. CXDiagnostics are now managed
+ // by the enclosing CXDiagnosticSet.
+}
+
+CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
+ if (!Diagnostic)
+ return cxstring::createEmpty();
+
+ CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
+
+ SmallString<256> Str;
+ llvm::raw_svector_ostream Out(Str);
+
+ if (Options & CXDiagnostic_DisplaySourceLocation) {
+ // Print source location (file:line), along with optional column
+ // and source ranges.
+ CXFile File;
+ unsigned Line, Column;
+ clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
+ &File, &Line, &Column, nullptr);
+ if (File) {
+ CXString FName = clang_getFileName(File);
+ Out << clang_getCString(FName) << ":" << Line << ":";
+ clang_disposeString(FName);
+ if (Options & CXDiagnostic_DisplayColumn)
+ Out << Column << ":";
+
+ if (Options & CXDiagnostic_DisplaySourceRanges) {
+ unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
+ bool PrintedRange = false;
+ for (unsigned I = 0; I != N; ++I) {
+ CXFile StartFile, EndFile;
+ CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
+
+ unsigned StartLine, StartColumn, EndLine, EndColumn;
+ clang_getSpellingLocation(clang_getRangeStart(Range),
+ &StartFile, &StartLine, &StartColumn,
+ nullptr);
+ clang_getSpellingLocation(clang_getRangeEnd(Range),
+ &EndFile, &EndLine, &EndColumn, nullptr);
+
+ if (StartFile != EndFile || StartFile != File)
+ continue;
+
+ Out << "{" << StartLine << ":" << StartColumn << "-"
+ << EndLine << ":" << EndColumn << "}";
+ PrintedRange = true;
+ }
+ if (PrintedRange)
+ Out << ":";
+ }
+
+ Out << " ";
+ }
+ }
+
+ /* Print warning/error/etc. */
+ switch (Severity) {
+ case CXDiagnostic_Ignored: llvm_unreachable("impossible");
+ case CXDiagnostic_Note: Out << "note: "; break;
+ case CXDiagnostic_Warning: Out << "warning: "; break;
+ case CXDiagnostic_Error: Out << "error: "; break;
+ case CXDiagnostic_Fatal: Out << "fatal error: "; break;
+ }
+
+ CXString Text = clang_getDiagnosticSpelling(Diagnostic);
+ if (clang_getCString(Text))
+ Out << clang_getCString(Text);
+ else
+ Out << "<no diagnostic text>";
+ clang_disposeString(Text);
+
+ if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
+ CXDiagnostic_DisplayCategoryName)) {
+ bool NeedBracket = true;
+ bool NeedComma = false;
+
+ if (Options & CXDiagnostic_DisplayOption) {
+ CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
+ if (const char *OptionText = clang_getCString(OptionName)) {
+ if (OptionText[0]) {
+ Out << " [" << OptionText;
+ NeedBracket = false;
+ NeedComma = true;
+ }
+ }
+ clang_disposeString(OptionName);
+ }
+
+ if (Options & (CXDiagnostic_DisplayCategoryId |
+ CXDiagnostic_DisplayCategoryName)) {
+ if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
+ if (Options & CXDiagnostic_DisplayCategoryId) {
+ if (NeedBracket)
+ Out << " [";
+ if (NeedComma)
+ Out << ", ";
+ Out << CategoryID;
+ NeedBracket = false;
+ NeedComma = true;
+ }
+
+ if (Options & CXDiagnostic_DisplayCategoryName) {
+ CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
+ if (NeedBracket)
+ Out << " [";
+ if (NeedComma)
+ Out << ", ";
+ Out << clang_getCString(CategoryName);
+ NeedBracket = false;
+ NeedComma = true;
+ clang_disposeString(CategoryName);
+ }
+ }
+ }
+
+ (void) NeedComma; // Silence dead store warning.
+ if (!NeedBracket)
+ Out << "]";
+ }
+
+ return cxstring::createDup(Out.str());
+}
+
+unsigned clang_defaultDiagnosticDisplayOptions() {
+ return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
+ CXDiagnostic_DisplayOption;
+}
+
+enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
+ return D->getSeverity();
+ return CXDiagnostic_Ignored;
+}
+
+CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
+ return D->getLocation();
+ return clang_getNullLocation();
+}
+
+CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getSpelling();
+ return cxstring::createEmpty();
+}
+
+CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
+ if (Disable)
+ *Disable = cxstring::createEmpty();
+
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getDiagnosticOption(Disable);
+
+ return cxstring::createEmpty();
+}
+
+unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getCategory();
+ return 0;
+}
+
+CXString clang_getDiagnosticCategoryName(unsigned Category) {
+ // Kept for backward compatibility.
+ return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
+}
+
+CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getCategoryText();
+ return cxstring::createEmpty();
+}
+
+unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getNumRanges();
+ return 0;
+}
+
+CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
+ CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
+ if (!D || Range >= D->getNumRanges())
+ return clang_getNullRange();
+ return D->getRange(Range);
+}
+
+unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
+ return D->getNumFixIts();
+ return 0;
+}
+
+CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
+ CXSourceRange *ReplacementRange) {
+ CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
+ if (!D || FixIt >= D->getNumFixIts()) {
+ if (ReplacementRange)
+ *ReplacementRange = clang_getNullRange();
+ return cxstring::createEmpty();
+ }
+ return D->getFixIt(FixIt, ReplacementRange);
+}
+
+void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
+ if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
+ if (D->isExternallyManaged())
+ delete D;
+ }
+}
+
+CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
+ unsigned Index) {
+ if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
+ if (Index < D->getNumDiagnostics())
+ return D->getDiagnostic(Index);
+ return nullptr;
+}
+
+CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
+ CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
+ return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
+ }
+ return nullptr;
+}
+
+unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
+ if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
+ return D->getNumDiagnostics();
+ return 0;
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.h b/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.h
new file mode 100644
index 0000000000..25589bb574
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexDiagnostic.h
@@ -0,0 +1,165 @@
+/*===-- CIndexDiagnostic.h - Diagnostics C Interface ------------*- C++ -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements the diagnostic functions of the Clang C interface. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CINDEXDIAGNOSTIC_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXDIAGNOSTIC_H
+
+#include "clang-c/Index.h"
+#include <memory>
+#include <vector>
+#include <assert.h>
+
+namespace clang {
+
+class LangOptions;
+class StoredDiagnostic;
+class CXDiagnosticImpl;
+
+class CXDiagnosticSetImpl {
+ std::vector<std::unique_ptr<CXDiagnosticImpl>> Diagnostics;
+ const bool IsExternallyManaged;
+public:
+ CXDiagnosticSetImpl(bool isManaged = false)
+ : IsExternallyManaged(isManaged) {}
+
+ virtual ~CXDiagnosticSetImpl();
+
+ size_t getNumDiagnostics() const {
+ return Diagnostics.size();
+ }
+
+ CXDiagnosticImpl *getDiagnostic(unsigned i) const {
+ assert(i < getNumDiagnostics());
+ return Diagnostics[i].get();
+ }
+
+ void appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D);
+
+ bool empty() const {
+ return Diagnostics.empty();
+ }
+
+ bool isExternallyManaged() const { return IsExternallyManaged; }
+};
+
+class CXDiagnosticImpl {
+public:
+ enum Kind { StoredDiagnosticKind, LoadedDiagnosticKind,
+ CustomNoteDiagnosticKind };
+
+ virtual ~CXDiagnosticImpl();
+
+ /// Return the severity of the diagnostic.
+ virtual CXDiagnosticSeverity getSeverity() const = 0;
+
+ /// Return the location of the diagnostic.
+ virtual CXSourceLocation getLocation() const = 0;
+
+ /// Return the spelling of the diagnostic.
+ virtual CXString getSpelling() const = 0;
+
+ /// Return the text for the diagnostic option.
+ virtual CXString getDiagnosticOption(CXString *Disable) const = 0;
+
+ /// Return the category of the diagnostic.
+ virtual unsigned getCategory() const = 0;
+
+ /// Return the category string of the diagnostic.
+ virtual CXString getCategoryText() const = 0;
+
+ /// Return the number of source ranges for the diagnostic.
+ virtual unsigned getNumRanges() const = 0;
+
+ /// Return the source ranges for the diagnostic.
+ virtual CXSourceRange getRange(unsigned Range) const = 0;
+
+ /// Return the number of FixIts.
+ virtual unsigned getNumFixIts() const = 0;
+
+ /// Return the FixIt information (source range and inserted text).
+ virtual CXString getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const = 0;
+
+ Kind getKind() const { return K; }
+
+ CXDiagnosticSetImpl &getChildDiagnostics() {
+ return ChildDiags;
+ }
+
+protected:
+ CXDiagnosticImpl(Kind k) : K(k) {}
+ CXDiagnosticSetImpl ChildDiags;
+
+ void append(std::unique_ptr<CXDiagnosticImpl> D) {
+ ChildDiags.appendDiagnostic(std::move(D));
+ }
+
+private:
+ Kind K;
+};
+
+/// The storage behind a CXDiagnostic
+struct CXStoredDiagnostic : public CXDiagnosticImpl {
+ const StoredDiagnostic &Diag;
+ const LangOptions &LangOpts;
+
+ CXStoredDiagnostic(const StoredDiagnostic &Diag,
+ const LangOptions &LangOpts)
+ : CXDiagnosticImpl(StoredDiagnosticKind),
+ Diag(Diag), LangOpts(LangOpts) { }
+
+ ~CXStoredDiagnostic() override {}
+
+ /// Return the severity of the diagnostic.
+ CXDiagnosticSeverity getSeverity() const override;
+
+ /// Return the location of the diagnostic.
+ CXSourceLocation getLocation() const override;
+
+ /// Return the spelling of the diagnostic.
+ CXString getSpelling() const override;
+
+ /// Return the text for the diagnostic option.
+ CXString getDiagnosticOption(CXString *Disable) const override;
+
+ /// Return the category of the diagnostic.
+ unsigned getCategory() const override;
+
+ /// Return the category string of the diagnostic.
+ CXString getCategoryText() const override;
+
+ /// Return the number of source ranges for the diagnostic.
+ unsigned getNumRanges() const override;
+
+ /// Return the source ranges for the diagnostic.
+ CXSourceRange getRange(unsigned Range) const override;
+
+ /// Return the number of FixIts.
+ unsigned getNumFixIts() const override;
+
+ /// Return the FixIt information (source range and inserted text).
+ CXString getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const override;
+
+ static bool classof(const CXDiagnosticImpl *D) {
+ return D->getKind() == StoredDiagnosticKind;
+ }
+};
+
+namespace cxdiag {
+CXDiagnosticSetImpl *lazyCreateDiags(CXTranslationUnit TU,
+ bool checkIfChanged = false);
+} // end namespace cxdiag
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CIndexHigh.cpp b/contrib/libs/clang14/tools/libclang/CIndexHigh.cpp
new file mode 100644
index 0000000000..0b49d1842e
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexHigh.cpp
@@ -0,0 +1,534 @@
+//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CursorVisitor.h"
+#include "CLog.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CXTranslationUnit.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+using namespace cxcursor;
+using namespace cxindex;
+
+static void getTopOverriddenMethods(CXTranslationUnit TU,
+ const Decl *D,
+ SmallVectorImpl<const Decl *> &Methods) {
+ if (!D)
+ return;
+ if (!isa<ObjCMethodDecl>(D) && !isa<CXXMethodDecl>(D))
+ return;
+
+ SmallVector<CXCursor, 8> Overridden;
+ cxcursor::getOverriddenCursors(cxcursor::MakeCXCursor(D, TU), Overridden);
+
+ if (Overridden.empty()) {
+ Methods.push_back(D->getCanonicalDecl());
+ return;
+ }
+
+ for (SmallVectorImpl<CXCursor>::iterator
+ I = Overridden.begin(), E = Overridden.end(); I != E; ++I)
+ getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods);
+}
+
+namespace {
+
+struct FindFileIdRefVisitData {
+ CXTranslationUnit TU;
+ FileID FID;
+ const Decl *Dcl;
+ int SelectorIdIdx;
+ CXCursorAndRangeVisitor visitor;
+
+ typedef SmallVector<const Decl *, 8> TopMethodsTy;
+ TopMethodsTy TopMethods;
+
+ FindFileIdRefVisitData(CXTranslationUnit TU, FileID FID,
+ const Decl *D, int selectorIdIdx,
+ CXCursorAndRangeVisitor visitor)
+ : TU(TU), FID(FID), SelectorIdIdx(selectorIdIdx), visitor(visitor) {
+ Dcl = getCanonical(D);
+ getTopOverriddenMethods(TU, Dcl, TopMethods);
+ }
+
+ ASTContext &getASTContext() const {
+ return cxtu::getASTUnit(TU)->getASTContext();
+ }
+
+ /// We are looking to find all semantically relevant identifiers,
+ /// so the definition of "canonical" here is different than in the AST, e.g.
+ ///
+ /// \code
+ /// class C {
+ /// C() {}
+ /// };
+ /// \endcode
+ ///
+ /// we consider the canonical decl of the constructor decl to be the class
+ /// itself, so both 'C' can be highlighted.
+ const Decl *getCanonical(const Decl *D) const {
+ if (!D)
+ return nullptr;
+
+ D = D->getCanonicalDecl();
+
+ if (const ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D)) {
+ if (ImplD->getClassInterface())
+ return getCanonical(ImplD->getClassInterface());
+
+ } else if (const CXXConstructorDecl *CXXCtorD =
+ dyn_cast<CXXConstructorDecl>(D)) {
+ return getCanonical(CXXCtorD->getParent());
+ }
+
+ return D;
+ }
+
+ bool isHit(const Decl *D) const {
+ if (!D)
+ return false;
+
+ D = getCanonical(D);
+ if (D == Dcl)
+ return true;
+
+ if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D))
+ return isOverriddingMethod(D);
+
+ return false;
+ }
+
+private:
+ bool isOverriddingMethod(const Decl *D) const {
+ if (llvm::is_contained(TopMethods, D))
+ return true;
+
+ TopMethodsTy methods;
+ getTopOverriddenMethods(TU, D, methods);
+ for (TopMethodsTy::iterator
+ I = methods.begin(), E = methods.end(); I != E; ++I) {
+ if (llvm::is_contained(TopMethods, *I))
+ return true;
+ }
+
+ return false;
+ }
+};
+
+} // end anonymous namespace.
+
+/// For a macro \arg Loc, returns the file spelling location and sets
+/// to \arg isMacroArg whether the spelling resides inside a macro definition or
+/// a macro argument.
+static SourceLocation getFileSpellingLoc(SourceManager &SM,
+ SourceLocation Loc,
+ bool &isMacroArg) {
+ assert(Loc.isMacroID());
+ SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc);
+ if (SpellLoc.isMacroID())
+ return getFileSpellingLoc(SM, SpellLoc, isMacroArg);
+
+ isMacroArg = SM.isMacroArgExpansion(Loc);
+ return SpellLoc;
+}
+
+static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ CXCursor declCursor = clang_getCursorReferenced(cursor);
+ if (!clang_isDeclaration(declCursor.kind))
+ return CXChildVisit_Recurse;
+
+ const Decl *D = cxcursor::getCursorDecl(declCursor);
+ if (!D)
+ return CXChildVisit_Continue;
+
+ FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data;
+ if (data->isHit(D)) {
+ cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor);
+
+ // We are looking for identifiers to highlight so for objc methods (and
+ // not a parameter) we can only highlight the selector identifiers.
+ if ((cursor.kind == CXCursor_ObjCClassMethodDecl ||
+ cursor.kind == CXCursor_ObjCInstanceMethodDecl) &&
+ cxcursor::getSelectorIdentifierIndex(cursor) == -1)
+ return CXChildVisit_Recurse;
+
+ if (clang_isExpression(cursor.kind)) {
+ if (cursor.kind == CXCursor_DeclRefExpr ||
+ cursor.kind == CXCursor_MemberRefExpr) {
+ // continue..
+
+ } else if (cursor.kind == CXCursor_ObjCMessageExpr &&
+ cxcursor::getSelectorIdentifierIndex(cursor) != -1) {
+ // continue..
+
+ } else
+ return CXChildVisit_Recurse;
+ }
+
+ SourceLocation
+ Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+ SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor);
+ if (SelIdLoc.isValid())
+ Loc = SelIdLoc;
+
+ ASTContext &Ctx = data->getASTContext();
+ SourceManager &SM = Ctx.getSourceManager();
+ bool isInMacroDef = false;
+ if (Loc.isMacroID()) {
+ bool isMacroArg;
+ Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
+ isInMacroDef = !isMacroArg;
+ }
+
+ // We are looking for identifiers in a specific file.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (LocInfo.first != data->FID)
+ return CXChildVisit_Recurse;
+
+ if (isInMacroDef) {
+ // FIXME: For a macro definition make sure that all expansions
+ // of it expand to the same reference before allowing to point to it.
+ return CXChildVisit_Recurse;
+ }
+
+ if (data->visitor.visit(data->visitor.context, cursor,
+ cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break)
+ return CXChildVisit_Break;
+ }
+ return CXChildVisit_Recurse;
+}
+
+static bool findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor,
+ const FileEntry *File,
+ CXCursorAndRangeVisitor Visitor) {
+ assert(clang_isDeclaration(declCursor.kind));
+ SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
+
+ FileID FID = SM.translateFile(File);
+ const Decl *Dcl = cxcursor::getCursorDecl(declCursor);
+ if (!Dcl)
+ return false;
+
+ FindFileIdRefVisitData data(TU, FID, Dcl,
+ cxcursor::getSelectorIdentifierIndex(declCursor),
+ Visitor);
+
+ if (const DeclContext *DC = Dcl->getParentFunctionOrMethod()) {
+ return clang_visitChildren(cxcursor::MakeCXCursor(cast<Decl>(DC), TU),
+ findFileIdRefVisit, &data);
+ }
+
+ SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
+ CursorVisitor FindIdRefsVisitor(TU,
+ findFileIdRefVisit, &data,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false,
+ Range,
+ /*VisitDeclsOnly=*/true);
+ return FindIdRefsVisitor.visitFileRegion();
+}
+
+namespace {
+
+struct FindFileMacroRefVisitData {
+ ASTUnit &Unit;
+ const FileEntry *File;
+ const IdentifierInfo *Macro;
+ CXCursorAndRangeVisitor visitor;
+
+ FindFileMacroRefVisitData(ASTUnit &Unit, const FileEntry *File,
+ const IdentifierInfo *Macro,
+ CXCursorAndRangeVisitor visitor)
+ : Unit(Unit), File(File), Macro(Macro), visitor(visitor) { }
+
+ ASTContext &getASTContext() const {
+ return Unit.getASTContext();
+ }
+};
+
+} // anonymous namespace
+
+static enum CXChildVisitResult findFileMacroRefVisit(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ const IdentifierInfo *Macro = nullptr;
+ if (cursor.kind == CXCursor_MacroDefinition)
+ Macro = getCursorMacroDefinition(cursor)->getName();
+ else if (cursor.kind == CXCursor_MacroExpansion)
+ Macro = getCursorMacroExpansion(cursor).getName();
+ if (!Macro)
+ return CXChildVisit_Continue;
+
+ FindFileMacroRefVisitData *data = (FindFileMacroRefVisitData *)client_data;
+ if (data->Macro != Macro)
+ return CXChildVisit_Continue;
+
+ SourceLocation
+ Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+
+ ASTContext &Ctx = data->getASTContext();
+ SourceManager &SM = Ctx.getSourceManager();
+ bool isInMacroDef = false;
+ if (Loc.isMacroID()) {
+ bool isMacroArg;
+ Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
+ isInMacroDef = !isMacroArg;
+ }
+
+ // We are looking for identifiers in a specific file.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (SM.getFileEntryForID(LocInfo.first) != data->File)
+ return CXChildVisit_Continue;
+
+ if (isInMacroDef) {
+ // FIXME: For a macro definition make sure that all expansions
+ // of it expand to the same reference before allowing to point to it.
+ return CXChildVisit_Continue;
+ }
+
+ if (data->visitor.visit(data->visitor.context, cursor,
+ cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break)
+ return CXChildVisit_Break;
+ return CXChildVisit_Continue;
+}
+
+static bool findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor,
+ const FileEntry *File,
+ CXCursorAndRangeVisitor Visitor) {
+ if (Cursor.kind != CXCursor_MacroDefinition &&
+ Cursor.kind != CXCursor_MacroExpansion)
+ return false;
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ SourceManager &SM = Unit->getSourceManager();
+
+ FileID FID = SM.translateFile(File);
+ const IdentifierInfo *Macro = nullptr;
+ if (Cursor.kind == CXCursor_MacroDefinition)
+ Macro = getCursorMacroDefinition(Cursor)->getName();
+ else
+ Macro = getCursorMacroExpansion(Cursor).getName();
+ if (!Macro)
+ return false;
+
+ FindFileMacroRefVisitData data(*Unit, File, Macro, Visitor);
+
+ SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
+ CursorVisitor FindMacroRefsVisitor(TU,
+ findFileMacroRefVisit, &data,
+ /*VisitPreprocessorLast=*/false,
+ /*VisitIncludedEntities=*/false,
+ Range);
+ return FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion();
+}
+
+namespace {
+
+struct FindFileIncludesVisitor {
+ ASTUnit &Unit;
+ const FileEntry *File;
+ CXCursorAndRangeVisitor visitor;
+
+ FindFileIncludesVisitor(ASTUnit &Unit, const FileEntry *File,
+ CXCursorAndRangeVisitor visitor)
+ : Unit(Unit), File(File), visitor(visitor) { }
+
+ ASTContext &getASTContext() const {
+ return Unit.getASTContext();
+ }
+
+ enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
+ if (cursor.kind != CXCursor_InclusionDirective)
+ return CXChildVisit_Continue;
+
+ SourceLocation
+ Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+
+ ASTContext &Ctx = getASTContext();
+ SourceManager &SM = Ctx.getSourceManager();
+
+ // We are looking for includes in a specific file.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (SM.getFileEntryForID(LocInfo.first) != File)
+ return CXChildVisit_Continue;
+
+ if (visitor.visit(visitor.context, cursor,
+ cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break)
+ return CXChildVisit_Break;
+ return CXChildVisit_Continue;
+ }
+
+ static enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<FindFileIncludesVisitor*>(client_data)->
+ visit(cursor, parent);
+ }
+};
+
+} // anonymous namespace
+
+static bool findIncludesInFile(CXTranslationUnit TU, const FileEntry *File,
+ CXCursorAndRangeVisitor Visitor) {
+ assert(TU && File && Visitor.visit);
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ SourceManager &SM = Unit->getSourceManager();
+
+ FileID FID = SM.translateFile(File);
+
+ FindFileIncludesVisitor IncludesVisitor(*Unit, File, Visitor);
+
+ SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
+ CursorVisitor InclusionCursorsVisitor(TU,
+ FindFileIncludesVisitor::visit,
+ &IncludesVisitor,
+ /*VisitPreprocessorLast=*/false,
+ /*VisitIncludedEntities=*/false,
+ Range);
+ return InclusionCursorsVisitor.visitPreprocessedEntitiesInRegion();
+}
+
+
+//===----------------------------------------------------------------------===//
+// libclang public APIs.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+CXResult clang_findReferencesInFile(CXCursor cursor, CXFile file,
+ CXCursorAndRangeVisitor visitor) {
+ LogRef Log = Logger::make(__func__);
+
+ if (clang_Cursor_isNull(cursor)) {
+ if (Log)
+ *Log << "Null cursor";
+ return CXResult_Invalid;
+ }
+ if (cursor.kind == CXCursor_NoDeclFound) {
+ if (Log)
+ *Log << "Got CXCursor_NoDeclFound";
+ return CXResult_Invalid;
+ }
+ if (!file) {
+ if (Log)
+ *Log << "Null file";
+ return CXResult_Invalid;
+ }
+ if (!visitor.visit) {
+ if (Log)
+ *Log << "Null visitor";
+ return CXResult_Invalid;
+ }
+
+ if (Log)
+ *Log << cursor << " @" << static_cast<const FileEntry *>(file);
+
+ ASTUnit *CXXUnit = cxcursor::getCursorASTUnit(cursor);
+ if (!CXXUnit)
+ return CXResult_Invalid;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ if (cursor.kind == CXCursor_MacroDefinition ||
+ cursor.kind == CXCursor_MacroExpansion) {
+ if (findMacroRefsInFile(cxcursor::getCursorTU(cursor),
+ cursor,
+ static_cast<const FileEntry *>(file),
+ visitor))
+ return CXResult_VisitBreak;
+ return CXResult_Success;
+ }
+
+ // We are interested in semantics of identifiers so for C++ constructor exprs
+ // prefer type references, e.g.:
+ //
+ // return MyStruct();
+ //
+ // for 'MyStruct' we'll have a cursor pointing at the constructor decl but
+ // we are actually interested in the type declaration.
+ cursor = cxcursor::getTypeRefCursor(cursor);
+
+ CXCursor refCursor = clang_getCursorReferenced(cursor);
+
+ if (!clang_isDeclaration(refCursor.kind)) {
+ if (Log)
+ *Log << "cursor is not referencing a declaration";
+ return CXResult_Invalid;
+ }
+
+ if (findIdRefsInFile(cxcursor::getCursorTU(cursor),
+ refCursor,
+ static_cast<const FileEntry *>(file),
+ visitor))
+ return CXResult_VisitBreak;
+ return CXResult_Success;
+}
+
+CXResult clang_findIncludesInFile(CXTranslationUnit TU, CXFile file,
+ CXCursorAndRangeVisitor visitor) {
+ if (cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return CXResult_Invalid;
+ }
+
+ LogRef Log = Logger::make(__func__);
+ if (!file) {
+ if (Log)
+ *Log << "Null file";
+ return CXResult_Invalid;
+ }
+ if (!visitor.visit) {
+ if (Log)
+ *Log << "Null visitor";
+ return CXResult_Invalid;
+ }
+
+ if (Log)
+ *Log << TU << " @" << static_cast<const FileEntry *>(file);
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return CXResult_Invalid;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ if (findIncludesInFile(TU, static_cast<const FileEntry *>(file), visitor))
+ return CXResult_VisitBreak;
+ return CXResult_Success;
+}
+
+static enum CXVisitorResult _visitCursorAndRange(void *context,
+ CXCursor cursor,
+ CXSourceRange range) {
+ CXCursorAndRangeVisitorBlock block = (CXCursorAndRangeVisitorBlock)context;
+ return INVOKE_BLOCK2(block, cursor, range);
+}
+
+CXResult clang_findReferencesInFileWithBlock(CXCursor cursor,
+ CXFile file,
+ CXCursorAndRangeVisitorBlock block) {
+ CXCursorAndRangeVisitor visitor = { block,
+ block ? _visitCursorAndRange : nullptr };
+ return clang_findReferencesInFile(cursor, file, visitor);
+}
+
+CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit TU,
+ CXFile file,
+ CXCursorAndRangeVisitorBlock block) {
+ CXCursorAndRangeVisitor visitor = { block,
+ block ? _visitCursorAndRange : nullptr };
+ return clang_findIncludesInFile(TU, file, visitor);
+}
+
+} // end: extern "C"
diff --git a/contrib/libs/clang14/tools/libclang/CIndexInclusionStack.cpp b/contrib/libs/clang14/tools/libclang/CIndexInclusionStack.cpp
new file mode 100644
index 0000000000..3e05cff12c
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexInclusionStack.cpp
@@ -0,0 +1,94 @@
+//===- CIndexInclusionStack.cpp - Clang-C Source Indexing Library ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a callback mechanism for clients to get the inclusion
+// stack from a translation unit.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXSourceLocation.h"
+#include "CXTranslationUnit.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+using namespace clang;
+
+namespace {
+void getInclusions(bool IsLocal, unsigned n, CXTranslationUnit TU,
+ CXInclusionVisitor CB, CXClientData clientData) {
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ SourceManager &SM = CXXUnit->getSourceManager();
+ ASTContext &Ctx = CXXUnit->getASTContext();
+ SmallVector<CXSourceLocation, 10> InclusionStack;
+ const bool HasPreamble = SM.getPreambleFileID().isValid();
+
+ for (unsigned i = 0 ; i < n ; ++i) {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SL =
+ IsLocal ? SM.getLocalSLocEntry(i) : SM.getLoadedSLocEntry(i, &Invalid);
+ if (!SL.isFile() || Invalid)
+ continue;
+
+ const SrcMgr::FileInfo &FI = SL.getFile();
+ if (!FI.getContentCache().OrigEntry)
+ continue;
+
+ // If this is the main file, and there is a preamble, skip this SLoc. The
+ // inclusions of the preamble already showed it.
+ SourceLocation L = FI.getIncludeLoc();
+ if (HasPreamble && CXXUnit->isInMainFileID(L))
+ continue;
+
+ // Build the inclusion stack.
+ InclusionStack.clear();
+ while (L.isValid()) {
+ PresumedLoc PLoc = SM.getPresumedLoc(L);
+ InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L));
+ L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation();
+ }
+
+ // If there is a preamble, the last entry is the "inclusion" of that
+ // preamble into the main file, which has the bogus entry of main.c:1:1
+ if (HasPreamble && !InclusionStack.empty())
+ InclusionStack.pop_back();
+
+ // Callback to the client.
+ // FIXME: We should have a function to construct CXFiles.
+ CB(static_cast<CXFile>(
+ const_cast<FileEntry *>(FI.getContentCache().OrigEntry)),
+ InclusionStack.data(), InclusionStack.size(), clientData);
+ }
+}
+} // namespace
+
+void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
+ CXClientData clientData) {
+ if (cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return;
+ }
+
+ SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
+ const unsigned n = SM.local_sloc_entry_size();
+
+ // In the case where all the SLocEntries are in an external source, traverse
+ // those SLocEntries as well. This is the case where we are looking
+ // at the inclusion stack of an AST/PCH file. Also, if we are not looking at
+ // a AST/PCH file, but this file has a pre-compiled preamble, we also need
+ // to look in that file.
+ if (n == 1 || SM.getPreambleFileID().isValid()) {
+ getInclusions(/*IsLocal=*/false, SM.loaded_sloc_entry_size(), TU, CB,
+ clientData);
+ }
+
+ // Not a PCH/AST file. Note, if there is a preamble, it could still be that
+ // there are #includes in this file (e.g. for any include after the first
+ // declaration).
+ if (n != 1)
+ getInclusions(/*IsLocal=*/true, n, TU, CB, clientData);
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexUSRs.cpp b/contrib/libs/clang14/tools/libclang/CIndexUSRs.cpp
new file mode 100644
index 0000000000..75bb3b0129
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexUSRs.cpp
@@ -0,0 +1,139 @@
+//===- CIndexUSRs.cpp - Clang-C Source Indexing Library -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the generation and use of USRs from CXEntities.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Index/USRGeneration.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::index;
+
+//===----------------------------------------------------------------------===//
+// API hooks.
+//===----------------------------------------------------------------------===//
+
+static inline StringRef extractUSRSuffix(StringRef s) {
+ return s.startswith("c:") ? s.substr(2) : "";
+}
+
+bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
+ return generateUSRForDecl(D, Buf);
+}
+
+CXString clang_getCursorUSR(CXCursor C) {
+ const CXCursorKind &K = clang_getCursorKind(C);
+
+ if (clang_isDeclaration(K)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return cxstring::createEmpty();
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ if (!TU)
+ return cxstring::createEmpty();
+
+ cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
+ if (!buf)
+ return cxstring::createEmpty();
+
+ bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
+ if (Ignore) {
+ buf->dispose();
+ return cxstring::createEmpty();
+ }
+
+ // Return the C-string, but don't make a copy since it is already in
+ // the string buffer.
+ buf->Data.push_back('\0');
+ return createCXString(buf);
+ }
+
+ if (K == CXCursor_MacroDefinition) {
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ if (!TU)
+ return cxstring::createEmpty();
+
+ cxstring::CXStringBuf *buf = cxstring::getCXStringBuf(TU);
+ if (!buf)
+ return cxstring::createEmpty();
+
+ bool Ignore = generateUSRForMacro(cxcursor::getCursorMacroDefinition(C),
+ cxtu::getASTUnit(TU)->getSourceManager(),
+ buf->Data);
+ if (Ignore) {
+ buf->dispose();
+ return cxstring::createEmpty();
+ }
+
+ // Return the C-string, but don't make a copy since it is already in
+ // the string buffer.
+ buf->Data.push_back('\0');
+ return createCXString(buf);
+ }
+
+ return cxstring::createEmpty();
+}
+
+CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ OS << extractUSRSuffix(clang_getCString(classUSR));
+ generateUSRForObjCIvar(name, OS);
+ return cxstring::createDup(OS.str());
+}
+
+CXString clang_constructUSR_ObjCMethod(const char *name,
+ unsigned isInstanceMethod,
+ CXString classUSR) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ OS << extractUSRSuffix(clang_getCString(classUSR));
+ generateUSRForObjCMethod(name, isInstanceMethod, OS);
+ return cxstring::createDup(OS.str());
+}
+
+CXString clang_constructUSR_ObjCClass(const char *name) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ generateUSRForObjCClass(name, OS);
+ return cxstring::createDup(OS.str());
+}
+
+CXString clang_constructUSR_ObjCProtocol(const char *name) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ generateUSRForObjCProtocol(name, OS);
+ return cxstring::createDup(OS.str());
+}
+
+CXString clang_constructUSR_ObjCCategory(const char *class_name,
+ const char *category_name) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ generateUSRForObjCCategory(class_name, category_name, OS);
+ return cxstring::createDup(OS.str());
+}
+
+CXString clang_constructUSR_ObjCProperty(const char *property,
+ CXString classUSR) {
+ SmallString<128> Buf(getUSRSpacePrefix());
+ llvm::raw_svector_ostream OS(Buf);
+ OS << extractUSRSuffix(clang_getCString(classUSR));
+ generateUSRForObjCProperty(property, /*isClassProp=*/false, OS);
+ return cxstring::createDup(OS.str());
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexer.cpp b/contrib/libs/clang14/tools/libclang/CIndexer.cpp
new file mode 100644
index 0000000000..8f3d548a1d
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexer.cpp
@@ -0,0 +1,222 @@
+//===- CIndexer.cpp - Clang-C Source Indexing Library ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Clang-C Source Indexing library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXString.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/YAMLParser.h"
+#include <cstdio>
+#include <mutex>
+
+#ifdef __CYGWIN__
+#include <cygwin/version.h>
+#include <sys/cygwin.h>
+#define _WIN32 1
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#elif defined(_AIX)
+#include <errno.h>
+#error #include <sys/ldr.h>
+#else
+#include <dlfcn.h>
+#endif
+
+using namespace clang;
+
+#ifdef _AIX
+namespace clang {
+namespace {
+
+template <typename LibClangPathType>
+void getClangResourcesPathImplAIX(LibClangPathType &LibClangPath) {
+ int PrevErrno = errno;
+
+ size_t BufSize = 2048u;
+ std::unique_ptr<char[]> Buf;
+ while (true) {
+ Buf = std::make_unique<char []>(BufSize);
+ errno = 0;
+ int Ret = loadquery(L_GETXINFO, Buf.get(), (unsigned int)BufSize);
+ if (Ret != -1)
+ break; // loadquery() was successful.
+ if (errno != ENOMEM)
+ llvm_unreachable("Encountered an unexpected loadquery() failure");
+
+ // errno == ENOMEM; try to allocate more memory.
+ if ((BufSize & ~((-1u) >> 1u)) != 0u)
+ llvm::report_fatal_error("BufSize needed for loadquery() too large");
+
+ Buf.release();
+ BufSize <<= 1u;
+ }
+
+ // Extract the function entry point from the function descriptor.
+ uint64_t EntryAddr =
+ reinterpret_cast<uintptr_t &>(clang_createTranslationUnit);
+
+ // Loop to locate the function entry point in the loadquery() results.
+ ld_xinfo *CurInfo = reinterpret_cast<ld_xinfo *>(Buf.get());
+ while (true) {
+ uint64_t CurTextStart = (uint64_t)CurInfo->ldinfo_textorg;
+ uint64_t CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize;
+ if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd)
+ break; // Successfully located.
+
+ if (CurInfo->ldinfo_next == 0u)
+ llvm::report_fatal_error("Cannot locate entry point in "
+ "the loadquery() results");
+ CurInfo = reinterpret_cast<ld_xinfo *>(reinterpret_cast<char *>(CurInfo) +
+ CurInfo->ldinfo_next);
+ }
+
+ LibClangPath += reinterpret_cast<char *>(CurInfo) + CurInfo->ldinfo_filename;
+ errno = PrevErrno;
+}
+
+} // end anonymous namespace
+} // end namespace clang
+#endif
+
+const std::string &CIndexer::getClangResourcesPath() {
+ // Did we already compute the path?
+ if (!ResourcesPath.empty())
+ return ResourcesPath;
+
+ SmallString<128> LibClangPath;
+
+ // Find the location where this library lives (libclang.dylib).
+#ifdef _WIN32
+ MEMORY_BASIC_INFORMATION mbi;
+ char path[MAX_PATH];
+ VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
+ sizeof(mbi));
+ GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
+
+#ifdef __CYGWIN__
+ char w32path[MAX_PATH];
+ strcpy(w32path, path);
+#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
+ cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH);
+#else
+ cygwin_conv_to_full_posix_path(w32path, path);
+#endif
+#endif
+
+ LibClangPath += path;
+#elif defined(_AIX)
+ getClangResourcesPathImplAIX(LibClangPath);
+#else
+ // This silly cast below avoids a C++ warning.
+ Dl_info info;
+ if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
+ llvm_unreachable("Call to dladdr() failed");
+
+ // We now have the CIndex directory, locate clang relative to it.
+ LibClangPath += info.dli_fname;
+#endif
+
+ // Cache our result.
+ ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath);
+ return ResourcesPath;
+}
+
+StringRef CIndexer::getClangToolchainPath() {
+ if (!ToolchainPath.empty())
+ return ToolchainPath;
+ StringRef ResourcePath = getClangResourcesPath();
+ ToolchainPath =
+ std::string(llvm::sys::path::parent_path(llvm::sys::path::parent_path(
+ llvm::sys::path::parent_path(ResourcePath))));
+ return ToolchainPath;
+}
+
+LibclangInvocationReporter::LibclangInvocationReporter(
+ CIndexer &Idx, OperationKind Op, unsigned ParseOptions,
+ llvm::ArrayRef<const char *> Args,
+ llvm::ArrayRef<std::string> InvocationArgs,
+ llvm::ArrayRef<CXUnsavedFile> UnsavedFiles) {
+ StringRef Path = Idx.getInvocationEmissionPath();
+ if (Path.empty())
+ return;
+
+ // Create a temporary file for the invocation log.
+ SmallString<256> TempPath;
+ TempPath = Path;
+ llvm::sys::path::append(TempPath, "libclang-%%%%%%%%%%%%");
+ int FD;
+ if (llvm::sys::fs::createUniqueFile(TempPath, FD, TempPath,
+ llvm::sys::fs::OF_Text))
+ return;
+ File = std::string(TempPath.begin(), TempPath.end());
+ llvm::raw_fd_ostream OS(FD, /*ShouldClose=*/true);
+
+ // Write out the information about the invocation to it.
+ auto WriteStringKey = [&OS](StringRef Key, StringRef Value) {
+ OS << R"(")" << Key << R"(":")";
+ OS << llvm::yaml::escape(Value) << '"';
+ };
+ OS << '{';
+ WriteStringKey("toolchain", Idx.getClangToolchainPath());
+ OS << ',';
+ WriteStringKey("libclang.operation",
+ Op == OperationKind::ParseOperation ? "parse" : "complete");
+ OS << ',';
+ OS << R"("libclang.opts":)" << ParseOptions;
+ OS << ',';
+ OS << R"("args":[)";
+ for (const auto &I : llvm::enumerate(Args)) {
+ if (I.index())
+ OS << ',';
+ OS << '"' << llvm::yaml::escape(I.value()) << '"';
+ }
+ if (!InvocationArgs.empty()) {
+ OS << R"(],"invocation-args":[)";
+ for (const auto &I : llvm::enumerate(InvocationArgs)) {
+ if (I.index())
+ OS << ',';
+ OS << '"' << llvm::yaml::escape(I.value()) << '"';
+ }
+ }
+ if (!UnsavedFiles.empty()) {
+ OS << R"(],"unsaved_file_hashes":[)";
+ for (const auto &UF : llvm::enumerate(UnsavedFiles)) {
+ if (UF.index())
+ OS << ',';
+ OS << '{';
+ WriteStringKey("name", UF.value().Filename);
+ OS << ',';
+ llvm::MD5 Hash;
+ Hash.update(getContents(UF.value()));
+ llvm::MD5::MD5Result Result;
+ Hash.final(Result);
+ SmallString<32> Digest = Result.digest();
+ WriteStringKey("md5", Digest);
+ OS << '}';
+ }
+ }
+ OS << "]}";
+}
+
+LibclangInvocationReporter::~LibclangInvocationReporter() {
+ if (!File.empty())
+ llvm::sys::fs::remove(File);
+}
diff --git a/contrib/libs/clang14/tools/libclang/CIndexer.h b/contrib/libs/clang14/tools/libclang/CIndexer.h
new file mode 100644
index 0000000000..de15cc34b5
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CIndexer.h
@@ -0,0 +1,153 @@
+//===- CIndexer.h - Clang-C Source Indexing Library -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CIndexer, a subclass of Indexer that provides extra
+// functionality needed by the CIndex library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H
+
+#include "clang-c/Index.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "llvm/ADT/STLExtras.h"
+#include <utility>
+
+namespace llvm {
+ class CrashRecoveryContext;
+}
+
+namespace clang {
+class ASTUnit;
+class MacroInfo;
+class MacroDefinitionRecord;
+class SourceLocation;
+class Token;
+class IdentifierInfo;
+
+class CIndexer {
+ bool OnlyLocalDecls;
+ bool DisplayDiagnostics;
+ unsigned Options; // CXGlobalOptFlags.
+
+ std::string ResourcesPath;
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+
+ std::string ToolchainPath;
+
+ std::string InvocationEmissionPath;
+
+public:
+ CIndexer(std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>())
+ : OnlyLocalDecls(false), DisplayDiagnostics(false),
+ Options(CXGlobalOpt_None), PCHContainerOps(std::move(PCHContainerOps)) {
+ }
+
+ /// Whether we only want to see "local" declarations (that did not
+ /// come from a previous precompiled header). If false, we want to see all
+ /// declarations.
+ bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; }
+
+ bool getDisplayDiagnostics() const { return DisplayDiagnostics; }
+ void setDisplayDiagnostics(bool Display = true) {
+ DisplayDiagnostics = Display;
+ }
+
+ std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const {
+ return PCHContainerOps;
+ }
+
+ unsigned getCXGlobalOptFlags() const { return Options; }
+ void setCXGlobalOptFlags(unsigned options) { Options = options; }
+
+ bool isOptEnabled(CXGlobalOptFlags opt) const {
+ return Options & opt;
+ }
+
+ /// Get the path of the clang resource files.
+ const std::string &getClangResourcesPath();
+
+ StringRef getClangToolchainPath();
+
+ void setInvocationEmissionPath(StringRef Str) {
+ InvocationEmissionPath = std::string(Str);
+ }
+
+ StringRef getInvocationEmissionPath() const { return InvocationEmissionPath; }
+};
+
+/// Logs information about a particular libclang operation like parsing to
+/// a new file in the invocation emission path.
+class LibclangInvocationReporter {
+public:
+ enum class OperationKind { ParseOperation, CompletionOperation };
+
+ LibclangInvocationReporter(CIndexer &Idx, OperationKind Op,
+ unsigned ParseOptions,
+ llvm::ArrayRef<const char *> Args,
+ llvm::ArrayRef<std::string> InvocationArgs,
+ llvm::ArrayRef<CXUnsavedFile> UnsavedFiles);
+ ~LibclangInvocationReporter();
+
+private:
+ std::string File;
+};
+
+ /// Return the current size to request for "safety".
+ unsigned GetSafetyThreadStackSize();
+
+ /// Set the current size to request for "safety" (or 0, if safety
+ /// threads should not be used).
+ void SetSafetyThreadStackSize(unsigned Value);
+
+ /// Execution the given code "safely", using crash recovery or safety
+ /// threads when possible.
+ ///
+ /// \return False if a crash was detected.
+ bool RunSafely(llvm::CrashRecoveryContext &CRC, llvm::function_ref<void()> Fn,
+ unsigned Size = 0);
+
+ /// Set the thread priority to background.
+ /// FIXME: Move to llvm/Support.
+ void setThreadBackgroundPriority();
+
+ /// Print libclang's resource usage to standard error.
+ void PrintLibclangResourceUsage(CXTranslationUnit TU);
+
+ namespace cxindex {
+ void printDiagsToStderr(ASTUnit *Unit);
+
+ /// If \c MacroDefLoc points at a macro definition with \c II as
+ /// its name, this retrieves its MacroInfo.
+ MacroInfo *getMacroInfo(const IdentifierInfo &II,
+ SourceLocation MacroDefLoc, CXTranslationUnit TU);
+
+ /// Retrieves the corresponding MacroInfo of a MacroDefinitionRecord.
+ const MacroInfo *getMacroInfo(const MacroDefinitionRecord *MacroDef,
+ CXTranslationUnit TU);
+
+ /// If \c Loc resides inside the definition of \c MI and it points at
+ /// an identifier that has ever been a macro name, this returns the latest
+ /// MacroDefinitionRecord for that name, otherwise it returns NULL.
+ MacroDefinitionRecord *checkForMacroInMacroDefinition(const MacroInfo *MI,
+ SourceLocation Loc,
+ CXTranslationUnit TU);
+
+ /// If \c Tok resides inside the definition of \c MI and it points at
+ /// an identifier that has ever been a macro name, this returns the latest
+ /// MacroDefinitionRecord for that name, otherwise it returns NULL.
+ MacroDefinitionRecord *checkForMacroInMacroDefinition(const MacroInfo *MI,
+ const Token &Tok,
+ CXTranslationUnit TU);
+ }
+ }
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CLog.h b/contrib/libs/clang14/tools/libclang/CLog.h
new file mode 100644
index 0000000000..ffd0940e7a
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CLog.h
@@ -0,0 +1,102 @@
+//===- CLog.h - Logging Interface -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+class format_object_base;
+}
+
+namespace clang {
+ class FileEntry;
+
+namespace cxindex {
+
+class Logger;
+typedef IntrusiveRefCntPtr<Logger> LogRef;
+
+/// Collects logging output and writes it to stderr when it's destructed.
+/// Common use case:
+/// \code
+/// if (LogRef Log = Logger::make(__func__)) {
+/// *Log << "stuff";
+/// }
+/// \endcode
+class Logger : public RefCountedBase<Logger> {
+ std::string Name;
+ bool Trace;
+ SmallString<64> Msg;
+ llvm::raw_svector_ostream LogOS;
+public:
+ static const char *getEnvVar() {
+ static const char *sCachedVar = ::getenv("LIBCLANG_LOGGING");
+ return sCachedVar;
+ }
+ static bool isLoggingEnabled() { return getEnvVar() != nullptr; }
+ static bool isStackTracingEnabled() {
+ if (const char *EnvOpt = Logger::getEnvVar())
+ return llvm::StringRef(EnvOpt) == "2";
+ return false;
+ }
+ static LogRef make(llvm::StringRef name,
+ bool trace = isStackTracingEnabled()) {
+ if (isLoggingEnabled())
+ return new Logger(name, trace);
+ return nullptr;
+ }
+
+ explicit Logger(llvm::StringRef name, bool trace)
+ : Name(std::string(name)), Trace(trace), LogOS(Msg) {}
+ ~Logger();
+
+ Logger &operator<<(CXTranslationUnit);
+ Logger &operator<<(const FileEntry *FE);
+ Logger &operator<<(CXCursor cursor);
+ Logger &operator<<(CXSourceLocation);
+ Logger &operator<<(CXSourceRange);
+ Logger &operator<<(CXString);
+ Logger &operator<<(llvm::StringRef Str) { LogOS << Str; return *this; }
+ Logger &operator<<(const char *Str) {
+ if (Str)
+ LogOS << Str;
+ return *this;
+ }
+ Logger &operator<<(unsigned long N) { LogOS << N; return *this; }
+ Logger &operator<<(long N) { LogOS << N ; return *this; }
+ Logger &operator<<(unsigned int N) { LogOS << N; return *this; }
+ Logger &operator<<(int N) { LogOS << N; return *this; }
+ Logger &operator<<(char C) { LogOS << C; return *this; }
+ Logger &operator<<(unsigned char C) { LogOS << C; return *this; }
+ Logger &operator<<(signed char C) { LogOS << C; return *this; }
+ Logger &operator<<(const llvm::format_object_base &Fmt);
+};
+
+}
+}
+
+/// Macros to automate common uses of Logger. Like this:
+/// \code
+/// LOG_FUNC_SECTION {
+/// *Log << "blah";
+/// }
+/// \endcode
+#define LOG_SECTION(NAME) \
+ if (clang::cxindex::LogRef Log = clang::cxindex::Logger::make(NAME))
+#define LOG_FUNC_SECTION LOG_SECTION(__func__)
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXComment.cpp b/contrib/libs/clang14/tools/libclang/CXComment.cpp
new file mode 100644
index 0000000000..bafaeb0fd0
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXComment.cpp
@@ -0,0 +1,408 @@
+//===- CXComment.cpp - libclang APIs for manipulating CXComments ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines all libclang APIs related to walking comment AST.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXComment.h"
+#include "CXCursor.h"
+#include "CXString.h"
+#include "clang-c/Documentation.h"
+#include "clang-c/Index.h"
+#include "clang/AST/Decl.h"
+#include "clang/Index/CommentToXML.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <climits>
+
+using namespace clang;
+using namespace clang::comments;
+using namespace clang::cxcomment;
+
+CXComment clang_Cursor_getParsedComment(CXCursor C) {
+ using namespace clang::cxcursor;
+
+ if (!clang_isDeclaration(C.kind))
+ return createCXComment(nullptr, nullptr);
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr);
+
+ return createCXComment(FC, getCursorTU(C));
+}
+
+enum CXCommentKind clang_Comment_getKind(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return CXComment_Null;
+
+ switch (C->getCommentKind()) {
+ case Comment::NoCommentKind:
+ return CXComment_Null;
+
+ case Comment::TextCommentKind:
+ return CXComment_Text;
+
+ case Comment::InlineCommandCommentKind:
+ return CXComment_InlineCommand;
+
+ case Comment::HTMLStartTagCommentKind:
+ return CXComment_HTMLStartTag;
+
+ case Comment::HTMLEndTagCommentKind:
+ return CXComment_HTMLEndTag;
+
+ case Comment::ParagraphCommentKind:
+ return CXComment_Paragraph;
+
+ case Comment::BlockCommandCommentKind:
+ return CXComment_BlockCommand;
+
+ case Comment::ParamCommandCommentKind:
+ return CXComment_ParamCommand;
+
+ case Comment::TParamCommandCommentKind:
+ return CXComment_TParamCommand;
+
+ case Comment::VerbatimBlockCommentKind:
+ return CXComment_VerbatimBlockCommand;
+
+ case Comment::VerbatimBlockLineCommentKind:
+ return CXComment_VerbatimBlockLine;
+
+ case Comment::VerbatimLineCommentKind:
+ return CXComment_VerbatimLine;
+
+ case Comment::FullCommentKind:
+ return CXComment_FullComment;
+ }
+ llvm_unreachable("unknown CommentKind");
+}
+
+unsigned clang_Comment_getNumChildren(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return 0;
+
+ return C->child_count();
+}
+
+CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
+ const Comment *C = getASTNode(CXC);
+ if (!C || ChildIdx >= C->child_count())
+ return createCXComment(nullptr, nullptr);
+
+ return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
+}
+
+unsigned clang_Comment_isWhitespace(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return false;
+
+ if (const TextComment *TC = dyn_cast<TextComment>(C))
+ return TC->isWhitespace();
+
+ if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
+ return PC->isWhitespace();
+
+ return false;
+}
+
+unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
+ const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
+ if (!ICC)
+ return false;
+
+ return ICC->hasTrailingNewline();
+}
+
+CXString clang_TextComment_getText(CXComment CXC) {
+ const TextComment *TC = getASTNodeAs<TextComment>(CXC);
+ if (!TC)
+ return cxstring::createNull();
+
+ return cxstring::createRef(TC->getText());
+}
+
+CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return cxstring::createNull();
+
+ const CommandTraits &Traits = getCommandTraits(CXC);
+ return cxstring::createRef(ICC->getCommandName(Traits));
+}
+
+enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return CXCommentInlineCommandRenderKind_Normal;
+
+ switch (ICC->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ return CXCommentInlineCommandRenderKind_Normal;
+
+ case InlineCommandComment::RenderBold:
+ return CXCommentInlineCommandRenderKind_Bold;
+
+ case InlineCommandComment::RenderMonospaced:
+ return CXCommentInlineCommandRenderKind_Monospaced;
+
+ case InlineCommandComment::RenderEmphasized:
+ return CXCommentInlineCommandRenderKind_Emphasized;
+
+ case InlineCommandComment::RenderAnchor:
+ return CXCommentInlineCommandRenderKind_Anchor;
+ }
+ llvm_unreachable("unknown InlineCommandComment::RenderKind");
+}
+
+unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return 0;
+
+ return ICC->getNumArgs();
+}
+
+CXString clang_InlineCommandComment_getArgText(CXComment CXC,
+ unsigned ArgIdx) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC || ArgIdx >= ICC->getNumArgs())
+ return cxstring::createNull();
+
+ return cxstring::createRef(ICC->getArgText(ArgIdx));
+}
+
+CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
+ const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
+ if (!HTC)
+ return cxstring::createNull();
+
+ return cxstring::createRef(HTC->getTagName());
+}
+
+unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST)
+ return false;
+
+ return HST->isSelfClosing();
+}
+
+unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST)
+ return 0;
+
+ return HST->getNumAttrs();
+}
+
+CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST || AttrIdx >= HST->getNumAttrs())
+ return cxstring::createNull();
+
+ return cxstring::createRef(HST->getAttr(AttrIdx).Name);
+}
+
+CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST || AttrIdx >= HST->getNumAttrs())
+ return cxstring::createNull();
+
+ return cxstring::createRef(HST->getAttr(AttrIdx).Value);
+}
+
+CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return cxstring::createNull();
+
+ const CommandTraits &Traits = getCommandTraits(CXC);
+ return cxstring::createRef(BCC->getCommandName(Traits));
+}
+
+unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return 0;
+
+ return BCC->getNumArgs();
+}
+
+CXString clang_BlockCommandComment_getArgText(CXComment CXC,
+ unsigned ArgIdx) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC || ArgIdx >= BCC->getNumArgs())
+ return cxstring::createNull();
+
+ return cxstring::createRef(BCC->getArgText(ArgIdx));
+}
+
+CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return createCXComment(nullptr, nullptr);
+
+ return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
+}
+
+CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC || !PCC->hasParamName())
+ return cxstring::createNull();
+
+ return cxstring::createRef(PCC->getParamNameAsWritten());
+}
+
+unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return false;
+
+ return PCC->isParamIndexValid();
+}
+
+unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
+ return ParamCommandComment::InvalidParamIndex;
+
+ return PCC->getParamIndex();
+}
+
+unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return false;
+
+ return PCC->isDirectionExplicit();
+}
+
+enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
+ CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return CXCommentParamPassDirection_In;
+
+ switch (PCC->getDirection()) {
+ case ParamCommandComment::In:
+ return CXCommentParamPassDirection_In;
+
+ case ParamCommandComment::Out:
+ return CXCommentParamPassDirection_Out;
+
+ case ParamCommandComment::InOut:
+ return CXCommentParamPassDirection_InOut;
+ }
+ llvm_unreachable("unknown ParamCommandComment::PassDirection");
+}
+
+CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->hasParamName())
+ return cxstring::createNull();
+
+ return cxstring::createRef(TPCC->getParamNameAsWritten());
+}
+
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC)
+ return false;
+
+ return TPCC->isPositionValid();
+}
+
+unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid())
+ return 0;
+
+ return TPCC->getDepth();
+}
+
+unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
+ return 0;
+
+ return TPCC->getIndex(Depth);
+}
+
+CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
+ const VerbatimBlockLineComment *VBL =
+ getASTNodeAs<VerbatimBlockLineComment>(CXC);
+ if (!VBL)
+ return cxstring::createNull();
+
+ return cxstring::createRef(VBL->getText());
+}
+
+CXString clang_VerbatimLineComment_getText(CXComment CXC) {
+ const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
+ if (!VLC)
+ return cxstring::createNull();
+
+ return cxstring::createRef(VLC->getText());
+}
+
+//===----------------------------------------------------------------------===//
+// Converting comments to XML.
+//===----------------------------------------------------------------------===//
+
+CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
+ const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
+ if (!HTC)
+ return cxstring::createNull();
+
+ CXTranslationUnit TU = CXC.TranslationUnit;
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new clang::index::CommentToXMLConverter();
+
+ SmallString<128> Text;
+ TU->CommentToXML->convertHTMLTagNodeToText(
+ HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
+ return cxstring::createDup(Text.str());
+}
+
+CXString clang_FullComment_getAsHTML(CXComment CXC) {
+ const FullComment *FC = getASTNodeAs<FullComment>(CXC);
+ if (!FC)
+ return cxstring::createNull();
+
+ CXTranslationUnit TU = CXC.TranslationUnit;
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new clang::index::CommentToXMLConverter();
+
+ SmallString<1024> HTML;
+ TU->CommentToXML
+ ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
+ return cxstring::createDup(HTML.str());
+}
+
+CXString clang_FullComment_getAsXML(CXComment CXC) {
+ const FullComment *FC = getASTNodeAs<FullComment>(CXC);
+ if (!FC)
+ return cxstring::createNull();
+
+ CXTranslationUnit TU = CXC.TranslationUnit;
+ if (!TU->CommentToXML)
+ TU->CommentToXML = new clang::index::CommentToXMLConverter();
+
+ SmallString<1024> XML;
+ TU->CommentToXML
+ ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
+ return cxstring::createDup(XML.str());
+}
+
diff --git a/contrib/libs/clang14/tools/libclang/CXComment.h b/contrib/libs/clang14/tools/libclang/CXComment.h
new file mode 100644
index 0000000000..30be06419c
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXComment.h
@@ -0,0 +1,63 @@
+//===- CXComment.h - Routines for manipulating CXComments -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXComments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXCOMMENT_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXCOMMENT_H
+
+#include "CXTranslationUnit.h"
+#include "clang-c/Documentation.h"
+#include "clang-c/Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Comment.h"
+#include "clang/Frontend/ASTUnit.h"
+
+namespace clang {
+namespace comments {
+ class CommandTraits;
+}
+
+namespace cxcomment {
+
+static inline CXComment createCXComment(const comments::Comment *C,
+ CXTranslationUnit TU) {
+ CXComment Result;
+ Result.ASTNode = C;
+ Result.TranslationUnit = TU;
+ return Result;
+}
+
+static inline const comments::Comment *getASTNode(CXComment CXC) {
+ return static_cast<const comments::Comment *>(CXC.ASTNode);
+}
+
+template<typename T>
+static inline const T *getASTNodeAs(CXComment CXC) {
+ const comments::Comment *C = getASTNode(CXC);
+ if (!C)
+ return nullptr;
+
+ return dyn_cast<T>(C);
+}
+
+static inline ASTContext &getASTContext(CXComment CXC) {
+ return cxtu::getASTUnit(CXC.TranslationUnit)->getASTContext();
+}
+
+static inline comments::CommandTraits &getCommandTraits(CXComment CXC) {
+ return getASTContext(CXC).getCommentCommandTraits();
+}
+
+} // end namespace cxcomment
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/libs/clang14/tools/libclang/CXCompilationDatabase.cpp b/contrib/libs/clang14/tools/libclang/CXCompilationDatabase.cpp
new file mode 100644
index 0000000000..2ca532659d
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXCompilationDatabase.cpp
@@ -0,0 +1,167 @@
+#include "clang-c/CXCompilationDatabase.h"
+#include "CXString.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include <cstdio>
+
+using namespace clang;
+using namespace clang::tooling;
+
+// FIXME: do something more useful with the error message
+CXCompilationDatabase
+clang_CompilationDatabase_fromDirectory(const char *BuildDir,
+ CXCompilationDatabase_Error *ErrorCode)
+{
+ std::string ErrorMsg;
+ CXCompilationDatabase_Error Err = CXCompilationDatabase_NoError;
+
+ std::unique_ptr<CompilationDatabase> db =
+ CompilationDatabase::loadFromDirectory(BuildDir, ErrorMsg);
+
+ if (!db) {
+ fprintf(stderr, "LIBCLANG TOOLING ERROR: %s\n", ErrorMsg.c_str());
+ Err = CXCompilationDatabase_CanNotLoadDatabase;
+ }
+
+ if (ErrorCode)
+ *ErrorCode = Err;
+
+ return db.release();
+}
+
+void
+clang_CompilationDatabase_dispose(CXCompilationDatabase CDb)
+{
+ delete static_cast<CompilationDatabase *>(CDb);
+}
+
+struct AllocatedCXCompileCommands
+{
+ std::vector<CompileCommand> CCmd;
+
+ AllocatedCXCompileCommands(std::vector<CompileCommand> Cmd)
+ : CCmd(std::move(Cmd)) {}
+};
+
+CXCompileCommands
+clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase CDb,
+ const char *CompleteFileName)
+{
+ if (CompilationDatabase *db = static_cast<CompilationDatabase *>(CDb)) {
+ std::vector<CompileCommand> CCmd(db->getCompileCommands(CompleteFileName));
+ if (!CCmd.empty())
+ return new AllocatedCXCompileCommands(std::move(CCmd));
+ }
+
+ return nullptr;
+}
+
+CXCompileCommands
+clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase CDb) {
+ if (CompilationDatabase *db = static_cast<CompilationDatabase *>(CDb)) {
+ std::vector<CompileCommand> CCmd(db->getAllCompileCommands());
+ if (!CCmd.empty())
+ return new AllocatedCXCompileCommands(std::move(CCmd));
+ }
+
+ return nullptr;
+}
+
+void
+clang_CompileCommands_dispose(CXCompileCommands Cmds)
+{
+ delete static_cast<AllocatedCXCompileCommands *>(Cmds);
+}
+
+unsigned
+clang_CompileCommands_getSize(CXCompileCommands Cmds)
+{
+ if (!Cmds)
+ return 0;
+
+ AllocatedCXCompileCommands *ACC =
+ static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+ return ACC->CCmd.size();
+}
+
+CXCompileCommand
+clang_CompileCommands_getCommand(CXCompileCommands Cmds, unsigned I)
+{
+ if (!Cmds)
+ return nullptr;
+
+ AllocatedCXCompileCommands *ACC =
+ static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+ if (I >= ACC->CCmd.size())
+ return nullptr;
+
+ return &ACC->CCmd[I];
+}
+
+CXString
+clang_CompileCommand_getDirectory(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return cxstring::createNull();
+
+ CompileCommand *cmd = static_cast<CompileCommand *>(CCmd);
+ return cxstring::createRef(cmd->Directory.c_str());
+}
+
+CXString
+clang_CompileCommand_getFilename(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return cxstring::createNull();
+
+ CompileCommand *cmd = static_cast<CompileCommand *>(CCmd);
+ return cxstring::createRef(cmd->Filename.c_str());
+}
+
+unsigned
+clang_CompileCommand_getNumArgs(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return 0;
+
+ return static_cast<CompileCommand *>(CCmd)->CommandLine.size();
+}
+
+CXString
+clang_CompileCommand_getArg(CXCompileCommand CCmd, unsigned Arg)
+{
+ if (!CCmd)
+ return cxstring::createNull();
+
+ CompileCommand *Cmd = static_cast<CompileCommand *>(CCmd);
+
+ if (Arg >= Cmd->CommandLine.size())
+ return cxstring::createNull();
+
+ return cxstring::createRef(Cmd->CommandLine[Arg].c_str());
+}
+
+unsigned
+clang_CompileCommand_getNumMappedSources(CXCompileCommand CCmd)
+{
+ // Left here for backward compatibility. No mapped sources exists in the C++
+ // backend anymore.
+ return 0;
+}
+
+CXString
+clang_CompileCommand_getMappedSourcePath(CXCompileCommand CCmd, unsigned I)
+{
+ // Left here for backward compatibility. No mapped sources exists in the C++
+ // backend anymore.
+ return cxstring::createNull();
+}
+
+CXString
+clang_CompileCommand_getMappedSourceContent(CXCompileCommand CCmd, unsigned I)
+{
+ // Left here for backward compatibility. No mapped sources exists in the C++
+ // backend anymore.
+ return cxstring::createNull();
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXCursor.cpp b/contrib/libs/clang14/tools/libclang/CXCursor.cpp
new file mode 100644
index 0000000000..db02e0c71c
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXCursor.cpp
@@ -0,0 +1,1721 @@
+//===- CXCursor.cpp - Routines for manipulating CXCursors -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors. It should be the
+// only file that has internal knowledge of the encoding of the data in
+// CXCursor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXCursor.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "CXType.h"
+#include "clang-c/Index.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+using namespace cxcursor;
+
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU) {
+ assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
+ CXCursor C = {K, 0, {nullptr, nullptr, TU}};
+ return C;
+}
+
+static CXCursorKind GetCursorKind(const Attr *A) {
+ assert(A && "Invalid arguments!");
+ switch (A->getKind()) {
+ default:
+ break;
+ case attr::IBAction:
+ return CXCursor_IBActionAttr;
+ case attr::IBOutlet:
+ return CXCursor_IBOutletAttr;
+ case attr::IBOutletCollection:
+ return CXCursor_IBOutletCollectionAttr;
+ case attr::Final:
+ return CXCursor_CXXFinalAttr;
+ case attr::Override:
+ return CXCursor_CXXOverrideAttr;
+ case attr::Annotate:
+ return CXCursor_AnnotateAttr;
+ case attr::AsmLabel:
+ return CXCursor_AsmLabelAttr;
+ case attr::Packed:
+ return CXCursor_PackedAttr;
+ case attr::Pure:
+ return CXCursor_PureAttr;
+ case attr::Const:
+ return CXCursor_ConstAttr;
+ case attr::NoDuplicate:
+ return CXCursor_NoDuplicateAttr;
+ case attr::CUDAConstant:
+ return CXCursor_CUDAConstantAttr;
+ case attr::CUDADevice:
+ return CXCursor_CUDADeviceAttr;
+ case attr::CUDAGlobal:
+ return CXCursor_CUDAGlobalAttr;
+ case attr::CUDAHost:
+ return CXCursor_CUDAHostAttr;
+ case attr::CUDAShared:
+ return CXCursor_CUDASharedAttr;
+ case attr::Visibility:
+ return CXCursor_VisibilityAttr;
+ case attr::DLLExport:
+ return CXCursor_DLLExport;
+ case attr::DLLImport:
+ return CXCursor_DLLImport;
+ case attr::NSReturnsRetained:
+ return CXCursor_NSReturnsRetained;
+ case attr::NSReturnsNotRetained:
+ return CXCursor_NSReturnsNotRetained;
+ case attr::NSReturnsAutoreleased:
+ return CXCursor_NSReturnsAutoreleased;
+ case attr::NSConsumesSelf:
+ return CXCursor_NSConsumesSelf;
+ case attr::NSConsumed:
+ return CXCursor_NSConsumed;
+ case attr::ObjCException:
+ return CXCursor_ObjCException;
+ case attr::ObjCNSObject:
+ return CXCursor_ObjCNSObject;
+ case attr::ObjCIndependentClass:
+ return CXCursor_ObjCIndependentClass;
+ case attr::ObjCPreciseLifetime:
+ return CXCursor_ObjCPreciseLifetime;
+ case attr::ObjCReturnsInnerPointer:
+ return CXCursor_ObjCReturnsInnerPointer;
+ case attr::ObjCRequiresSuper:
+ return CXCursor_ObjCRequiresSuper;
+ case attr::ObjCRootClass:
+ return CXCursor_ObjCRootClass;
+ case attr::ObjCSubclassingRestricted:
+ return CXCursor_ObjCSubclassingRestricted;
+ case attr::ObjCExplicitProtocolImpl:
+ return CXCursor_ObjCExplicitProtocolImpl;
+ case attr::ObjCDesignatedInitializer:
+ return CXCursor_ObjCDesignatedInitializer;
+ case attr::ObjCRuntimeVisible:
+ return CXCursor_ObjCRuntimeVisible;
+ case attr::ObjCBoxable:
+ return CXCursor_ObjCBoxable;
+ case attr::FlagEnum:
+ return CXCursor_FlagEnum;
+ case attr::Convergent:
+ return CXCursor_ConvergentAttr;
+ case attr::WarnUnused:
+ return CXCursor_WarnUnusedAttr;
+ case attr::WarnUnusedResult:
+ return CXCursor_WarnUnusedResultAttr;
+ case attr::Aligned:
+ return CXCursor_AlignedAttr;
+ }
+
+ return CXCursor_UnexposedAttr;
+}
+
+CXCursor cxcursor::MakeCXCursor(const Attr *A, const Decl *Parent,
+ CXTranslationUnit TU) {
+ assert(A && Parent && TU && "Invalid arguments!");
+ CXCursor C = {GetCursorKind(A), 0, {Parent, A, TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(const Decl *D, CXTranslationUnit TU,
+ SourceRange RegionOfInterest,
+ bool FirstInDeclGroup) {
+ assert(D && TU && "Invalid arguments!");
+
+ CXCursorKind K = getCursorKindForDecl(D);
+
+ if (K == CXCursor_ObjCClassMethodDecl ||
+ K == CXCursor_ObjCInstanceMethodDecl) {
+ int SelectorIdIndex = -1;
+ // Check if cursor points to a selector id.
+ if (RegionOfInterest.isValid() &&
+ RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) {
+ SmallVector<SourceLocation, 16> SelLocs;
+ cast<ObjCMethodDecl>(D)->getSelectorLocs(SelLocs);
+ SmallVectorImpl<SourceLocation>::iterator I =
+ llvm::find(SelLocs, RegionOfInterest.getBegin());
+ if (I != SelLocs.end())
+ SelectorIdIndex = I - SelLocs.begin();
+ }
+ CXCursor C = {K,
+ SelectorIdIndex,
+ {D, (void *)(intptr_t)(FirstInDeclGroup ? 1 : 0), TU}};
+ return C;
+ }
+
+ CXCursor C = {K, 0, {D, (void *)(intptr_t)(FirstInDeclGroup ? 1 : 0), TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
+ CXTranslationUnit TU,
+ SourceRange RegionOfInterest) {
+ assert(S && TU && "Invalid arguments!");
+ CXCursorKind K = CXCursor_NotImplemented;
+
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass:
+ break;
+
+ case Stmt::CaseStmtClass:
+ K = CXCursor_CaseStmt;
+ break;
+
+ case Stmt::DefaultStmtClass:
+ K = CXCursor_DefaultStmt;
+ break;
+
+ case Stmt::IfStmtClass:
+ K = CXCursor_IfStmt;
+ break;
+
+ case Stmt::SwitchStmtClass:
+ K = CXCursor_SwitchStmt;
+ break;
+
+ case Stmt::WhileStmtClass:
+ K = CXCursor_WhileStmt;
+ break;
+
+ case Stmt::DoStmtClass:
+ K = CXCursor_DoStmt;
+ break;
+
+ case Stmt::ForStmtClass:
+ K = CXCursor_ForStmt;
+ break;
+
+ case Stmt::GotoStmtClass:
+ K = CXCursor_GotoStmt;
+ break;
+
+ case Stmt::IndirectGotoStmtClass:
+ K = CXCursor_IndirectGotoStmt;
+ break;
+
+ case Stmt::ContinueStmtClass:
+ K = CXCursor_ContinueStmt;
+ break;
+
+ case Stmt::BreakStmtClass:
+ K = CXCursor_BreakStmt;
+ break;
+
+ case Stmt::ReturnStmtClass:
+ K = CXCursor_ReturnStmt;
+ break;
+
+ case Stmt::GCCAsmStmtClass:
+ K = CXCursor_GCCAsmStmt;
+ break;
+
+ case Stmt::MSAsmStmtClass:
+ K = CXCursor_MSAsmStmt;
+ break;
+
+ case Stmt::ObjCAtTryStmtClass:
+ K = CXCursor_ObjCAtTryStmt;
+ break;
+
+ case Stmt::ObjCAtCatchStmtClass:
+ K = CXCursor_ObjCAtCatchStmt;
+ break;
+
+ case Stmt::ObjCAtFinallyStmtClass:
+ K = CXCursor_ObjCAtFinallyStmt;
+ break;
+
+ case Stmt::ObjCAtThrowStmtClass:
+ K = CXCursor_ObjCAtThrowStmt;
+ break;
+
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ K = CXCursor_ObjCAtSynchronizedStmt;
+ break;
+
+ case Stmt::ObjCAutoreleasePoolStmtClass:
+ K = CXCursor_ObjCAutoreleasePoolStmt;
+ break;
+
+ case Stmt::ObjCForCollectionStmtClass:
+ K = CXCursor_ObjCForCollectionStmt;
+ break;
+
+ case Stmt::CXXCatchStmtClass:
+ K = CXCursor_CXXCatchStmt;
+ break;
+
+ case Stmt::CXXTryStmtClass:
+ K = CXCursor_CXXTryStmt;
+ break;
+
+ case Stmt::CXXForRangeStmtClass:
+ K = CXCursor_CXXForRangeStmt;
+ break;
+
+ case Stmt::SEHTryStmtClass:
+ K = CXCursor_SEHTryStmt;
+ break;
+
+ case Stmt::SEHExceptStmtClass:
+ K = CXCursor_SEHExceptStmt;
+ break;
+
+ case Stmt::SEHFinallyStmtClass:
+ K = CXCursor_SEHFinallyStmt;
+ break;
+
+ case Stmt::SEHLeaveStmtClass:
+ K = CXCursor_SEHLeaveStmt;
+ break;
+
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoreturnStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
+ case Stmt::ArrayTypeTraitExprClass:
+ case Stmt::AsTypeExprClass:
+ case Stmt::AtomicExprClass:
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::TypeTraitExprClass:
+ case Stmt::CoawaitExprClass:
+ case Stmt::ConceptSpecializationExprClass:
+ case Stmt::RequiresExprClass:
+ case Stmt::DependentCoawaitExprClass:
+ case Stmt::CoyieldExprClass:
+ case Stmt::CXXBindTemporaryExprClass:
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass:
+ case Stmt::CXXFoldExprClass:
+ case Stmt::CXXRewrittenBinaryOperatorClass:
+ case Stmt::CXXStdInitializerListExprClass:
+ case Stmt::CXXScalarValueInitExprClass:
+ case Stmt::CXXUuidofExprClass:
+ case Stmt::ChooseExprClass:
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::DesignatedInitUpdateExprClass:
+ case Stmt::ArrayInitLoopExprClass:
+ case Stmt::ArrayInitIndexExprClass:
+ case Stmt::ExprWithCleanupsClass:
+ case Stmt::ExpressionTraitExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ImplicitValueInitExprClass:
+ case Stmt::NoInitExprClass:
+ case Stmt::MaterializeTemporaryExprClass:
+ case Stmt::ObjCIndirectCopyRestoreExprClass:
+ case Stmt::OffsetOfExprClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::SourceLocExprClass:
+ case Stmt::ConvertVectorExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::ObjCArrayLiteralClass:
+ case Stmt::ObjCDictionaryLiteralClass:
+ case Stmt::ObjCBoxedExprClass:
+ case Stmt::ObjCSubscriptRefExprClass:
+ case Stmt::RecoveryExprClass:
+ case Stmt::SYCLUniqueStableNameExprClass:
+ K = CXCursor_UnexposedExpr;
+ break;
+
+ case Stmt::OpaqueValueExprClass:
+ if (Expr *Src = cast<OpaqueValueExpr>(S)->getSourceExpr())
+ return MakeCXCursor(Src, Parent, TU, RegionOfInterest);
+ K = CXCursor_UnexposedExpr;
+ break;
+
+ case Stmt::PseudoObjectExprClass:
+ return MakeCXCursor(cast<PseudoObjectExpr>(S)->getSyntacticForm(), Parent,
+ TU, RegionOfInterest);
+
+ case Stmt::CompoundStmtClass:
+ K = CXCursor_CompoundStmt;
+ break;
+
+ case Stmt::NullStmtClass:
+ K = CXCursor_NullStmt;
+ break;
+
+ case Stmt::LabelStmtClass:
+ K = CXCursor_LabelStmt;
+ break;
+
+ case Stmt::AttributedStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
+ case Stmt::DeclStmtClass:
+ K = CXCursor_DeclStmt;
+ break;
+
+ case Stmt::CapturedStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
+ case Stmt::IntegerLiteralClass:
+ K = CXCursor_IntegerLiteral;
+ break;
+
+ case Stmt::FixedPointLiteralClass:
+ K = CXCursor_FixedPointLiteral;
+ break;
+
+ case Stmt::FloatingLiteralClass:
+ K = CXCursor_FloatingLiteral;
+ break;
+
+ case Stmt::ImaginaryLiteralClass:
+ K = CXCursor_ImaginaryLiteral;
+ break;
+
+ case Stmt::StringLiteralClass:
+ K = CXCursor_StringLiteral;
+ break;
+
+ case Stmt::CharacterLiteralClass:
+ K = CXCursor_CharacterLiteral;
+ break;
+
+ case Stmt::ConstantExprClass:
+ return MakeCXCursor(cast<ConstantExpr>(S)->getSubExpr(), Parent, TU,
+ RegionOfInterest);
+
+ case Stmt::ParenExprClass:
+ K = CXCursor_ParenExpr;
+ break;
+
+ case Stmt::UnaryOperatorClass:
+ K = CXCursor_UnaryOperator;
+ break;
+
+ case Stmt::UnaryExprOrTypeTraitExprClass:
+ case Stmt::CXXNoexceptExprClass:
+ K = CXCursor_UnaryExpr;
+ break;
+
+ case Stmt::MSPropertySubscriptExprClass:
+ case Stmt::ArraySubscriptExprClass:
+ K = CXCursor_ArraySubscriptExpr;
+ break;
+
+ case Stmt::MatrixSubscriptExprClass:
+ // TODO: add support for MatrixSubscriptExpr.
+ K = CXCursor_UnexposedExpr;
+ break;
+
+ case Stmt::OMPArraySectionExprClass:
+ K = CXCursor_OMPArraySectionExpr;
+ break;
+
+ case Stmt::OMPArrayShapingExprClass:
+ K = CXCursor_OMPArrayShapingExpr;
+ break;
+
+ case Stmt::OMPIteratorExprClass:
+ K = CXCursor_OMPIteratorExpr;
+ break;
+
+ case Stmt::BinaryOperatorClass:
+ K = CXCursor_BinaryOperator;
+ break;
+
+ case Stmt::CompoundAssignOperatorClass:
+ K = CXCursor_CompoundAssignOperator;
+ break;
+
+ case Stmt::ConditionalOperatorClass:
+ K = CXCursor_ConditionalOperator;
+ break;
+
+ case Stmt::CStyleCastExprClass:
+ K = CXCursor_CStyleCastExpr;
+ break;
+
+ case Stmt::CompoundLiteralExprClass:
+ K = CXCursor_CompoundLiteralExpr;
+ break;
+
+ case Stmt::InitListExprClass:
+ K = CXCursor_InitListExpr;
+ break;
+
+ case Stmt::AddrLabelExprClass:
+ K = CXCursor_AddrLabelExpr;
+ break;
+
+ case Stmt::StmtExprClass:
+ K = CXCursor_StmtExpr;
+ break;
+
+ case Stmt::GenericSelectionExprClass:
+ K = CXCursor_GenericSelectionExpr;
+ break;
+
+ case Stmt::GNUNullExprClass:
+ K = CXCursor_GNUNullExpr;
+ break;
+
+ case Stmt::CXXStaticCastExprClass:
+ K = CXCursor_CXXStaticCastExpr;
+ break;
+
+ case Stmt::CXXDynamicCastExprClass:
+ K = CXCursor_CXXDynamicCastExpr;
+ break;
+
+ case Stmt::CXXReinterpretCastExprClass:
+ K = CXCursor_CXXReinterpretCastExpr;
+ break;
+
+ case Stmt::CXXConstCastExprClass:
+ K = CXCursor_CXXConstCastExpr;
+ break;
+
+ case Stmt::CXXFunctionalCastExprClass:
+ K = CXCursor_CXXFunctionalCastExpr;
+ break;
+
+ case Stmt::CXXAddrspaceCastExprClass:
+ K = CXCursor_CXXAddrspaceCastExpr;
+ break;
+
+ case Stmt::CXXTypeidExprClass:
+ K = CXCursor_CXXTypeidExpr;
+ break;
+
+ case Stmt::CXXBoolLiteralExprClass:
+ K = CXCursor_CXXBoolLiteralExpr;
+ break;
+
+ case Stmt::CXXNullPtrLiteralExprClass:
+ K = CXCursor_CXXNullPtrLiteralExpr;
+ break;
+
+ case Stmt::CXXThisExprClass:
+ K = CXCursor_CXXThisExpr;
+ break;
+
+ case Stmt::CXXThrowExprClass:
+ K = CXCursor_CXXThrowExpr;
+ break;
+
+ case Stmt::CXXNewExprClass:
+ K = CXCursor_CXXNewExpr;
+ break;
+
+ case Stmt::CXXDeleteExprClass:
+ K = CXCursor_CXXDeleteExpr;
+ break;
+
+ case Stmt::ObjCStringLiteralClass:
+ K = CXCursor_ObjCStringLiteral;
+ break;
+
+ case Stmt::ObjCEncodeExprClass:
+ K = CXCursor_ObjCEncodeExpr;
+ break;
+
+ case Stmt::ObjCSelectorExprClass:
+ K = CXCursor_ObjCSelectorExpr;
+ break;
+
+ case Stmt::ObjCProtocolExprClass:
+ K = CXCursor_ObjCProtocolExpr;
+ break;
+
+ case Stmt::ObjCBoolLiteralExprClass:
+ K = CXCursor_ObjCBoolLiteralExpr;
+ break;
+
+ case Stmt::ObjCAvailabilityCheckExprClass:
+ K = CXCursor_ObjCAvailabilityCheckExpr;
+ break;
+
+ case Stmt::ObjCBridgedCastExprClass:
+ K = CXCursor_ObjCBridgedCastExpr;
+ break;
+
+ case Stmt::BlockExprClass:
+ K = CXCursor_BlockExpr;
+ break;
+
+ case Stmt::PackExpansionExprClass:
+ K = CXCursor_PackExpansionExpr;
+ break;
+
+ case Stmt::SizeOfPackExprClass:
+ K = CXCursor_SizeOfPackExpr;
+ break;
+
+ case Stmt::DeclRefExprClass:
+ if (const ImplicitParamDecl *IPD = dyn_cast_or_null<ImplicitParamDecl>(
+ cast<DeclRefExpr>(S)->getDecl())) {
+ if (const ObjCMethodDecl *MD =
+ dyn_cast<ObjCMethodDecl>(IPD->getDeclContext())) {
+ if (MD->getSelfDecl() == IPD) {
+ K = CXCursor_ObjCSelfExpr;
+ break;
+ }
+ }
+ }
+
+ K = CXCursor_DeclRefExpr;
+ break;
+
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::SubstNonTypeTemplateParmExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ case Stmt::FunctionParmPackExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::TypoExprClass: // A typo could actually be a DeclRef or a MemberRef
+ K = CXCursor_DeclRefExpr;
+ break;
+
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::MemberExprClass:
+ case Stmt::MSPropertyRefExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ObjCIvarRefExprClass:
+ case Stmt::ObjCPropertyRefExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ K = CXCursor_MemberRefExpr;
+ break;
+
+ case Stmt::CallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::CUDAKernelCallExprClass:
+ case Stmt::CXXConstructExprClass:
+ case Stmt::CXXInheritedCtorInitExprClass:
+ case Stmt::CXXTemporaryObjectExprClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::UserDefinedLiteralClass:
+ K = CXCursor_CallExpr;
+ break;
+
+ case Stmt::LambdaExprClass:
+ K = CXCursor_LambdaExpr;
+ break;
+
+ case Stmt::ObjCMessageExprClass: {
+ K = CXCursor_ObjCMessageExpr;
+ int SelectorIdIndex = -1;
+ // Check if cursor points to a selector id.
+ if (RegionOfInterest.isValid() &&
+ RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) {
+ SmallVector<SourceLocation, 16> SelLocs;
+ cast<ObjCMessageExpr>(S)->getSelectorLocs(SelLocs);
+ SmallVectorImpl<SourceLocation>::iterator I =
+ llvm::find(SelLocs, RegionOfInterest.getBegin());
+ if (I != SelLocs.end())
+ SelectorIdIndex = I - SelLocs.begin();
+ }
+ CXCursor C = {K, 0, {Parent, S, TU}};
+ return getSelectorIdentifierCursor(SelectorIdIndex, C);
+ }
+
+ case Stmt::MSDependentExistsStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+ case Stmt::OMPCanonicalLoopClass:
+ K = CXCursor_OMPCanonicalLoop;
+ break;
+ case Stmt::OMPMetaDirectiveClass:
+ K = CXCursor_OMPMetaDirective;
+ break;
+ case Stmt::OMPParallelDirectiveClass:
+ K = CXCursor_OMPParallelDirective;
+ break;
+ case Stmt::OMPSimdDirectiveClass:
+ K = CXCursor_OMPSimdDirective;
+ break;
+ case Stmt::OMPTileDirectiveClass:
+ K = CXCursor_OMPTileDirective;
+ break;
+ case Stmt::OMPUnrollDirectiveClass:
+ K = CXCursor_OMPUnrollDirective;
+ break;
+ case Stmt::OMPForDirectiveClass:
+ K = CXCursor_OMPForDirective;
+ break;
+ case Stmt::OMPForSimdDirectiveClass:
+ K = CXCursor_OMPForSimdDirective;
+ break;
+ case Stmt::OMPSectionsDirectiveClass:
+ K = CXCursor_OMPSectionsDirective;
+ break;
+ case Stmt::OMPSectionDirectiveClass:
+ K = CXCursor_OMPSectionDirective;
+ break;
+ case Stmt::OMPSingleDirectiveClass:
+ K = CXCursor_OMPSingleDirective;
+ break;
+ case Stmt::OMPMasterDirectiveClass:
+ K = CXCursor_OMPMasterDirective;
+ break;
+ case Stmt::OMPCriticalDirectiveClass:
+ K = CXCursor_OMPCriticalDirective;
+ break;
+ case Stmt::OMPParallelForDirectiveClass:
+ K = CXCursor_OMPParallelForDirective;
+ break;
+ case Stmt::OMPParallelForSimdDirectiveClass:
+ K = CXCursor_OMPParallelForSimdDirective;
+ break;
+ case Stmt::OMPParallelMasterDirectiveClass:
+ K = CXCursor_OMPParallelMasterDirective;
+ break;
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ K = CXCursor_OMPParallelSectionsDirective;
+ break;
+ case Stmt::OMPTaskDirectiveClass:
+ K = CXCursor_OMPTaskDirective;
+ break;
+ case Stmt::OMPTaskyieldDirectiveClass:
+ K = CXCursor_OMPTaskyieldDirective;
+ break;
+ case Stmt::OMPBarrierDirectiveClass:
+ K = CXCursor_OMPBarrierDirective;
+ break;
+ case Stmt::OMPTaskwaitDirectiveClass:
+ K = CXCursor_OMPTaskwaitDirective;
+ break;
+ case Stmt::OMPTaskgroupDirectiveClass:
+ K = CXCursor_OMPTaskgroupDirective;
+ break;
+ case Stmt::OMPFlushDirectiveClass:
+ K = CXCursor_OMPFlushDirective;
+ break;
+ case Stmt::OMPDepobjDirectiveClass:
+ K = CXCursor_OMPDepobjDirective;
+ break;
+ case Stmt::OMPScanDirectiveClass:
+ K = CXCursor_OMPScanDirective;
+ break;
+ case Stmt::OMPOrderedDirectiveClass:
+ K = CXCursor_OMPOrderedDirective;
+ break;
+ case Stmt::OMPAtomicDirectiveClass:
+ K = CXCursor_OMPAtomicDirective;
+ break;
+ case Stmt::OMPTargetDirectiveClass:
+ K = CXCursor_OMPTargetDirective;
+ break;
+ case Stmt::OMPTargetDataDirectiveClass:
+ K = CXCursor_OMPTargetDataDirective;
+ break;
+ case Stmt::OMPTargetEnterDataDirectiveClass:
+ K = CXCursor_OMPTargetEnterDataDirective;
+ break;
+ case Stmt::OMPTargetExitDataDirectiveClass:
+ K = CXCursor_OMPTargetExitDataDirective;
+ break;
+ case Stmt::OMPTargetParallelDirectiveClass:
+ K = CXCursor_OMPTargetParallelDirective;
+ break;
+ case Stmt::OMPTargetParallelForDirectiveClass:
+ K = CXCursor_OMPTargetParallelForDirective;
+ break;
+ case Stmt::OMPTargetUpdateDirectiveClass:
+ K = CXCursor_OMPTargetUpdateDirective;
+ break;
+ case Stmt::OMPTeamsDirectiveClass:
+ K = CXCursor_OMPTeamsDirective;
+ break;
+ case Stmt::OMPCancellationPointDirectiveClass:
+ K = CXCursor_OMPCancellationPointDirective;
+ break;
+ case Stmt::OMPCancelDirectiveClass:
+ K = CXCursor_OMPCancelDirective;
+ break;
+ case Stmt::OMPTaskLoopDirectiveClass:
+ K = CXCursor_OMPTaskLoopDirective;
+ break;
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ K = CXCursor_OMPTaskLoopSimdDirective;
+ break;
+ case Stmt::OMPMasterTaskLoopDirectiveClass:
+ K = CXCursor_OMPMasterTaskLoopDirective;
+ break;
+ case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
+ K = CXCursor_OMPMasterTaskLoopSimdDirective;
+ break;
+ case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
+ K = CXCursor_OMPParallelMasterTaskLoopDirective;
+ break;
+ case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
+ K = CXCursor_OMPParallelMasterTaskLoopSimdDirective;
+ break;
+ case Stmt::OMPDistributeDirectiveClass:
+ K = CXCursor_OMPDistributeDirective;
+ break;
+ case Stmt::OMPDistributeParallelForDirectiveClass:
+ K = CXCursor_OMPDistributeParallelForDirective;
+ break;
+ case Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ K = CXCursor_OMPDistributeParallelForSimdDirective;
+ break;
+ case Stmt::OMPDistributeSimdDirectiveClass:
+ K = CXCursor_OMPDistributeSimdDirective;
+ break;
+ case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ K = CXCursor_OMPTargetParallelForSimdDirective;
+ break;
+ case Stmt::OMPTargetSimdDirectiveClass:
+ K = CXCursor_OMPTargetSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeDirective;
+ break;
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeParallelForSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeParallelForDirective;
+ break;
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeParallelForDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeSimdDirective;
+ break;
+ case Stmt::OMPInteropDirectiveClass:
+ K = CXCursor_OMPInteropDirective;
+ break;
+ case Stmt::OMPDispatchDirectiveClass:
+ K = CXCursor_OMPDispatchDirective;
+ break;
+ case Stmt::OMPMaskedDirectiveClass:
+ K = CXCursor_OMPMaskedDirective;
+ break;
+ case Stmt::OMPGenericLoopDirectiveClass:
+ K = CXCursor_OMPGenericLoopDirective;
+ break;
+ case Stmt::BuiltinBitCastExprClass:
+ K = CXCursor_BuiltinBitCastExpr;
+ }
+
+ CXCursor C = {K, 0, {Parent, S, TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Super && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_ObjCSuperClassRef, 0, {Super, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCSuperClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCSuperClassRef);
+ return std::make_pair(static_cast<const ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorObjCProtocolRef(const ObjCProtocolDecl *Proto,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Proto && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_ObjCProtocolRef, 0, {Proto, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const ObjCProtocolDecl *, SourceLocation>
+cxcursor::getCursorObjCProtocolRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCProtocolRef);
+ return std::make_pair(static_cast<const ObjCProtocolDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorObjCClassRef(const ObjCInterfaceDecl *Class,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ // 'Class' can be null for invalid code.
+ if (!Class)
+ return MakeCXCursorInvalid(CXCursor_InvalidCode);
+ assert(TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_ObjCClassRef, 0, {Class, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCClassRef);
+ return std::make_pair(static_cast<const ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorTypeRef(const TypeDecl *Type, SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Type && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_TypeRef, 0, {Type, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const TypeDecl *, SourceLocation>
+cxcursor::getCursorTypeRef(CXCursor C) {
+ assert(C.kind == CXCursor_TypeRef);
+ return std::make_pair(static_cast<const TypeDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorTemplateRef(const TemplateDecl *Template,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Template && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_TemplateRef, 0, {Template, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const TemplateDecl *, SourceLocation>
+cxcursor::getCursorTemplateRef(CXCursor C) {
+ assert(C.kind == CXCursor_TemplateRef);
+ return std::make_pair(static_cast<const TemplateDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorNamespaceRef(const NamedDecl *NS,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+
+ assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU &&
+ "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_NamespaceRef, 0, {NS, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const NamedDecl *, SourceLocation>
+cxcursor::getCursorNamespaceRef(CXCursor C) {
+ assert(C.kind == CXCursor_NamespaceRef);
+ return std::make_pair(static_cast<const NamedDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorVariableRef(const VarDecl *Var, SourceLocation Loc,
+ CXTranslationUnit TU) {
+
+ assert(Var && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_VariableRef, 0, {Var, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const VarDecl *, SourceLocation>
+cxcursor::getCursorVariableRef(CXCursor C) {
+ assert(C.kind == CXCursor_VariableRef);
+ return std::make_pair(static_cast<const VarDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorMemberRef(const FieldDecl *Field,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+
+ assert(Field && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_MemberRef, 0, {Field, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const FieldDecl *, SourceLocation>
+cxcursor::getCursorMemberRef(CXCursor C) {
+ assert(C.kind == CXCursor_MemberRef);
+ return std::make_pair(static_cast<const FieldDecl *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorCXXBaseSpecifier(const CXXBaseSpecifier *B,
+ CXTranslationUnit TU) {
+ CXCursor C = {CXCursor_CXXBaseSpecifier, 0, {B, nullptr, TU}};
+ return C;
+}
+
+const CXXBaseSpecifier *cxcursor::getCursorCXXBaseSpecifier(CXCursor C) {
+ assert(C.kind == CXCursor_CXXBaseSpecifier);
+ return static_cast<const CXXBaseSpecifier *>(C.data[0]);
+}
+
+CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range,
+ CXTranslationUnit TU) {
+ CXCursor C = {
+ CXCursor_PreprocessingDirective,
+ 0,
+ {Range.getBegin().getPtrEncoding(), Range.getEnd().getPtrEncoding(), TU}};
+ return C;
+}
+
+SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) {
+ assert(C.kind == CXCursor_PreprocessingDirective);
+ SourceRange Range(SourceLocation::getFromPtrEncoding(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+ ASTUnit *TU = getCursorASTUnit(C);
+ return TU->mapRangeFromPreamble(Range);
+}
+
+CXCursor cxcursor::MakeMacroDefinitionCursor(const MacroDefinitionRecord *MI,
+ CXTranslationUnit TU) {
+ CXCursor C = {CXCursor_MacroDefinition, 0, {MI, nullptr, TU}};
+ return C;
+}
+
+const MacroDefinitionRecord *cxcursor::getCursorMacroDefinition(CXCursor C) {
+ assert(C.kind == CXCursor_MacroDefinition);
+ return static_cast<const MacroDefinitionRecord *>(C.data[0]);
+}
+
+CXCursor cxcursor::MakeMacroExpansionCursor(MacroExpansion *MI,
+ CXTranslationUnit TU) {
+ CXCursor C = {CXCursor_MacroExpansion, 0, {MI, nullptr, TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeMacroExpansionCursor(MacroDefinitionRecord *MI,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Loc.isValid());
+ CXCursor C = {CXCursor_MacroExpansion, 0, {MI, Loc.getPtrEncoding(), TU}};
+ return C;
+}
+
+const IdentifierInfo *cxcursor::MacroExpansionCursor::getName() const {
+ if (isPseudo())
+ return getAsMacroDefinition()->getName();
+ return getAsMacroExpansion()->getName();
+}
+const MacroDefinitionRecord *
+cxcursor::MacroExpansionCursor::getDefinition() const {
+ if (isPseudo())
+ return getAsMacroDefinition();
+ return getAsMacroExpansion()->getDefinition();
+}
+SourceRange cxcursor::MacroExpansionCursor::getSourceRange() const {
+ if (isPseudo())
+ return getPseudoLoc();
+ return getAsMacroExpansion()->getSourceRange();
+}
+
+CXCursor cxcursor::MakeInclusionDirectiveCursor(InclusionDirective *ID,
+ CXTranslationUnit TU) {
+ CXCursor C = {CXCursor_InclusionDirective, 0, {ID, nullptr, TU}};
+ return C;
+}
+
+const InclusionDirective *cxcursor::getCursorInclusionDirective(CXCursor C) {
+ assert(C.kind == CXCursor_InclusionDirective);
+ return static_cast<const InclusionDirective *>(C.data[0]);
+}
+
+CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc,
+ CXTranslationUnit TU) {
+
+ assert(Label && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ CXCursor C = {CXCursor_LabelRef, 0, {Label, RawLoc, TU}};
+ return C;
+}
+
+std::pair<const LabelStmt *, SourceLocation>
+cxcursor::getCursorLabelRef(CXCursor C) {
+ assert(C.kind == CXCursor_LabelRef);
+ return std::make_pair(static_cast<const LabelStmt *>(C.data[0]),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+CXCursor cxcursor::MakeCursorOverloadedDeclRef(const OverloadExpr *E,
+ CXTranslationUnit TU) {
+ assert(E && TU && "Invalid arguments!");
+ OverloadedDeclRefStorage Storage(E);
+ void *RawLoc = E->getNameLoc().getPtrEncoding();
+ CXCursor C = {
+ CXCursor_OverloadedDeclRef, 0, {Storage.getOpaqueValue(), RawLoc, TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeCursorOverloadedDeclRef(const Decl *D,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(D && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ OverloadedDeclRefStorage Storage(D);
+ CXCursor C = {
+ CXCursor_OverloadedDeclRef, 0, {Storage.getOpaqueValue(), RawLoc, TU}};
+ return C;
+}
+
+CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name,
+ SourceLocation Loc,
+ CXTranslationUnit TU) {
+ assert(Name.getAsOverloadedTemplate() && TU && "Invalid arguments!");
+ void *RawLoc = Loc.getPtrEncoding();
+ OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate());
+ CXCursor C = {
+ CXCursor_OverloadedDeclRef, 0, {Storage.getOpaqueValue(), RawLoc, TU}};
+ return C;
+}
+
+std::pair<cxcursor::OverloadedDeclRefStorage, SourceLocation>
+cxcursor::getCursorOverloadedDeclRef(CXCursor C) {
+ assert(C.kind == CXCursor_OverloadedDeclRef);
+ return std::make_pair(OverloadedDeclRefStorage::getFromOpaqueValue(
+ const_cast<void *>(C.data[0])),
+ SourceLocation::getFromPtrEncoding(C.data[1]));
+}
+
+const Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
+ return static_cast<const Decl *>(Cursor.data[0]);
+}
+
+const Expr *cxcursor::getCursorExpr(CXCursor Cursor) {
+ return dyn_cast_or_null<Expr>(getCursorStmt(Cursor));
+}
+
+const Stmt *cxcursor::getCursorStmt(CXCursor Cursor) {
+ if (Cursor.kind == CXCursor_ObjCSuperClassRef ||
+ Cursor.kind == CXCursor_ObjCProtocolRef ||
+ Cursor.kind == CXCursor_ObjCClassRef)
+ return nullptr;
+
+ return static_cast<const Stmt *>(Cursor.data[1]);
+}
+
+const Attr *cxcursor::getCursorAttr(CXCursor Cursor) {
+ return static_cast<const Attr *>(Cursor.data[1]);
+}
+
+ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
+ return getCursorASTUnit(Cursor)->getASTContext();
+}
+
+ASTUnit *cxcursor::getCursorASTUnit(CXCursor Cursor) {
+ CXTranslationUnit TU = getCursorTU(Cursor);
+ if (!TU)
+ return nullptr;
+ return cxtu::getASTUnit(TU);
+}
+
+CXTranslationUnit cxcursor::getCursorTU(CXCursor Cursor) {
+ return static_cast<CXTranslationUnit>(const_cast<void *>(Cursor.data[2]));
+}
+
+void cxcursor::getOverriddenCursors(CXCursor cursor,
+ SmallVectorImpl<CXCursor> &overridden) {
+ assert(clang_isDeclaration(cursor.kind));
+ const NamedDecl *D = dyn_cast_or_null<NamedDecl>(getCursorDecl(cursor));
+ if (!D)
+ return;
+
+ CXTranslationUnit TU = getCursorTU(cursor);
+ SmallVector<const NamedDecl *, 8> OverDecls;
+ D->getASTContext().getOverriddenMethods(D, OverDecls);
+
+ for (SmallVectorImpl<const NamedDecl *>::iterator I = OverDecls.begin(),
+ E = OverDecls.end();
+ I != E; ++I) {
+ overridden.push_back(MakeCXCursor(*I, TU));
+ }
+}
+
+std::pair<int, SourceLocation>
+cxcursor::getSelectorIdentifierIndexAndLoc(CXCursor cursor) {
+ if (cursor.kind == CXCursor_ObjCMessageExpr) {
+ if (cursor.xdata != -1)
+ return std::make_pair(cursor.xdata,
+ cast<ObjCMessageExpr>(getCursorExpr(cursor))
+ ->getSelectorLoc(cursor.xdata));
+ } else if (cursor.kind == CXCursor_ObjCClassMethodDecl ||
+ cursor.kind == CXCursor_ObjCInstanceMethodDecl) {
+ if (cursor.xdata != -1)
+ return std::make_pair(cursor.xdata,
+ cast<ObjCMethodDecl>(getCursorDecl(cursor))
+ ->getSelectorLoc(cursor.xdata));
+ }
+
+ return std::make_pair(-1, SourceLocation());
+}
+
+CXCursor cxcursor::getSelectorIdentifierCursor(int SelIdx, CXCursor cursor) {
+ CXCursor newCursor = cursor;
+
+ if (cursor.kind == CXCursor_ObjCMessageExpr) {
+ if (SelIdx == -1 ||
+ unsigned(SelIdx) >=
+ cast<ObjCMessageExpr>(getCursorExpr(cursor))->getNumSelectorLocs())
+ newCursor.xdata = -1;
+ else
+ newCursor.xdata = SelIdx;
+ } else if (cursor.kind == CXCursor_ObjCClassMethodDecl ||
+ cursor.kind == CXCursor_ObjCInstanceMethodDecl) {
+ if (SelIdx == -1 ||
+ unsigned(SelIdx) >=
+ cast<ObjCMethodDecl>(getCursorDecl(cursor))->getNumSelectorLocs())
+ newCursor.xdata = -1;
+ else
+ newCursor.xdata = SelIdx;
+ }
+
+ return newCursor;
+}
+
+CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) {
+ if (cursor.kind != CXCursor_CallExpr)
+ return cursor;
+
+ if (cursor.xdata == 0)
+ return cursor;
+
+ const Expr *E = getCursorExpr(cursor);
+ TypeSourceInfo *Type = nullptr;
+ if (const CXXUnresolvedConstructExpr *UnCtor =
+ dyn_cast<CXXUnresolvedConstructExpr>(E)) {
+ Type = UnCtor->getTypeSourceInfo();
+ } else if (const CXXTemporaryObjectExpr *Tmp =
+ dyn_cast<CXXTemporaryObjectExpr>(E)) {
+ Type = Tmp->getTypeSourceInfo();
+ }
+
+ if (!Type)
+ return cursor;
+
+ CXTranslationUnit TU = getCursorTU(cursor);
+ QualType Ty = Type->getType();
+ TypeLoc TL = Type->getTypeLoc();
+ SourceLocation Loc = TL.getBeginLoc();
+
+ if (const ElaboratedType *ElabT = Ty->getAs<ElaboratedType>()) {
+ Ty = ElabT->getNamedType();
+ ElaboratedTypeLoc ElabTL = TL.castAs<ElaboratedTypeLoc>();
+ Loc = ElabTL.getNamedTypeLoc().getBeginLoc();
+ }
+
+ if (const TypedefType *Typedef = Ty->getAs<TypedefType>())
+ return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU);
+ if (const TagType *Tag = Ty->getAs<TagType>())
+ return MakeCursorTypeRef(Tag->getDecl(), Loc, TU);
+ if (const TemplateTypeParmType *TemplP = Ty->getAs<TemplateTypeParmType>())
+ return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU);
+
+ return cursor;
+}
+
+bool cxcursor::operator==(CXCursor X, CXCursor Y) {
+ return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] &&
+ X.data[2] == Y.data[2];
+}
+
+// FIXME: Remove once we can model DeclGroups and their appropriate ranges
+// properly in the ASTs.
+bool cxcursor::isFirstInDeclGroup(CXCursor C) {
+ assert(clang_isDeclaration(C.kind));
+ return ((uintptr_t)(C.data[1])) != 0;
+}
+
+//===----------------------------------------------------------------------===//
+// libclang CXCursor APIs
+//===----------------------------------------------------------------------===//
+
+int clang_Cursor_isNull(CXCursor cursor) {
+ return clang_equalCursors(cursor, clang_getNullCursor());
+}
+
+CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor cursor) {
+ return getCursorTU(cursor);
+}
+
+int clang_Cursor_getNumArguments(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
+ return MD->param_size();
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ return FD->param_size();
+ }
+
+ if (clang_isExpression(C.kind)) {
+ const Expr *E = cxcursor::getCursorExpr(C);
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ return CE->getNumArgs();
+ }
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
+ return CE->getNumArgs();
+ }
+ }
+
+ return -1;
+}
+
+CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) {
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
+ if (i < MD->param_size())
+ return cxcursor::MakeCXCursor(MD->parameters()[i],
+ cxcursor::getCursorTU(C));
+ } else if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (i < FD->param_size())
+ return cxcursor::MakeCXCursor(FD->parameters()[i],
+ cxcursor::getCursorTU(C));
+ }
+ }
+
+ if (clang_isExpression(C.kind)) {
+ const Expr *E = cxcursor::getCursorExpr(C);
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ if (i < CE->getNumArgs()) {
+ return cxcursor::MakeCXCursor(CE->getArg(i), getCursorDecl(C),
+ cxcursor::getCursorTU(C));
+ }
+ }
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
+ if (i < CE->getNumArgs()) {
+ return cxcursor::MakeCXCursor(CE->getArg(i), getCursorDecl(C),
+ cxcursor::getCursorTU(C));
+ }
+ }
+ }
+
+ return clang_getNullCursor();
+}
+
+int clang_Cursor_getNumTemplateArguments(CXCursor C) {
+ if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
+ return -1;
+ }
+
+ const FunctionDecl *FD =
+ llvm::dyn_cast_or_null<clang::FunctionDecl>(getCursorDecl(C));
+ if (!FD) {
+ return -1;
+ }
+
+ const FunctionTemplateSpecializationInfo *SpecInfo =
+ FD->getTemplateSpecializationInfo();
+ if (!SpecInfo) {
+ return -1;
+ }
+
+ return SpecInfo->TemplateArguments->size();
+}
+
+enum CXGetTemplateArgumentStatus {
+ /** The operation completed successfully */
+ CXGetTemplateArgumentStatus_Success = 0,
+
+ /** The specified cursor did not represent a FunctionDecl. */
+ CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1,
+
+ /** The specified cursor was not castable to a FunctionDecl. */
+ CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2,
+
+ /** A NULL FunctionTemplateSpecializationInfo was retrieved. */
+ CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3,
+
+ /** An invalid (OOB) argument index was specified */
+ CXGetTemplateArgumentStatus_InvalidIndex = -4
+};
+
+static int clang_Cursor_getTemplateArgument(CXCursor C, unsigned I,
+ TemplateArgument *TA) {
+ if (clang_getCursorKind(C) != CXCursor_FunctionDecl) {
+ return CXGetTemplateArgumentStatus_CursorNotFunctionDecl;
+ }
+
+ const FunctionDecl *FD =
+ llvm::dyn_cast_or_null<clang::FunctionDecl>(getCursorDecl(C));
+ if (!FD) {
+ return CXGetTemplateArgumentStatus_BadFunctionDeclCast;
+ }
+
+ const FunctionTemplateSpecializationInfo *SpecInfo =
+ FD->getTemplateSpecializationInfo();
+ if (!SpecInfo) {
+ return CXGetTemplateArgumentStatus_NullTemplSpecInfo;
+ }
+
+ if (I >= SpecInfo->TemplateArguments->size()) {
+ return CXGetTemplateArgumentStatus_InvalidIndex;
+ }
+
+ *TA = SpecInfo->TemplateArguments->get(I);
+ return 0;
+}
+
+enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
+ unsigned I) {
+ TemplateArgument TA;
+ if (clang_Cursor_getTemplateArgument(C, I, &TA)) {
+ return CXTemplateArgumentKind_Invalid;
+ }
+
+ switch (TA.getKind()) {
+ case TemplateArgument::Null:
+ return CXTemplateArgumentKind_Null;
+ case TemplateArgument::Type:
+ return CXTemplateArgumentKind_Type;
+ case TemplateArgument::Declaration:
+ return CXTemplateArgumentKind_Declaration;
+ case TemplateArgument::NullPtr:
+ return CXTemplateArgumentKind_NullPtr;
+ case TemplateArgument::Integral:
+ return CXTemplateArgumentKind_Integral;
+ case TemplateArgument::Template:
+ return CXTemplateArgumentKind_Template;
+ case TemplateArgument::TemplateExpansion:
+ return CXTemplateArgumentKind_TemplateExpansion;
+ case TemplateArgument::Expression:
+ return CXTemplateArgumentKind_Expression;
+ case TemplateArgument::Pack:
+ return CXTemplateArgumentKind_Pack;
+ }
+
+ return CXTemplateArgumentKind_Invalid;
+}
+
+CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) {
+ TemplateArgument TA;
+ if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
+ CXGetTemplateArgumentStatus_Success) {
+ return cxtype::MakeCXType(QualType(), getCursorTU(C));
+ }
+
+ if (TA.getKind() != TemplateArgument::Type) {
+ return cxtype::MakeCXType(QualType(), getCursorTU(C));
+ }
+
+ return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C));
+}
+
+long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) {
+ TemplateArgument TA;
+ if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
+ CXGetTemplateArgumentStatus_Success) {
+ assert(0 && "Unable to retrieve TemplateArgument");
+ return 0;
+ }
+
+ if (TA.getKind() != TemplateArgument::Integral) {
+ assert(0 && "Passed template argument is not Integral");
+ return 0;
+ }
+
+ return TA.getAsIntegral().getSExtValue();
+}
+
+unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
+ unsigned I) {
+ TemplateArgument TA;
+ if (clang_Cursor_getTemplateArgument(C, I, &TA) !=
+ CXGetTemplateArgumentStatus_Success) {
+ assert(0 && "Unable to retrieve TemplateArgument");
+ return 0;
+ }
+
+ if (TA.getKind() != TemplateArgument::Integral) {
+ assert(0 && "Passed template argument is not Integral");
+ return 0;
+ }
+
+ return TA.getAsIntegral().getZExtValue();
+}
+
+//===----------------------------------------------------------------------===//
+// CXCursorSet.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::DenseMap<CXCursor, unsigned> CXCursorSet_Impl;
+
+static inline CXCursorSet packCXCursorSet(CXCursorSet_Impl *setImpl) {
+ return (CXCursorSet)setImpl;
+}
+static inline CXCursorSet_Impl *unpackCXCursorSet(CXCursorSet set) {
+ return (CXCursorSet_Impl *)set;
+}
+namespace llvm {
+template <> struct DenseMapInfo<CXCursor> {
+public:
+ static inline CXCursor getEmptyKey() {
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
+ }
+ static inline CXCursor getTombstoneKey() {
+ return MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ }
+ static inline unsigned getHashValue(const CXCursor &cursor) {
+ return llvm::DenseMapInfo<std::pair<const void *, const void *>>::
+ getHashValue(std::make_pair(cursor.data[0], cursor.data[1]));
+ }
+ static inline bool isEqual(const CXCursor &x, const CXCursor &y) {
+ return x.kind == y.kind && x.data[0] == y.data[0] && x.data[1] == y.data[1];
+ }
+};
+} // namespace llvm
+
+CXCursorSet clang_createCXCursorSet() {
+ return packCXCursorSet(new CXCursorSet_Impl());
+}
+
+void clang_disposeCXCursorSet(CXCursorSet set) {
+ delete unpackCXCursorSet(set);
+}
+
+unsigned clang_CXCursorSet_contains(CXCursorSet set, CXCursor cursor) {
+ CXCursorSet_Impl *setImpl = unpackCXCursorSet(set);
+ if (!setImpl)
+ return 0;
+ return setImpl->find(cursor) != setImpl->end();
+}
+
+unsigned clang_CXCursorSet_insert(CXCursorSet set, CXCursor cursor) {
+ // Do not insert invalid cursors into the set.
+ if (cursor.kind >= CXCursor_FirstInvalid &&
+ cursor.kind <= CXCursor_LastInvalid)
+ return 1;
+
+ CXCursorSet_Impl *setImpl = unpackCXCursorSet(set);
+ if (!setImpl)
+ return 1;
+ unsigned &entry = (*setImpl)[cursor];
+ unsigned flag = entry == 0 ? 1 : 0;
+ entry = 1;
+ return flag;
+}
+
+CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
+ enum CXCursorKind kind = clang_getCursorKind(cursor);
+ if (clang_isDeclaration(kind)) {
+ const Decl *decl = getCursorDecl(cursor);
+ if (const NamedDecl *namedDecl = dyn_cast_or_null<NamedDecl>(decl)) {
+ ASTUnit *unit = getCursorASTUnit(cursor);
+ CodeCompletionResult Result(namedDecl, CCP_Declaration);
+ CodeCompletionString *String = Result.CreateCodeCompletionString(
+ unit->getASTContext(), unit->getPreprocessor(),
+ CodeCompletionContext::CCC_Other,
+ unit->getCodeCompletionTUInfo().getAllocator(),
+ unit->getCodeCompletionTUInfo(), true);
+ return String;
+ }
+ } else if (kind == CXCursor_MacroDefinition) {
+ const MacroDefinitionRecord *definition = getCursorMacroDefinition(cursor);
+ const IdentifierInfo *Macro = definition->getName();
+ ASTUnit *unit = getCursorASTUnit(cursor);
+ CodeCompletionResult Result(
+ Macro,
+ unit->getPreprocessor().getMacroDefinition(Macro).getMacroInfo());
+ CodeCompletionString *String = Result.CreateCodeCompletionString(
+ unit->getASTContext(), unit->getPreprocessor(),
+ CodeCompletionContext::CCC_Other,
+ unit->getCodeCompletionTUInfo().getAllocator(),
+ unit->getCodeCompletionTUInfo(), false);
+ return String;
+ }
+ return nullptr;
+}
+
+namespace {
+struct OverridenCursorsPool {
+ typedef SmallVector<CXCursor, 2> CursorVec;
+ std::vector<CursorVec *> AllCursors;
+ std::vector<CursorVec *> AvailableCursors;
+
+ ~OverridenCursorsPool() {
+ for (std::vector<CursorVec *>::iterator I = AllCursors.begin(),
+ E = AllCursors.end();
+ I != E; ++I) {
+ delete *I;
+ }
+ }
+};
+} // namespace
+
+void *cxcursor::createOverridenCXCursorsPool() {
+ return new OverridenCursorsPool();
+}
+
+void cxcursor::disposeOverridenCXCursorsPool(void *pool) {
+ delete static_cast<OverridenCursorsPool *>(pool);
+}
+
+void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden,
+ unsigned *num_overridden) {
+ if (overridden)
+ *overridden = nullptr;
+ if (num_overridden)
+ *num_overridden = 0;
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
+
+ if (!overridden || !num_overridden || !TU)
+ return;
+
+ if (!clang_isDeclaration(cursor.kind))
+ return;
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool *>(TU->OverridenCursorsPool);
+
+ OverridenCursorsPool::CursorVec *Vec = nullptr;
+
+ if (!pool.AvailableCursors.empty()) {
+ Vec = pool.AvailableCursors.back();
+ pool.AvailableCursors.pop_back();
+ } else {
+ Vec = new OverridenCursorsPool::CursorVec();
+ pool.AllCursors.push_back(Vec);
+ }
+
+ // Clear out the vector, but don't free the memory contents. This
+ // reduces malloc() traffic.
+ Vec->clear();
+
+ // Use the first entry to contain a back reference to the vector.
+ // This is a complete hack.
+ CXCursor backRefCursor = MakeCXCursorInvalid(CXCursor_InvalidFile, TU);
+ backRefCursor.data[0] = Vec;
+ assert(cxcursor::getCursorTU(backRefCursor) == TU);
+ Vec->push_back(backRefCursor);
+
+ // Get the overridden cursors.
+ cxcursor::getOverriddenCursors(cursor, *Vec);
+
+ // Did we get any overridden cursors? If not, return Vec to the pool
+ // of available cursor vectors.
+ if (Vec->size() == 1) {
+ pool.AvailableCursors.push_back(Vec);
+ return;
+ }
+
+ // Now tell the caller about the overridden cursors.
+ assert(Vec->size() > 1);
+ *overridden = &((*Vec)[1]);
+ *num_overridden = Vec->size() - 1;
+}
+
+void clang_disposeOverriddenCursors(CXCursor *overridden) {
+ if (!overridden)
+ return;
+
+ // Use pointer arithmetic to get back the first faux entry
+ // which has a back-reference to the TU and the vector.
+ --overridden;
+ OverridenCursorsPool::CursorVec *Vec =
+ static_cast<OverridenCursorsPool::CursorVec *>(
+ const_cast<void *>(overridden->data[0]));
+ CXTranslationUnit TU = getCursorTU(*overridden);
+
+ assert(Vec && TU);
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool *>(TU->OverridenCursorsPool);
+
+ pool.AvailableCursors.push_back(Vec);
+}
+
+int clang_Cursor_isDynamicCall(CXCursor C) {
+ const Expr *E = nullptr;
+ if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+ if (!E)
+ return 0;
+
+ if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
+ if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
+ return false;
+ if (auto *RecE = dyn_cast<ObjCMessageExpr>(
+ MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
+ if (RecE->getMethodFamily() == OMF_alloc)
+ return false;
+ }
+ return true;
+ }
+
+ if (auto *PropRefE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ return !PropRefE->isSuperReceiver();
+ }
+
+ const MemberExpr *ME = nullptr;
+ if (isa<MemberExpr>(E))
+ ME = cast<MemberExpr>(E);
+ else if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+ ME = dyn_cast_or_null<MemberExpr>(CE->getCallee());
+
+ if (ME) {
+ if (const CXXMethodDecl *MD =
+ dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
+ return MD->isVirtual() &&
+ ME->performsVirtualDispatch(
+ cxcursor::getCursorContext(C).getLangOpts());
+ }
+
+ return 0;
+}
+
+CXType clang_Cursor_getReceiverType(CXCursor C) {
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ const Expr *E = nullptr;
+ if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+
+ if (const ObjCMessageExpr *MsgE = dyn_cast_or_null<ObjCMessageExpr>(E))
+ return cxtype::MakeCXType(MsgE->getReceiverType(), TU);
+
+ if (auto *PropRefE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ return cxtype::MakeCXType(
+ PropRefE->getReceiverType(cxcursor::getCursorContext(C)), TU);
+ }
+
+ const MemberExpr *ME = nullptr;
+ if (isa<MemberExpr>(E))
+ ME = cast<MemberExpr>(E);
+ else if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+ ME = dyn_cast_or_null<MemberExpr>(CE->getCallee());
+
+ if (ME) {
+ if (isa_and_nonnull<CXXMethodDecl>(ME->getMemberDecl())) {
+ auto receiverTy = ME->getBase()->IgnoreImpCasts()->getType();
+ return cxtype::MakeCXType(receiverTy, TU);
+ }
+ }
+
+ return cxtype::MakeCXType(QualType(), TU);
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXCursor.h b/contrib/libs/clang14/tools/libclang/CXCursor.h
new file mode 100644
index 0000000000..1e4c0a05c9
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXCursor.h
@@ -0,0 +1,293 @@
+//===- CXCursor.h - Routines for manipulating CXCursors -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXCURSOR_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXCURSOR_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerUnion.h"
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class ASTUnit;
+class Attr;
+class CXXBaseSpecifier;
+class Decl;
+class Expr;
+class FieldDecl;
+class InclusionDirective;
+class LabelStmt;
+class MacroDefinitionRecord;
+class MacroExpansion;
+class NamedDecl;
+class ObjCInterfaceDecl;
+class ObjCProtocolDecl;
+class OverloadedTemplateStorage;
+class OverloadExpr;
+class Stmt;
+class TemplateDecl;
+class TemplateName;
+class TypeDecl;
+class VarDecl;
+class IdentifierInfo;
+
+namespace cxcursor {
+
+CXCursor getCursor(CXTranslationUnit, SourceLocation);
+
+CXCursor MakeCXCursor(const clang::Attr *A, const clang::Decl *Parent,
+ CXTranslationUnit TU);
+CXCursor MakeCXCursor(const clang::Decl *D, CXTranslationUnit TU,
+ SourceRange RegionOfInterest = SourceRange(),
+ bool FirstInDeclGroup = true);
+CXCursor MakeCXCursor(const clang::Stmt *S, const clang::Decl *Parent,
+ CXTranslationUnit TU,
+ SourceRange RegionOfInterest = SourceRange());
+CXCursor MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU = nullptr);
+
+/// Create an Objective-C superclass reference at the given location.
+CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc, CXTranslationUnit TU);
+
+/// Unpack an ObjCSuperClassRef cursor into the interface it references
+/// and optionally the location where the reference occurred.
+std::pair<const ObjCInterfaceDecl *, SourceLocation>
+getCursorObjCSuperClassRef(CXCursor C);
+
+/// Create an Objective-C protocol reference at the given location.
+CXCursor MakeCursorObjCProtocolRef(const ObjCProtocolDecl *Proto,
+ SourceLocation Loc, CXTranslationUnit TU);
+
+/// Unpack an ObjCProtocolRef cursor into the protocol it references
+/// and optionally the location where the reference occurred.
+std::pair<const ObjCProtocolDecl *, SourceLocation>
+getCursorObjCProtocolRef(CXCursor C);
+
+/// Create an Objective-C class reference at the given location.
+CXCursor MakeCursorObjCClassRef(const ObjCInterfaceDecl *Class,
+ SourceLocation Loc, CXTranslationUnit TU);
+
+/// Unpack an ObjCClassRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<const ObjCInterfaceDecl *, SourceLocation>
+getCursorObjCClassRef(CXCursor C);
+
+/// Create a type reference at the given location.
+CXCursor MakeCursorTypeRef(const TypeDecl *Type, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a TypeRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<const TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
+
+/// Create a reference to a template at the given location.
+CXCursor MakeCursorTemplateRef(const TemplateDecl *Template, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a TemplateRef cursor into the template it references and
+/// the location where the reference occurred.
+std::pair<const TemplateDecl *, SourceLocation>
+getCursorTemplateRef(CXCursor C);
+
+/// Create a reference to a namespace or namespace alias at the given
+/// location.
+CXCursor MakeCursorNamespaceRef(const NamedDecl *NS, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a NamespaceRef cursor into the namespace or namespace alias
+/// it references and the location where the reference occurred.
+std::pair<const NamedDecl *, SourceLocation> getCursorNamespaceRef(CXCursor C);
+
+/// Create a reference to a variable at the given location.
+CXCursor MakeCursorVariableRef(const VarDecl *Var, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a VariableRef cursor into the variable it references and the
+/// location where the where the reference occurred.
+std::pair<const VarDecl *, SourceLocation> getCursorVariableRef(CXCursor C);
+
+/// Create a reference to a field at the given location.
+CXCursor MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a MemberRef cursor into the field it references and the
+/// location where the reference occurred.
+std::pair<const FieldDecl *, SourceLocation> getCursorMemberRef(CXCursor C);
+
+/// Create a CXX base specifier cursor.
+CXCursor MakeCursorCXXBaseSpecifier(const CXXBaseSpecifier *B,
+ CXTranslationUnit TU);
+
+/// Unpack a CXXBaseSpecifier cursor into a CXXBaseSpecifier.
+const CXXBaseSpecifier *getCursorCXXBaseSpecifier(CXCursor C);
+
+/// Create a preprocessing directive cursor.
+CXCursor MakePreprocessingDirectiveCursor(SourceRange Range,
+ CXTranslationUnit TU);
+
+/// Unpack a given preprocessing directive to retrieve its source range.
+SourceRange getCursorPreprocessingDirective(CXCursor C);
+
+/// Create a macro definition cursor.
+CXCursor MakeMacroDefinitionCursor(const MacroDefinitionRecord *,
+ CXTranslationUnit TU);
+
+/// Unpack a given macro definition cursor to retrieve its
+/// source range.
+const MacroDefinitionRecord *getCursorMacroDefinition(CXCursor C);
+
+/// Create a macro expansion cursor.
+CXCursor MakeMacroExpansionCursor(MacroExpansion *, CXTranslationUnit TU);
+
+/// Create a "pseudo" macro expansion cursor, using a macro definition
+/// and a source location.
+CXCursor MakeMacroExpansionCursor(MacroDefinitionRecord *, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Wraps a macro expansion cursor and provides a common interface
+/// for a normal macro expansion cursor or a "pseudo" one.
+///
+/// "Pseudo" macro expansion cursors (essentially a macro definition along with
+/// a source location) are created in special cases, for example they can be
+/// created for identifiers inside macro definitions, if these identifiers are
+/// macro names.
+class MacroExpansionCursor {
+ CXCursor C;
+
+ bool isPseudo() const { return C.data[1] != nullptr; }
+ const MacroDefinitionRecord *getAsMacroDefinition() const {
+ assert(isPseudo());
+ return static_cast<const MacroDefinitionRecord *>(C.data[0]);
+ }
+ const MacroExpansion *getAsMacroExpansion() const {
+ assert(!isPseudo());
+ return static_cast<const MacroExpansion *>(C.data[0]);
+ }
+ SourceLocation getPseudoLoc() const {
+ assert(isPseudo());
+ return SourceLocation::getFromPtrEncoding(C.data[1]);
+ }
+
+public:
+ MacroExpansionCursor(CXCursor C) : C(C) {
+ assert(C.kind == CXCursor_MacroExpansion);
+ }
+
+ const IdentifierInfo *getName() const;
+ const MacroDefinitionRecord *getDefinition() const;
+ SourceRange getSourceRange() const;
+};
+
+/// Unpack a given macro expansion cursor to retrieve its info.
+static inline MacroExpansionCursor getCursorMacroExpansion(CXCursor C) {
+ return C;
+}
+
+/// Create an inclusion directive cursor.
+CXCursor MakeInclusionDirectiveCursor(InclusionDirective *,
+ CXTranslationUnit TU);
+
+/// Unpack a given inclusion directive cursor to retrieve its
+/// source range.
+const InclusionDirective *getCursorInclusionDirective(CXCursor C);
+
+/// Create a label reference at the given location.
+CXCursor MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc,
+ CXTranslationUnit TU);
+
+/// Unpack a label reference into the label statement it refers to and
+/// the location of the reference.
+std::pair<const LabelStmt *, SourceLocation> getCursorLabelRef(CXCursor C);
+
+/// Create a overloaded declaration reference cursor for an expression.
+CXCursor MakeCursorOverloadedDeclRef(const OverloadExpr *E,
+ CXTranslationUnit TU);
+
+/// Create a overloaded declaration reference cursor for a declaration.
+CXCursor MakeCursorOverloadedDeclRef(const Decl *D, SourceLocation Location,
+ CXTranslationUnit TU);
+
+/// Create a overloaded declaration reference cursor for a template name.
+CXCursor MakeCursorOverloadedDeclRef(TemplateName Template,
+ SourceLocation Location,
+ CXTranslationUnit TU);
+
+/// Internal storage for an overloaded declaration reference cursor;
+typedef llvm::PointerUnion<const OverloadExpr *, const Decl *,
+ OverloadedTemplateStorage *>
+ OverloadedDeclRefStorage;
+
+/// Unpack an overloaded declaration reference into an expression,
+/// declaration, or template name along with the source location.
+std::pair<OverloadedDeclRefStorage, SourceLocation>
+getCursorOverloadedDeclRef(CXCursor C);
+
+const Decl *getCursorDecl(CXCursor Cursor);
+const Expr *getCursorExpr(CXCursor Cursor);
+const Stmt *getCursorStmt(CXCursor Cursor);
+const Attr *getCursorAttr(CXCursor Cursor);
+
+ASTContext &getCursorContext(CXCursor Cursor);
+ASTUnit *getCursorASTUnit(CXCursor Cursor);
+CXTranslationUnit getCursorTU(CXCursor Cursor);
+
+void getOverriddenCursors(CXCursor cursor,
+ SmallVectorImpl<CXCursor> &overridden);
+
+/// Create an opaque pool used for fast generation of overridden
+/// CXCursor arrays.
+void *createOverridenCXCursorsPool();
+
+/// Dispose of the overridden CXCursors pool.
+void disposeOverridenCXCursorsPool(void *pool);
+
+/// Returns a index/location pair for a selector identifier if the cursor
+/// points to one.
+std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);
+static inline int getSelectorIdentifierIndex(CXCursor cursor) {
+ return getSelectorIdentifierIndexAndLoc(cursor).first;
+}
+static inline SourceLocation getSelectorIdentifierLoc(CXCursor cursor) {
+ return getSelectorIdentifierIndexAndLoc(cursor).second;
+}
+
+CXCursor getSelectorIdentifierCursor(int SelIdx, CXCursor cursor);
+
+static inline CXCursor getTypeRefedCallExprCursor(CXCursor cursor) {
+ CXCursor newCursor = cursor;
+ if (cursor.kind == CXCursor_CallExpr)
+ newCursor.xdata = 1;
+ return newCursor;
+}
+
+CXCursor getTypeRefCursor(CXCursor cursor);
+
+/// Generate a USR for \arg D and put it in \arg Buf.
+/// \returns true if no USR was computed or the result should be ignored,
+/// false otherwise.
+bool getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf);
+
+bool operator==(CXCursor X, CXCursor Y);
+
+inline bool operator!=(CXCursor X, CXCursor Y) { return !(X == Y); }
+
+/// Return true if the cursor represents a declaration that is the
+/// first in a declaration group.
+bool isFirstInDeclGroup(CXCursor C);
+
+} // namespace cxcursor
+} // namespace clang
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.cpp b/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.cpp
new file mode 100644
index 0000000000..2f892fd1a4
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.cpp
@@ -0,0 +1,1312 @@
+//===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXIndexDataConsumer.h"
+#include "CIndexDiagnostic.h"
+#include "CXTranslationUnit.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+
+using namespace clang;
+using namespace clang::index;
+using namespace cxindex;
+using namespace cxcursor;
+
+namespace {
+class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
+ CXIndexDataConsumer &DataConsumer;
+ SourceLocation DeclLoc;
+ const DeclContext *LexicalDC;
+
+public:
+ IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
+ const DeclContext *lexicalDC)
+ : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
+
+ bool VisitFunctionDecl(const FunctionDecl *D) {
+ DataConsumer.handleFunction(D);
+ return true;
+ }
+
+ bool VisitVarDecl(const VarDecl *D) {
+ DataConsumer.handleVar(D);
+ return true;
+ }
+
+ bool VisitFieldDecl(const FieldDecl *D) {
+ DataConsumer.handleField(D);
+ return true;
+ }
+
+ bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+ return true;
+ }
+
+ bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
+ DataConsumer.handleEnumerator(D);
+ return true;
+ }
+
+ bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
+ DataConsumer.handleTypedefName(D);
+ return true;
+ }
+
+ bool VisitTagDecl(const TagDecl *D) {
+ DataConsumer.handleTagDecl(D);
+ return true;
+ }
+
+ bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
+ DataConsumer.handleObjCInterface(D);
+ return true;
+ }
+
+ bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
+ DataConsumer.handleObjCProtocol(D);
+ return true;
+ }
+
+ bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
+ DataConsumer.handleObjCImplementation(D);
+ return true;
+ }
+
+ bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
+ DataConsumer.handleObjCCategory(D);
+ return true;
+ }
+
+ bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
+ DataConsumer.handleObjCCategoryImpl(D);
+ return true;
+ }
+
+ bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+ if (isa<ObjCImplDecl>(LexicalDC) && !D->isThisDeclarationADefinition())
+ DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC);
+ else
+ DataConsumer.handleObjCMethod(D, DeclLoc);
+ return true;
+ }
+
+ bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
+ DataConsumer.handleObjCProperty(D);
+ return true;
+ }
+
+ bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
+ DataConsumer.handleSynthesizedObjCProperty(D);
+ return true;
+ }
+
+ bool VisitNamespaceDecl(const NamespaceDecl *D) {
+ DataConsumer.handleNamespace(D);
+ return true;
+ }
+
+ bool VisitUsingDecl(const UsingDecl *D) {
+ return true;
+ }
+
+ bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
+ return true;
+ }
+
+ bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
+ DataConsumer.handleClassTemplate(D);
+ return true;
+ }
+
+ bool VisitClassTemplateSpecializationDecl(const
+ ClassTemplateSpecializationDecl *D) {
+ DataConsumer.handleTagDecl(D);
+ return true;
+ }
+
+ bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
+ DataConsumer.handleFunctionTemplate(D);
+ return true;
+ }
+
+ bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
+ DataConsumer.handleTypeAliasTemplate(D);
+ return true;
+ }
+
+ bool VisitImportDecl(const ImportDecl *D) {
+ DataConsumer.importedModule(D);
+ return true;
+ }
+};
+
+CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
+ // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
+ return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
+}
+}
+
+bool CXIndexDataConsumer::handleDeclOccurrence(
+ const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
+ SourceLocation Loc, ASTNodeInfo ASTNode) {
+ Loc = getASTContext().getSourceManager().getFileLoc(Loc);
+
+ if (Roles & (unsigned)SymbolRole::Reference) {
+ const NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return true;
+
+ if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
+ if (!ObjCID->isThisDeclarationADefinition() &&
+ ObjCID->getLocation() == Loc) {
+ // The libclang API treats this as ObjCClassRef declaration.
+ IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
+ return true;
+ }
+ }
+ if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(ASTNode.OrigD)) {
+ if (!ObjCPD->isThisDeclarationADefinition() &&
+ ObjCPD->getLocation() == Loc) {
+ // The libclang API treats this as ObjCProtocolRef declaration.
+ IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD);
+ return true;
+ }
+ }
+
+ CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
+ if (Roles & (unsigned)SymbolRole::Implicit) {
+ Kind = CXIdxEntityRef_Implicit;
+ }
+ CXSymbolRole CXRole = getSymbolRole(Roles);
+
+ CXCursor Cursor;
+ if (ASTNode.OrigE) {
+ Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
+ cast<Decl>(ASTNode.ContainerDC),
+ getCXTU());
+ } else {
+ if (ASTNode.OrigD) {
+ if (auto *OrigND = dyn_cast<NamedDecl>(ASTNode.OrigD))
+ Cursor = getRefCursor(OrigND, Loc);
+ else
+ Cursor = MakeCXCursor(ASTNode.OrigD, CXTU);
+ } else {
+ Cursor = getRefCursor(ND, Loc);
+ }
+ }
+ handleReference(ND, Loc, Cursor,
+ dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
+ ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole);
+
+ } else {
+ const DeclContext *LexicalDC = ASTNode.ContainerDC;
+ if (!LexicalDC) {
+ for (const auto &SymRel : Relations) {
+ if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
+ LexicalDC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
+ }
+ }
+ IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD);
+ }
+
+ return !shouldAbort();
+}
+
+bool CXIndexDataConsumer::handleModuleOccurrence(const ImportDecl *ImportD,
+ const Module *Mod,
+ SymbolRoleSet Roles,
+ SourceLocation Loc) {
+ if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
+ IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
+ return !shouldAbort();
+}
+
+void CXIndexDataConsumer::finish() {
+ indexDiagnostics();
+}
+
+
+CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
+ const ObjCProtocolList &ProtList,
+ CXIndexDataConsumer &IdxCtx,
+ ScratchAlloc &SA) {
+ ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
+ for (ObjCInterfaceDecl::protocol_iterator
+ I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
+ SourceLocation Loc = *LI;
+ ObjCProtocolDecl *PD = *I;
+ ProtEntities.push_back(EntityInfo());
+ IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
+ CXIdxObjCProtocolRefInfo ProtInfo = { nullptr,
+ MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU),
+ IdxCtx.getIndexLoc(Loc) };
+ ProtInfos.push_back(ProtInfo);
+
+ if (IdxCtx.shouldSuppressRefs())
+ IdxCtx.markEntityOccurrenceInFile(PD, Loc);
+ }
+
+ for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
+ ProtInfos[i].protocol = &ProtEntities[i];
+
+ for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
+ Prots.push_back(&ProtInfos[i]);
+}
+
+
+IBOutletCollectionInfo::IBOutletCollectionInfo(
+ const IBOutletCollectionInfo &other)
+ : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
+
+ IBCollInfo.attrInfo = this;
+ IBCollInfo.classCursor = other.IBCollInfo.classCursor;
+ IBCollInfo.classLoc = other.IBCollInfo.classLoc;
+ if (other.IBCollInfo.objcClass) {
+ ClassInfo = other.ClassInfo;
+ IBCollInfo.objcClass = &ClassInfo;
+ } else
+ IBCollInfo.objcClass = nullptr;
+}
+
+AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
+ : SA(IdxCtx), ref_cnt(0) {
+
+ if (!D->hasAttrs())
+ return;
+
+ for (const auto *A : D->attrs()) {
+ CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU);
+ CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation());
+ switch (C.kind) {
+ default:
+ Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
+ break;
+ case CXCursor_IBActionAttr:
+ Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
+ break;
+ case CXCursor_IBOutletAttr:
+ Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
+ break;
+ case CXCursor_IBOutletCollectionAttr:
+ IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
+ break;
+ }
+ }
+
+ for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
+ IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
+ CXAttrs.push_back(&IBInfo);
+
+ const IBOutletCollectionAttr *
+ IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
+ SourceLocation InterfaceLocStart =
+ IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
+ IBInfo.IBCollInfo.attrInfo = &IBInfo;
+ IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart);
+ IBInfo.IBCollInfo.objcClass = nullptr;
+ IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
+ QualType Ty = IBAttr->getInterface();
+ if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) {
+ if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) {
+ IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
+ IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
+ IBInfo.IBCollInfo.classCursor =
+ MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU);
+ }
+ }
+ }
+
+ for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
+ CXAttrs.push_back(&Attrs[i]);
+}
+
+IntrusiveRefCntPtr<AttrListInfo>
+AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
+ ScratchAlloc SA(IdxCtx);
+ AttrListInfo *attrs = SA.allocate<AttrListInfo>();
+ return new (attrs) AttrListInfo(D, IdxCtx);
+}
+
+CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
+ CXIndexDataConsumer &IdxCtx,
+ ScratchAlloc &SA) {
+ for (const auto &Base : D->bases()) {
+ BaseEntities.push_back(EntityInfo());
+ const NamedDecl *BaseD = nullptr;
+ QualType T = Base.getType();
+ SourceLocation Loc = getBaseLoc(Base);
+
+ if (const TypedefType *TDT = T->getAs<TypedefType>()) {
+ BaseD = TDT->getDecl();
+ } else if (const TemplateSpecializationType *
+ TST = T->getAs<TemplateSpecializationType>()) {
+ BaseD = TST->getTemplateName().getAsTemplateDecl();
+ } else if (const RecordType *RT = T->getAs<RecordType>()) {
+ BaseD = RT->getDecl();
+ }
+
+ if (BaseD)
+ IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA);
+ CXIdxBaseClassInfo BaseInfo = { nullptr,
+ MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU),
+ IdxCtx.getIndexLoc(Loc) };
+ BaseInfos.push_back(BaseInfo);
+ }
+
+ for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
+ if (BaseEntities[i].name && BaseEntities[i].USR)
+ BaseInfos[i].base = &BaseEntities[i];
+ }
+
+ for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
+ CXBases.push_back(&BaseInfos[i]);
+}
+
+SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
+ const CXXBaseSpecifier &Base) const {
+ SourceLocation Loc = Base.getSourceRange().getBegin();
+ TypeLoc TL;
+ if (Base.getTypeSourceInfo())
+ TL = Base.getTypeSourceInfo()->getTypeLoc();
+ if (TL.isNull())
+ return Loc;
+
+ if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
+ TL = QL.getUnqualifiedLoc();
+
+ if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
+ return EL.getNamedTypeLoc().getBeginLoc();
+ if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
+ return DL.getNameLoc();
+ if (DependentTemplateSpecializationTypeLoc DTL =
+ TL.getAs<DependentTemplateSpecializationTypeLoc>())
+ return DTL.getTemplateNameLoc();
+
+ return Loc;
+}
+
+const char *ScratchAlloc::toCStr(StringRef Str) {
+ if (Str.empty())
+ return "";
+ if (Str.data()[Str.size()] == '\0')
+ return Str.data();
+ return copyCStr(Str);
+}
+
+const char *ScratchAlloc::copyCStr(StringRef Str) {
+ char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1);
+ std::uninitialized_copy(Str.begin(), Str.end(), buf);
+ buf[Str.size()] = '\0';
+ return buf;
+}
+
+void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
+ Ctx = &ctx;
+ cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
+}
+
+void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
+ cxtu::getASTUnit(CXTU)->setPreprocessor(std::move(PP));
+}
+
+bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
+ assert(D);
+
+ if (!D->getParentFunctionOrMethod())
+ return false;
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ switch (ND->getFormalLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ return true;
+ case VisibleNoLinkage:
+ case ModuleInternalLinkage:
+ case UniqueExternalLinkage:
+ llvm_unreachable("Not a sema linkage");
+ case ModuleLinkage:
+ case ExternalLinkage:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CXIndexDataConsumer::shouldAbort() {
+ if (!CB.abortQuery)
+ return false;
+ return CB.abortQuery(ClientData, nullptr);
+}
+
+void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
+ if (File && CB.enteredMainFile) {
+ CXIdxClientFile idxFile =
+ CB.enteredMainFile(ClientData,
+ static_cast<CXFile>(const_cast<FileEntry *>(File)),
+ nullptr);
+ FileMap[File] = idxFile;
+ }
+}
+
+void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
+ StringRef filename,
+ const FileEntry *File,
+ bool isImport, bool isAngled,
+ bool isModuleImport) {
+ if (!CB.ppIncludedFile)
+ return;
+
+ ScratchAlloc SA(*this);
+ CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
+ SA.toCStr(filename),
+ static_cast<CXFile>(
+ const_cast<FileEntry *>(File)),
+ isImport, isAngled, isModuleImport };
+ CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
+ FileMap[File] = idxFile;
+}
+
+void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
+ if (!CB.importedASTFile)
+ return;
+
+ Module *Mod = ImportD->getImportedModule();
+ if (!Mod)
+ return;
+
+ // If the imported module is part of the top-level module that we're
+ // indexing, it doesn't correspond to an imported AST file.
+ // FIXME: This assumes that AST files and top-level modules directly
+ // correspond, which is unlikely to remain true forever.
+ if (Module *SrcMod = ImportD->getImportedOwningModule())
+ if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
+ return;
+
+ FileEntry *FE = nullptr;
+ if (auto File = Mod->getASTFile())
+ FE = const_cast<FileEntry *>(&File->getFileEntry());
+ CXIdxImportedASTFileInfo Info = {static_cast<CXFile>(FE), Mod,
+ getIndexLoc(ImportD->getLocation()),
+ ImportD->isImplicit()};
+ CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
+ (void)astFile;
+}
+
+void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
+ if (!CB.importedASTFile)
+ return;
+
+ CXIdxImportedASTFileInfo Info = {
+ static_cast<CXFile>(
+ const_cast<FileEntry *>(File)),
+ /*module=*/nullptr,
+ getIndexLoc(SourceLocation()),
+ /*isImplicit=*/false
+ };
+ CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
+ (void)astFile;
+}
+
+void CXIndexDataConsumer::startedTranslationUnit() {
+ CXIdxClientContainer idxCont = nullptr;
+ if (CB.startedTranslationUnit)
+ idxCont = CB.startedTranslationUnit(ClientData, nullptr);
+ addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
+}
+
+void CXIndexDataConsumer::indexDiagnostics() {
+ if (!hasDiagnosticCallback())
+ return;
+
+ CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
+ handleDiagnosticSet(DiagSet);
+}
+
+void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
+ if (!CB.diagnostic)
+ return;
+
+ CB.diagnostic(ClientData, CXDiagSet, nullptr);
+}
+
+bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
+ SourceLocation Loc, CXCursor Cursor,
+ DeclInfo &DInfo,
+ const DeclContext *LexicalDC,
+ const DeclContext *SemaDC) {
+ if (!CB.indexDeclaration || !D)
+ return false;
+ if (D->isImplicit() && shouldIgnoreIfImplicit(D))
+ return false;
+
+ ScratchAlloc SA(*this);
+ getEntityInfo(D, DInfo.EntInfo, SA);
+ if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
+ || Loc.isInvalid())
+ return false;
+
+ if (!LexicalDC)
+ LexicalDC = D->getLexicalDeclContext();
+
+ if (shouldSuppressRefs())
+ markEntityOccurrenceInFile(D, Loc);
+
+ DInfo.entityInfo = &DInfo.EntInfo;
+ DInfo.cursor = Cursor;
+ DInfo.loc = getIndexLoc(Loc);
+ DInfo.isImplicit = D->isImplicit();
+
+ DInfo.attributes = DInfo.EntInfo.attributes;
+ DInfo.numAttributes = DInfo.EntInfo.numAttributes;
+
+ if (!SemaDC)
+ SemaDC = D->getDeclContext();
+ getContainerInfo(SemaDC, DInfo.SemanticContainer);
+ DInfo.semanticContainer = &DInfo.SemanticContainer;
+
+ if (LexicalDC == SemaDC) {
+ DInfo.lexicalContainer = &DInfo.SemanticContainer;
+ } else if (isTemplateImplicitInstantiation(D)) {
+ // Implicit instantiations have the lexical context of where they were
+ // instantiated first. We choose instead the semantic context because:
+ // 1) at the time that we see the instantiation we have not seen the
+ // function where it occurred yet.
+ // 2) the lexical context of the first instantiation is not useful
+ // information anyway.
+ DInfo.lexicalContainer = &DInfo.SemanticContainer;
+ } else {
+ getContainerInfo(LexicalDC, DInfo.LexicalContainer);
+ DInfo.lexicalContainer = &DInfo.LexicalContainer;
+ }
+
+ if (DInfo.isContainer) {
+ getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
+ DInfo.declAsContainer = &DInfo.DeclAsContainer;
+ }
+
+ CB.indexDeclaration(ClientData, &DInfo);
+ return true;
+}
+
+bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
+ SourceLocation Loc, CXCursor Cursor,
+ ObjCContainerDeclInfo &ContDInfo) {
+ ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
+ return handleDecl(D, Loc, Cursor, ContDInfo);
+}
+
+bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
+ bool isDef = D->isThisDeclarationADefinition();
+ bool isContainer = isDef;
+ bool isSkipped = false;
+ if (D->hasSkippedBody()) {
+ isSkipped = true;
+ isDef = true;
+ isContainer = false;
+ }
+
+ DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer);
+ if (isSkipped)
+ DInfo.flags |= CXIdxDeclFlag_Skipped;
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
+ DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
+ return handleCXXRecordDecl(CXXRD, D);
+
+ DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
+ D->isThisDeclarationADefinition());
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
+ DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
+ // For @class forward declarations, suppress them the same way as references.
+ if (!D->isThisDeclarationADefinition()) {
+ if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
+ return false; // already occurred.
+
+ // FIXME: This seems like the wrong definition for redeclaration.
+ bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
+ ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
+ /*isImplementation=*/false);
+ return handleObjCContainer(D, D->getLocation(),
+ MakeCursorObjCClassRef(D, D->getLocation(),
+ CXTU),
+ ContDInfo);
+ }
+
+ ScratchAlloc SA(*this);
+
+ CXIdxBaseClassInfo BaseClass;
+ EntityInfo BaseEntity;
+ BaseClass.cursor = clang_getNullCursor();
+ if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
+ getEntityInfo(SuperD, BaseEntity, SA);
+ SourceLocation SuperLoc = D->getSuperClassLoc();
+ BaseClass.base = &BaseEntity;
+ BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU);
+ BaseClass.loc = getIndexLoc(SuperLoc);
+
+ if (shouldSuppressRefs())
+ markEntityOccurrenceInFile(SuperD, SuperLoc);
+ }
+
+ ObjCProtocolList EmptyProtoList;
+ ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()
+ ? D->getReferencedProtocols()
+ : EmptyProtoList,
+ *this, SA);
+
+ ObjCInterfaceDeclInfo InterInfo(D);
+ InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
+ InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo;
+ InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass
+ : nullptr;
+ InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
+
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCImplementation(
+ const ObjCImplementationDecl *D) {
+ ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
+ /*isRedeclaration=*/true,
+ /*isImplementation=*/true);
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
+ if (!D->isThisDeclarationADefinition()) {
+ if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
+ return false; // already occurred.
+
+ // FIXME: This seems like the wrong definition for redeclaration.
+ bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
+ ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
+ isRedeclaration,
+ /*isImplementation=*/false);
+ return handleObjCContainer(D, D->getLocation(),
+ MakeCursorObjCProtocolRef(D, D->getLocation(),
+ CXTU),
+ ContDInfo);
+ }
+
+ ScratchAlloc SA(*this);
+ ObjCProtocolList EmptyProtoList;
+ ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition()
+ ? D->getReferencedProtocols()
+ : EmptyProtoList,
+ *this, SA);
+
+ ObjCProtocolDeclInfo ProtInfo(D);
+ ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
+
+ return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
+ ScratchAlloc SA(*this);
+
+ ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
+ EntityInfo ClassEntity;
+ const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
+ SourceLocation ClassLoc = D->getLocation();
+ SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
+ : D->getCategoryNameLoc();
+ getEntityInfo(IFaceD, ClassEntity, SA);
+
+ if (shouldSuppressRefs())
+ markEntityOccurrenceInFile(IFaceD, ClassLoc);
+
+ ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
+
+ CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
+ if (IFaceD) {
+ CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
+ CatDInfo.ObjCCatDeclInfo.classCursor =
+ MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
+ } else {
+ CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
+ CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
+ }
+ CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
+ CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
+ CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo;
+
+ return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
+ ScratchAlloc SA(*this);
+
+ const ObjCCategoryDecl *CatD = D->getCategoryDecl();
+ ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
+ EntityInfo ClassEntity;
+ const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
+ SourceLocation ClassLoc = D->getLocation();
+ SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ getEntityInfo(IFaceD, ClassEntity, SA);
+
+ if (shouldSuppressRefs())
+ markEntityOccurrenceInFile(IFaceD, ClassLoc);
+
+ CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
+ if (IFaceD) {
+ CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
+ CatDInfo.ObjCCatDeclInfo.classCursor =
+ MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
+ } else {
+ CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
+ CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
+ }
+ CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
+ CatDInfo.ObjCCatDeclInfo.protocols = nullptr;
+
+ return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
+}
+
+bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D,
+ SourceLocation Loc) {
+ bool isDef = D->isThisDeclarationADefinition();
+ bool isContainer = isDef;
+ bool isSkipped = false;
+ if (D->hasSkippedBody()) {
+ isSkipped = true;
+ isDef = true;
+ isContainer = false;
+ }
+
+ DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer);
+ if (isSkipped)
+ DInfo.flags |= CXIdxDeclFlag_Skipped;
+ return handleDecl(D, Loc, getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
+ const ObjCPropertyImplDecl *D) {
+ ObjCPropertyDecl *PD = D->getPropertyDecl();
+ auto *DC = D->getDeclContext();
+ return handleReference(PD, D->getLocation(), getCursor(D),
+ dyn_cast<NamedDecl>(DC), DC);
+}
+
+bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
+ SourceLocation Loc,
+ const DeclContext *LexicalDC) {
+ DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
+ /*isContainer=*/false);
+ return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, D->getDeclContext());
+}
+
+bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
+ ScratchAlloc SA(*this);
+
+ ObjCPropertyDeclInfo DInfo;
+ EntityInfo GetterEntity;
+ EntityInfo SetterEntity;
+
+ DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
+
+ if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) {
+ getEntityInfo(Getter, GetterEntity, SA);
+ DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
+ } else {
+ DInfo.ObjCPropDeclInfo.getter = nullptr;
+ }
+ if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
+ getEntityInfo(Setter, SetterEntity, SA);
+ DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
+ } else {
+ DInfo.ObjCPropDeclInfo.setter = nullptr;
+ }
+
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
+ /*isDefinition=*/true,
+ /*isContainer=*/true);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
+ return handleCXXRecordDecl(D->getTemplatedDecl(), D);
+}
+
+bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
+ /*isDefinition=*/D->isThisDeclarationADefinition(),
+ /*isContainer=*/D->isThisDeclarationADefinition());
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
+ DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
+ /*isDefinition=*/true, /*isContainer=*/false);
+ return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
+}
+
+bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
+ CXCursor Cursor,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ const Expr *E,
+ CXIdxEntityRefKind Kind,
+ CXSymbolRole Role) {
+ if (!CB.indexEntityReference)
+ return false;
+
+ if (!D || !DC)
+ return false;
+ if (Loc.isInvalid())
+ return false;
+ if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+ return false;
+ if (isNotFromSourceFile(D->getLocation()))
+ return false;
+ if (D->isImplicit() && shouldIgnoreIfImplicit(D))
+ return false;
+
+ if (shouldSuppressRefs()) {
+ if (markEntityOccurrenceInFile(D, Loc))
+ return false; // already occurred.
+ }
+
+ ScratchAlloc SA(*this);
+ EntityInfo RefEntity, ParentEntity;
+ getEntityInfo(D, RefEntity, SA);
+ if (!RefEntity.USR)
+ return false;
+
+ getEntityInfo(Parent, ParentEntity, SA);
+
+ ContainerInfo Container;
+ getContainerInfo(DC, Container);
+
+ CXIdxEntityRefInfo Info = { Kind,
+ Cursor,
+ getIndexLoc(Loc),
+ &RefEntity,
+ Parent ? &ParentEntity : nullptr,
+ &Container,
+ Role };
+ CB.indexEntityReference(ClientData, &Info);
+ return true;
+}
+
+bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
+ if (Loc.isInvalid())
+ return true;
+ SourceManager &SM = Ctx->getSourceManager();
+ SourceLocation FileLoc = SM.getFileLoc(Loc);
+ FileID FID = SM.getFileID(FileLoc);
+ return SM.getFileEntryForID(FID) == nullptr;
+}
+
+void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
+ CXIdxClientContainer container) {
+ if (!DC)
+ return;
+
+ ContainerMapTy::iterator I = ContainerMap.find(DC);
+ if (I == ContainerMap.end()) {
+ if (container)
+ ContainerMap[DC] = container;
+ return;
+ }
+ // Allow changing the container of a previously seen DeclContext so we
+ // can handle invalid user code, like a function re-definition.
+ if (container)
+ I->second = container;
+ else
+ ContainerMap.erase(I);
+}
+
+CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
+ if (!D)
+ return nullptr;
+ EntityMapTy::const_iterator I = EntityMap.find(D);
+ if (I == EntityMap.end())
+ return nullptr;
+ return I->second;
+}
+
+void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
+ if (!D)
+ return;
+ EntityMap[D] = client;
+}
+
+bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
+ const NamedDecl *OrigD) {
+ if (RD->isThisDeclarationADefinition()) {
+ ScratchAlloc SA(*this);
+ CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
+ /*isDefinition=*/RD->isThisDeclarationADefinition());
+ CXXBasesListInfo BaseList(RD, *this, SA);
+ CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
+ CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
+ CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
+
+ if (shouldSuppressRefs()) {
+ // Go through bases and mark them as referenced.
+ for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
+ const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
+ if (baseInfo->base) {
+ const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
+ SourceLocation
+ Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
+ markEntityOccurrenceInFile(BaseD, Loc);
+ }
+ }
+ }
+
+ return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
+ }
+
+ DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
+ /*isDefinition=*/RD->isThisDeclarationADefinition(),
+ /*isContainer=*/RD->isThisDeclarationADefinition());
+ return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
+}
+
+bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
+ SourceLocation Loc) {
+ if (!D || Loc.isInvalid())
+ return true;
+
+ SourceManager &SM = Ctx->getSourceManager();
+ D = getEntityDecl(D);
+
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
+ FileID FID = LocInfo.first;
+ if (FID.isInvalid())
+ return true;
+
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (!FE)
+ return true;
+ RefFileOccurrence RefOccur(FE, D);
+ std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
+ res = RefFileOccurrences.insert(RefOccur);
+ return !res.second; // already in map
+}
+
+const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
+ assert(D);
+ D = cast<NamedDecl>(D->getCanonicalDecl());
+
+ if (const ObjCImplementationDecl *
+ ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
+ return getEntityDecl(ImplD->getClassInterface());
+
+ } else if (const ObjCCategoryImplDecl *
+ CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
+ return getEntityDecl(CatImplD->getCategoryDecl());
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
+ return getEntityDecl(TemplD);
+ } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
+ return getEntityDecl(TemplD);
+ }
+
+ return D;
+}
+
+const DeclContext *
+CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
+ const DeclContext *DC = dyn_cast<DeclContext>(D);
+ if (DC)
+ return DC;
+
+ if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
+ DC = ClassTempl->getTemplatedDecl();
+ } else if (const FunctionTemplateDecl *
+ FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
+ DC = FuncTempl->getTemplatedDecl();
+ }
+
+ return DC;
+}
+
+CXIdxClientContainer
+CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
+ if (!DC)
+ return nullptr;
+
+ ContainerMapTy::const_iterator I = ContainerMap.find(DC);
+ if (I == ContainerMap.end())
+ return nullptr;
+
+ return I->second;
+}
+
+CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
+ if (!File)
+ return nullptr;
+
+ FileMapTy::iterator FI = FileMap.find(File);
+ if (FI != FileMap.end())
+ return FI->second;
+
+ return nullptr;
+}
+
+CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
+ CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 };
+ if (Loc.isInvalid())
+ return idxLoc;
+
+ idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
+ idxLoc.int_data = Loc.getRawEncoding();
+ return idxLoc;
+}
+
+void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
+ CXIdxClientFile *indexFile, CXFile *file,
+ unsigned *line, unsigned *column,
+ unsigned *offset) {
+ if (Loc.isInvalid())
+ return;
+
+ SourceManager &SM = Ctx->getSourceManager();
+ Loc = SM.getFileLoc(Loc);
+
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (FID.isInvalid())
+ return;
+
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (indexFile)
+ *indexFile = getIndexFile(FE);
+ if (file)
+ *file = const_cast<FileEntry *>(FE);
+ if (line)
+ *line = SM.getLineNumber(FID, FileOffset);
+ if (column)
+ *column = SM.getColumnNumber(FID, FileOffset);
+ if (offset)
+ *offset = FileOffset;
+}
+
+static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
+static CXIdxEntityCXXTemplateKind
+getEntityKindFromSymbolProperties(SymbolPropertySet K);
+static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
+
+void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
+ EntityInfo &EntityInfo,
+ ScratchAlloc &SA) {
+ if (!D)
+ return;
+
+ D = getEntityDecl(D);
+ EntityInfo.cursor = getCursor(D);
+ EntityInfo.Dcl = D;
+ EntityInfo.IndexCtx = this;
+
+ SymbolInfo SymInfo = getSymbolInfo(D);
+ EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang);
+ EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties);
+ EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
+
+ if (D->hasAttrs()) {
+ EntityInfo.AttrList = AttrListInfo::create(D, *this);
+ EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
+ EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
+ }
+
+ if (EntityInfo.kind == CXIdxEntity_Unexposed)
+ return;
+
+ if (IdentifierInfo *II = D->getIdentifier()) {
+ EntityInfo.name = SA.toCStr(II->getName());
+
+ } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
+ EntityInfo.name = nullptr; // anonymous tag/field/namespace.
+
+ } else {
+ SmallString<256> StrBuf;
+ {
+ llvm::raw_svector_ostream OS(StrBuf);
+ D->printName(OS);
+ }
+ EntityInfo.name = SA.copyCStr(StrBuf.str());
+ }
+
+ {
+ SmallString<512> StrBuf;
+ bool Ignore = getDeclCursorUSR(D, StrBuf);
+ if (Ignore) {
+ EntityInfo.USR = nullptr;
+ } else {
+ EntityInfo.USR = SA.copyCStr(StrBuf.str());
+ }
+ }
+}
+
+void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
+ ContainerInfo &ContInfo) {
+ ContInfo.cursor = getCursor(cast<Decl>(DC));
+ ContInfo.DC = DC;
+ ContInfo.IndexCtx = this;
+}
+
+CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
+ return MakeCursorTypeRef(TD, Loc, CXTU);
+ if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+ return MakeCursorObjCClassRef(ID, Loc, CXTU);
+ if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
+ return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
+ if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+ return MakeCursorTemplateRef(Template, Loc, CXTU);
+ if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
+ return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
+ if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
+ return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
+ if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
+ return MakeCursorMemberRef(Field, Loc, CXTU);
+ if (const VarDecl *Var = dyn_cast<VarDecl>(D))
+ return MakeCursorVariableRef(Var, Loc, CXTU);
+
+ return clang_getNullCursor();
+}
+
+bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
+ if (isa<ObjCInterfaceDecl>(D))
+ return false;
+ if (isa<ObjCCategoryDecl>(D))
+ return false;
+ if (isa<ObjCIvarDecl>(D))
+ return false;
+ if (isa<ObjCMethodDecl>(D))
+ return false;
+ if (isa<ImportDecl>(D))
+ return false;
+ return true;
+}
+
+bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
+ if (const ClassTemplateSpecializationDecl *
+ SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
+ }
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
+ }
+ return false;
+}
+
+static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) {
+ switch (K) {
+ case SymbolKind::Unknown:
+ case SymbolKind::Module:
+ case SymbolKind::Macro:
+ case SymbolKind::ClassProperty:
+ case SymbolKind::Using:
+ case SymbolKind::TemplateTypeParm:
+ case SymbolKind::TemplateTemplateParm:
+ case SymbolKind::NonTypeTemplateParm:
+ return CXIdxEntity_Unexposed;
+
+ case SymbolKind::Enum: return CXIdxEntity_Enum;
+ case SymbolKind::Struct: return CXIdxEntity_Struct;
+ case SymbolKind::Union: return CXIdxEntity_Union;
+ case SymbolKind::TypeAlias:
+ if (Lang == SymbolLanguage::CXX)
+ return CXIdxEntity_CXXTypeAlias;
+ return CXIdxEntity_Typedef;
+ case SymbolKind::Function: return CXIdxEntity_Function;
+ case SymbolKind::Variable: return CXIdxEntity_Variable;
+ case SymbolKind::Field:
+ if (Lang == SymbolLanguage::ObjC)
+ return CXIdxEntity_ObjCIvar;
+ return CXIdxEntity_Field;
+ case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
+ case SymbolKind::Class:
+ if (Lang == SymbolLanguage::ObjC)
+ return CXIdxEntity_ObjCClass;
+ return CXIdxEntity_CXXClass;
+ case SymbolKind::Protocol:
+ if (Lang == SymbolLanguage::ObjC)
+ return CXIdxEntity_ObjCProtocol;
+ return CXIdxEntity_CXXInterface;
+ case SymbolKind::Extension: return CXIdxEntity_ObjCCategory;
+ case SymbolKind::InstanceMethod:
+ if (Lang == SymbolLanguage::ObjC)
+ return CXIdxEntity_ObjCInstanceMethod;
+ return CXIdxEntity_CXXInstanceMethod;
+ case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod;
+ case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod;
+ case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty;
+ case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable;
+ case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace;
+ case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
+ case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
+ case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
+ case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
+ case SymbolKind::Parameter: return CXIdxEntity_Variable;
+ }
+ llvm_unreachable("invalid symbol kind");
+}
+
+static CXIdxEntityCXXTemplateKind
+getEntityKindFromSymbolProperties(SymbolPropertySet K) {
+ if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
+ return CXIdxEntity_TemplatePartialSpecialization;
+ if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
+ return CXIdxEntity_TemplateSpecialization;
+ if (K & (SymbolPropertySet)SymbolProperty::Generic)
+ return CXIdxEntity_Template;
+ return CXIdxEntity_NonTemplate;
+}
+
+static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
+ switch (L) {
+ case SymbolLanguage::C: return CXIdxEntityLang_C;
+ case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
+ case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
+ case SymbolLanguage::Swift: return CXIdxEntityLang_Swift;
+ }
+ llvm_unreachable("invalid symbol language");
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.h b/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.h
new file mode 100644
index 0000000000..8e6045dbf6
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXIndexDataConsumer.h
@@ -0,0 +1,500 @@
+//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
+
+#include "CXCursor.h"
+#include "Index_Internal.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace clang {
+ class FileEntry;
+ class MSPropertyDecl;
+ class ObjCPropertyDecl;
+ class ClassTemplateDecl;
+ class FunctionTemplateDecl;
+ class TypeAliasTemplateDecl;
+ class ClassTemplateSpecializationDecl;
+
+namespace cxindex {
+ class CXIndexDataConsumer;
+ class AttrListInfo;
+
+class ScratchAlloc {
+ CXIndexDataConsumer &IdxCtx;
+
+public:
+ explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
+ ScratchAlloc(const ScratchAlloc &SA);
+
+ ~ScratchAlloc();
+
+ const char *toCStr(StringRef Str);
+ const char *copyCStr(StringRef Str);
+
+ template <typename T>
+ T *allocate();
+};
+
+struct EntityInfo : public CXIdxEntityInfo {
+ const NamedDecl *Dcl;
+ CXIndexDataConsumer *IndexCtx;
+ IntrusiveRefCntPtr<AttrListInfo> AttrList;
+
+ EntityInfo() {
+ name = USR = nullptr;
+ attributes = nullptr;
+ numAttributes = 0;
+ }
+};
+
+struct ContainerInfo : public CXIdxContainerInfo {
+ const DeclContext *DC;
+ CXIndexDataConsumer *IndexCtx;
+};
+
+struct DeclInfo : public CXIdxDeclInfo {
+ enum DInfoKind {
+ Info_Decl,
+
+ Info_ObjCContainer,
+ Info_ObjCInterface,
+ Info_ObjCProtocol,
+ Info_ObjCCategory,
+
+ Info_ObjCProperty,
+
+ Info_CXXClass
+ };
+
+ DInfoKind Kind;
+
+ EntityInfo EntInfo;
+ ContainerInfo SemanticContainer;
+ ContainerInfo LexicalContainer;
+ ContainerInfo DeclAsContainer;
+
+ DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
+ : Kind(Info_Decl) {
+ this->isRedeclaration = isRedeclaration;
+ this->isDefinition = isDefinition;
+ this->isContainer = isContainer;
+ attributes = nullptr;
+ numAttributes = 0;
+ declAsContainer = semanticContainer = lexicalContainer = nullptr;
+ flags = 0;
+ }
+ DeclInfo(DInfoKind K,
+ bool isRedeclaration, bool isDefinition, bool isContainer)
+ : Kind(K) {
+ this->isRedeclaration = isRedeclaration;
+ this->isDefinition = isDefinition;
+ this->isContainer = isContainer;
+ attributes = nullptr;
+ numAttributes = 0;
+ declAsContainer = semanticContainer = lexicalContainer = nullptr;
+ flags = 0;
+ }
+};
+
+struct ObjCContainerDeclInfo : public DeclInfo {
+ CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
+
+ ObjCContainerDeclInfo(bool isForwardRef,
+ bool isRedeclaration,
+ bool isImplementation)
+ : DeclInfo(Info_ObjCContainer, isRedeclaration,
+ /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
+ init(isForwardRef, isImplementation);
+ }
+ ObjCContainerDeclInfo(DInfoKind K,
+ bool isForwardRef,
+ bool isRedeclaration,
+ bool isImplementation)
+ : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
+ /*isContainer=*/!isForwardRef) {
+ init(isForwardRef, isImplementation);
+ }
+
+ static bool classof(const DeclInfo *D) {
+ return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
+ }
+
+private:
+ void init(bool isForwardRef, bool isImplementation) {
+ if (isForwardRef)
+ ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
+ else if (isImplementation)
+ ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
+ else
+ ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
+ }
+};
+
+struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
+ CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
+ CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
+
+ ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
+ : ObjCContainerDeclInfo(Info_ObjCInterface,
+ /*isForwardRef=*/false,
+ /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
+ /*isImplementation=*/false) { }
+
+ static bool classof(const DeclInfo *D) {
+ return D->Kind == Info_ObjCInterface;
+ }
+};
+
+struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
+ CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
+
+ ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
+ : ObjCContainerDeclInfo(Info_ObjCProtocol,
+ /*isForwardRef=*/false,
+ /*isRedeclaration=*/D->getPreviousDecl(),
+ /*isImplementation=*/false) { }
+
+ static bool classof(const DeclInfo *D) {
+ return D->Kind == Info_ObjCProtocol;
+ }
+};
+
+struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
+ CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
+ CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
+
+ explicit ObjCCategoryDeclInfo(bool isImplementation)
+ : ObjCContainerDeclInfo(Info_ObjCCategory,
+ /*isForwardRef=*/false,
+ /*isRedeclaration=*/isImplementation,
+ /*isImplementation=*/isImplementation) { }
+
+ static bool classof(const DeclInfo *D) {
+ return D->Kind == Info_ObjCCategory;
+ }
+};
+
+struct ObjCPropertyDeclInfo : public DeclInfo {
+ CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
+
+ ObjCPropertyDeclInfo()
+ : DeclInfo(Info_ObjCProperty,
+ /*isRedeclaration=*/false, /*isDefinition=*/false,
+ /*isContainer=*/false) { }
+
+ static bool classof(const DeclInfo *D) {
+ return D->Kind == Info_ObjCProperty;
+ }
+};
+
+struct CXXClassDeclInfo : public DeclInfo {
+ CXIdxCXXClassDeclInfo CXXClassInfo;
+
+ CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
+ : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
+
+ static bool classof(const DeclInfo *D) {
+ return D->Kind == Info_CXXClass;
+ }
+};
+
+struct AttrInfo : public CXIdxAttrInfo {
+ const Attr *A;
+
+ AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
+ kind = Kind;
+ cursor = C;
+ loc = Loc;
+ this->A = A;
+ }
+};
+
+struct IBOutletCollectionInfo : public AttrInfo {
+ EntityInfo ClassInfo;
+ CXIdxIBOutletCollectionAttrInfo IBCollInfo;
+
+ IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
+ AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
+ assert(C.kind == CXCursor_IBOutletCollectionAttr);
+ IBCollInfo.objcClass = nullptr;
+ }
+
+ IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
+
+ static bool classof(const AttrInfo *A) {
+ return A->kind == CXIdxAttr_IBOutletCollection;
+ }
+};
+
+class AttrListInfo {
+ ScratchAlloc SA;
+
+ SmallVector<AttrInfo, 2> Attrs;
+ SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
+ SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
+ unsigned ref_cnt;
+
+ AttrListInfo(const AttrListInfo &) = delete;
+ void operator=(const AttrListInfo &) = delete;
+public:
+ AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
+
+ static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
+ CXIndexDataConsumer &IdxCtx);
+
+ const CXIdxAttrInfo *const *getAttrs() const {
+ if (CXAttrs.empty())
+ return nullptr;
+ return CXAttrs.data();
+ }
+ unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
+
+ /// Retain/Release only useful when we allocate a AttrListInfo from the
+ /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
+ // in the EntityInfo
+ void Retain() { ++ref_cnt; }
+ void Release() {
+ assert (ref_cnt > 0 && "Reference count is already zero.");
+ if (--ref_cnt == 0) {
+ // Memory is allocated from a BumpPtrAllocator, no need to delete it.
+ this->~AttrListInfo();
+ }
+ }
+};
+
+class CXIndexDataConsumer : public index::IndexDataConsumer {
+ ASTContext *Ctx;
+ CXClientData ClientData;
+ IndexerCallbacks &CB;
+ unsigned IndexOptions;
+ CXTranslationUnit CXTU;
+
+ typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
+ typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
+ ContainerMapTy;
+ typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
+
+ FileMapTy FileMap;
+ ContainerMapTy ContainerMap;
+ EntityMapTy EntityMap;
+
+ typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
+ llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
+
+ llvm::BumpPtrAllocator StrScratch;
+ unsigned StrAdapterCount;
+ friend class ScratchAlloc;
+
+ struct ObjCProtocolListInfo {
+ SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
+ SmallVector<EntityInfo, 4> ProtEntities;
+ SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
+
+ CXIdxObjCProtocolRefListInfo getListInfo() const {
+ CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
+ (unsigned)Prots.size() };
+ return Info;
+ }
+
+ ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
+ CXIndexDataConsumer &IdxCtx,
+ ScratchAlloc &SA);
+ };
+
+ struct CXXBasesListInfo {
+ SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
+ SmallVector<EntityInfo, 4> BaseEntities;
+ SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
+
+ const CXIdxBaseClassInfo *const *getBases() const {
+ return CXBases.data();
+ }
+ unsigned getNumBases() const { return (unsigned)CXBases.size(); }
+
+ CXXBasesListInfo(const CXXRecordDecl *D,
+ CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
+
+ private:
+ SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
+ };
+
+ friend class AttrListInfo;
+
+public:
+ CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
+ unsigned indexOptions, CXTranslationUnit cxTU)
+ : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
+ IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) {}
+
+ ASTContext &getASTContext() const { return *Ctx; }
+ CXTranslationUnit getCXTU() const { return CXTU; }
+
+ void setASTContext(ASTContext &ctx);
+ void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;
+
+ bool shouldSuppressRefs() const {
+ return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
+ }
+
+ bool shouldIndexFunctionLocalSymbols() const {
+ return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
+ }
+
+ bool shouldIndexImplicitTemplateInsts() const {
+ return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
+ }
+
+ static bool isFunctionLocalDecl(const Decl *D);
+
+ bool shouldAbort();
+
+ bool hasDiagnosticCallback() const { return CB.diagnostic; }
+
+ void enteredMainFile(const FileEntry *File);
+
+ void ppIncludedFile(SourceLocation hashLoc,
+ StringRef filename, const FileEntry *File,
+ bool isImport, bool isAngled, bool isModuleImport);
+
+ void importedModule(const ImportDecl *ImportD);
+ void importedPCH(const FileEntry *File);
+
+ void startedTranslationUnit();
+
+ void indexDiagnostics();
+
+ void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
+
+ bool handleFunction(const FunctionDecl *FD);
+
+ bool handleVar(const VarDecl *D);
+
+ bool handleField(const FieldDecl *D);
+
+ bool handleEnumerator(const EnumConstantDecl *D);
+
+ bool handleTagDecl(const TagDecl *D);
+
+ bool handleTypedefName(const TypedefNameDecl *D);
+
+ bool handleObjCInterface(const ObjCInterfaceDecl *D);
+ bool handleObjCImplementation(const ObjCImplementationDecl *D);
+
+ bool handleObjCProtocol(const ObjCProtocolDecl *D);
+
+ bool handleObjCCategory(const ObjCCategoryDecl *D);
+ bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
+
+ bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
+
+ bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
+ bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
+ const DeclContext *LexicalDC);
+
+ bool handleObjCProperty(const ObjCPropertyDecl *D);
+
+ bool handleNamespace(const NamespaceDecl *D);
+
+ bool handleClassTemplate(const ClassTemplateDecl *D);
+ bool handleFunctionTemplate(const FunctionTemplateDecl *D);
+ bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
+
+ bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ const Expr *E = nullptr,
+ CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
+ CXSymbolRole Role = CXSymbolRole_None);
+
+ bool isNotFromSourceFile(SourceLocation Loc) const;
+
+ void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
+ unsigned *line, unsigned *column, unsigned *offset);
+
+ CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
+ void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
+
+ CXIdxClientEntity getClientEntity(const Decl *D) const;
+ void setClientEntity(const Decl *D, CXIdxClientEntity client);
+
+ static bool isTemplateImplicitInstantiation(const Decl *D);
+
+private:
+ bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
+ ArrayRef<index::SymbolRelation> Relations,
+ SourceLocation Loc, ASTNodeInfo ASTNode) override;
+
+ bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod,
+ index::SymbolRoleSet Roles,
+ SourceLocation Loc) override;
+
+ void finish() override;
+
+ bool handleDecl(const NamedDecl *D,
+ SourceLocation Loc, CXCursor Cursor,
+ DeclInfo &DInfo,
+ const DeclContext *LexicalDC = nullptr,
+ const DeclContext *SemaDC = nullptr);
+
+ bool handleObjCContainer(const ObjCContainerDecl *D,
+ SourceLocation Loc, CXCursor Cursor,
+ ObjCContainerDeclInfo &ContDInfo);
+
+ bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
+
+ bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
+
+ const NamedDecl *getEntityDecl(const NamedDecl *D) const;
+
+ const DeclContext *getEntityContainer(const Decl *D) const;
+
+ CXIdxClientFile getIndexFile(const FileEntry *File);
+
+ CXIdxLoc getIndexLoc(SourceLocation Loc) const;
+
+ void getEntityInfo(const NamedDecl *D,
+ EntityInfo &EntityInfo,
+ ScratchAlloc &SA);
+
+ void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
+
+ CXCursor getCursor(const Decl *D) {
+ return cxcursor::MakeCXCursor(D, CXTU);
+ }
+
+ CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
+
+ static bool shouldIgnoreIfImplicit(const Decl *D);
+};
+
+inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
+ ++IdxCtx.StrAdapterCount;
+}
+inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
+ ++IdxCtx.StrAdapterCount;
+}
+
+inline ScratchAlloc::~ScratchAlloc() {
+ --IdxCtx.StrAdapterCount;
+ if (IdxCtx.StrAdapterCount == 0)
+ IdxCtx.StrScratch.Reset();
+}
+
+template <typename T>
+inline T *ScratchAlloc::allocate() {
+ return IdxCtx.StrScratch.Allocate<T>();
+}
+
+}} // end clang::cxindex
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.cpp b/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.cpp
new file mode 100644
index 0000000000..bb6942a45f
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.cpp
@@ -0,0 +1,394 @@
+//===-- CXLoadedDiagnostic.cpp - Handling of persisent diags ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements handling of persisent diagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXLoadedDiagnostic.h"
+#include "CXString.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Frontend/SerializedDiagnosticReader.h"
+#include "clang/Frontend/SerializedDiagnostics.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::DenseMap<unsigned, const char *> Strings;
+
+namespace {
+class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
+public:
+ CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
+ ~CXLoadedDiagnosticSetImpl() override {}
+
+ llvm::BumpPtrAllocator Alloc;
+ Strings Categories;
+ Strings WarningFlags;
+ Strings FileNames;
+
+ FileSystemOptions FO;
+ FileManager FakeFiles;
+ llvm::DenseMap<unsigned, const FileEntry *> Files;
+
+ /// Copy the string into our own allocator.
+ const char *copyString(StringRef Blob) {
+ char *mem = Alloc.Allocate<char>(Blob.size() + 1);
+ memcpy(mem, Blob.data(), Blob.size());
+ mem[Blob.size()] = '\0';
+ return mem;
+ }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Cleanup.
+//===----------------------------------------------------------------------===//
+
+CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
+
+//===----------------------------------------------------------------------===//
+// Public CXLoadedDiagnostic methods.
+//===----------------------------------------------------------------------===//
+
+CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
+ // FIXME: Fail more softly if the diagnostic level is unknown?
+ auto severityAsLevel = static_cast<serialized_diags::Level>(severity);
+ assert(severity == static_cast<unsigned>(severityAsLevel) &&
+ "unknown serialized diagnostic level");
+
+ switch (severityAsLevel) {
+#define CASE(X) case serialized_diags::X: return CXDiagnostic_##X;
+ CASE(Ignored)
+ CASE(Note)
+ CASE(Warning)
+ CASE(Error)
+ CASE(Fatal)
+#undef CASE
+ // The 'Remark' level isn't represented in the stable API.
+ case serialized_diags::Remark: return CXDiagnostic_Warning;
+ }
+
+ llvm_unreachable("Invalid diagnostic level");
+}
+
+static CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ uintptr_t V = (uintptr_t) DLoc;
+ V |= 0x1;
+ CXSourceLocation Loc = { { (void*) V, nullptr }, 0 };
+ return Loc;
+}
+
+CXSourceLocation CXLoadedDiagnostic::getLocation() const {
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ return makeLocation(&DiagLoc);
+}
+
+CXString CXLoadedDiagnostic::getSpelling() const {
+ return cxstring::createRef(Spelling);
+}
+
+CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
+ if (DiagOption.empty())
+ return cxstring::createEmpty();
+
+ // FIXME: possibly refactor with logic in CXStoredDiagnostic.
+ if (Disable)
+ *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str());
+ return cxstring::createDup((Twine("-W") + DiagOption).str());
+}
+
+unsigned CXLoadedDiagnostic::getCategory() const {
+ return category;
+}
+
+CXString CXLoadedDiagnostic::getCategoryText() const {
+ return cxstring::createDup(CategoryText);
+}
+
+unsigned CXLoadedDiagnostic::getNumRanges() const {
+ return Ranges.size();
+}
+
+CXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
+ assert(Range < Ranges.size());
+ return Ranges[Range];
+}
+
+unsigned CXLoadedDiagnostic::getNumFixIts() const {
+ return FixIts.size();
+}
+
+CXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const {
+ assert(FixIt < FixIts.size());
+ if (ReplacementRange)
+ *ReplacementRange = FixIts[FixIt].first;
+ return cxstring::createRef(FixIts[FixIt].second);
+}
+
+void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned int *line,
+ unsigned int *column,
+ unsigned int *offset) {
+
+
+ // CXSourceLocation consists of the following fields:
+ //
+ // void *ptr_data[2];
+ // unsigned int_data;
+ //
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ //
+ // For now, do the unoptimized approach and store the data in a side
+ // data structure. We can optimize this case later.
+
+ uintptr_t V = (uintptr_t) location.ptr_data[0];
+ assert((V & 0x1) == 1);
+ V &= ~(uintptr_t)1;
+
+ const Location &Loc = *((Location*)V);
+
+ if (file)
+ *file = Loc.file;
+ if (line)
+ *line = Loc.line;
+ if (column)
+ *column = Loc.column;
+ if (offset)
+ *offset = Loc.offset;
+}
+
+//===----------------------------------------------------------------------===//
+// Deserialize diagnostics.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DiagLoader : serialized_diags::SerializedDiagnosticReader {
+ enum CXLoadDiag_Error *error;
+ CXString *errorString;
+ std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags;
+ SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags;
+
+ std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
+ if (error)
+ *error = code;
+ if (errorString)
+ *errorString = cxstring::createDup(err);
+ return serialized_diags::SDError::HandlerFailed;
+ }
+
+ std::error_code reportInvalidFile(llvm::StringRef err) {
+ return reportBad(CXLoadDiag_InvalidFile, err);
+ }
+
+ std::error_code readRange(const serialized_diags::Location &SDStart,
+ const serialized_diags::Location &SDEnd,
+ CXSourceRange &SR);
+
+ std::error_code readLocation(const serialized_diags::Location &SDLoc,
+ CXLoadedDiagnostic::Location &LoadedLoc);
+
+protected:
+ std::error_code visitStartOfDiagnostic() override;
+ std::error_code visitEndOfDiagnostic() override;
+
+ std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
+
+ std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
+
+ std::error_code visitDiagnosticRecord(
+ unsigned Severity, const serialized_diags::Location &Location,
+ unsigned Category, unsigned Flag, StringRef Message) override;
+
+ std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
+ unsigned Timestamp,
+ StringRef Name) override;
+
+ std::error_code visitFixitRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End,
+ StringRef CodeToInsert) override;
+
+ std::error_code
+ visitSourceRangeRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End) override;
+
+public:
+ DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
+ : error(e), errorString(es) {
+ if (error)
+ *error = CXLoadDiag_None;
+ if (errorString)
+ *errorString = cxstring::createEmpty();
+ }
+
+ CXDiagnosticSet load(const char *file);
+};
+} // end anonymous namespace
+
+CXDiagnosticSet DiagLoader::load(const char *file) {
+ TopDiags = std::make_unique<CXLoadedDiagnosticSetImpl>();
+
+ std::error_code EC = readDiagnostics(file);
+ if (EC) {
+ switch (EC.value()) {
+ case static_cast<int>(serialized_diags::SDError::HandlerFailed):
+ // We've already reported the problem.
+ break;
+ case static_cast<int>(serialized_diags::SDError::CouldNotLoad):
+ reportBad(CXLoadDiag_CannotLoad, EC.message());
+ break;
+ default:
+ reportInvalidFile(EC.message());
+ break;
+ }
+ return nullptr;
+ }
+
+ return (CXDiagnosticSet)TopDiags.release();
+}
+
+std::error_code
+DiagLoader::readLocation(const serialized_diags::Location &SDLoc,
+ CXLoadedDiagnostic::Location &LoadedLoc) {
+ unsigned FileID = SDLoc.FileID;
+ if (FileID == 0)
+ LoadedLoc.file = nullptr;
+ else {
+ LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]);
+ if (!LoadedLoc.file)
+ return reportInvalidFile("Corrupted file entry in source location");
+ }
+ LoadedLoc.line = SDLoc.Line;
+ LoadedLoc.column = SDLoc.Col;
+ LoadedLoc.offset = SDLoc.Offset;
+ return std::error_code();
+}
+
+std::error_code
+DiagLoader::readRange(const serialized_diags::Location &SDStart,
+ const serialized_diags::Location &SDEnd,
+ CXSourceRange &SR) {
+ CXLoadedDiagnostic::Location *Start, *End;
+ Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
+ End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
+
+ std::error_code EC;
+ if ((EC = readLocation(SDStart, *Start)))
+ return EC;
+ if ((EC = readLocation(SDEnd, *End)))
+ return EC;
+
+ CXSourceLocation startLoc = makeLocation(Start);
+ CXSourceLocation endLoc = makeLocation(End);
+ SR = clang_getRange(startLoc, endLoc);
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitStartOfDiagnostic() {
+ CurrentDiags.push_back(std::make_unique<CXLoadedDiagnostic>());
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitEndOfDiagnostic() {
+ auto D = CurrentDiags.pop_back_val();
+ if (CurrentDiags.empty())
+ TopDiags->appendDiagnostic(std::move(D));
+ else
+ CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D));
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) {
+ // FIXME: Why do we care about long strings?
+ if (Name.size() > 65536)
+ return reportInvalidFile("Out-of-bounds string in category");
+ TopDiags->Categories[ID] = TopDiags->copyString(Name);
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) {
+ // FIXME: Why do we care about long strings?
+ if (Name.size() > 65536)
+ return reportInvalidFile("Out-of-bounds string in warning flag");
+ TopDiags->WarningFlags[ID] = TopDiags->copyString(Name);
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size,
+ unsigned Timestamp,
+ StringRef Name) {
+ // FIXME: Why do we care about long strings?
+ if (Name.size() > 65536)
+ return reportInvalidFile("Out-of-bounds string in filename");
+ TopDiags->FileNames[ID] = TopDiags->copyString(Name);
+ TopDiags->Files[ID] =
+ TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp);
+ return std::error_code();
+}
+
+std::error_code
+DiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End) {
+ CXSourceRange SR;
+ if (std::error_code EC = readRange(Start, End, SR))
+ return EC;
+ CurrentDiags.back()->Ranges.push_back(SR);
+ return std::error_code();
+}
+
+std::error_code
+DiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End,
+ StringRef CodeToInsert) {
+ CXSourceRange SR;
+ if (std::error_code EC = readRange(Start, End, SR))
+ return EC;
+ // FIXME: Why do we care about long strings?
+ if (CodeToInsert.size() > 65536)
+ return reportInvalidFile("Out-of-bounds string in FIXIT");
+ CurrentDiags.back()->FixIts.push_back(
+ std::make_pair(SR, TopDiags->copyString(CodeToInsert)));
+ return std::error_code();
+}
+
+std::error_code DiagLoader::visitDiagnosticRecord(
+ unsigned Severity, const serialized_diags::Location &Location,
+ unsigned Category, unsigned Flag, StringRef Message) {
+ CXLoadedDiagnostic &D = *CurrentDiags.back();
+ D.severity = Severity;
+ if (std::error_code EC = readLocation(Location, D.DiagLoc))
+ return EC;
+ D.category = Category;
+ D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : "";
+ D.CategoryText = Category ? TopDiags->Categories[Category] : "";
+ D.Spelling = TopDiags->copyString(Message);
+ return std::error_code();
+}
+
+CXDiagnosticSet clang_loadDiagnostics(const char *file,
+ enum CXLoadDiag_Error *error,
+ CXString *errorString) {
+ DiagLoader L(error, errorString);
+ return L.load(file);
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.h b/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.h
new file mode 100644
index 0000000000..93995d7bb7
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXLoadedDiagnostic.h
@@ -0,0 +1,93 @@
+/*===-- CXLoadedDiagnostic.h - Handling of persisent diags ------*- C++ -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements handling of persisent diagnostics. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXLOADEDDIAGNOSTIC_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXLOADEDDIAGNOSTIC_H
+
+#include "CIndexDiagnostic.h"
+#include "llvm/ADT/StringRef.h"
+#include "clang/Basic/LLVM.h"
+#include <vector>
+
+namespace clang {
+class CXLoadedDiagnostic : public CXDiagnosticImpl {
+public:
+ CXLoadedDiagnostic() : CXDiagnosticImpl(LoadedDiagnosticKind),
+ severity(0), category(0) {}
+
+ ~CXLoadedDiagnostic() override;
+
+ /// Return the severity of the diagnostic.
+ CXDiagnosticSeverity getSeverity() const override;
+
+ /// Return the location of the diagnostic.
+ CXSourceLocation getLocation() const override;
+
+ /// Return the spelling of the diagnostic.
+ CXString getSpelling() const override;
+
+ /// Return the text for the diagnostic option.
+ CXString getDiagnosticOption(CXString *Disable) const override;
+
+ /// Return the category of the diagnostic.
+ unsigned getCategory() const override;
+
+ /// Return the category string of the diagnostic.
+ CXString getCategoryText() const override;
+
+ /// Return the number of source ranges for the diagnostic.
+ unsigned getNumRanges() const override;
+
+ /// Return the source ranges for the diagnostic.
+ CXSourceRange getRange(unsigned Range) const override;
+
+ /// Return the number of FixIts.
+ unsigned getNumFixIts() const override;
+
+ /// Return the FixIt information (source range and inserted text).
+ CXString getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const override;
+
+ static bool classof(const CXDiagnosticImpl *D) {
+ return D->getKind() == LoadedDiagnosticKind;
+ }
+
+ /// Decode the CXSourceLocation into file, line, column, and offset.
+ static void decodeLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+ struct Location {
+ CXFile file;
+ unsigned line;
+ unsigned column;
+ unsigned offset;
+
+ Location() : line(0), column(0), offset(0) {}
+ };
+
+ Location DiagLoc;
+
+ std::vector<CXSourceRange> Ranges;
+ std::vector<std::pair<CXSourceRange, const char *> > FixIts;
+ const char *Spelling;
+ llvm::StringRef DiagOption;
+ llvm::StringRef CategoryText;
+ unsigned severity;
+ unsigned category;
+};
+}
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXSourceLocation.cpp b/contrib/libs/clang14/tools/libclang/CXSourceLocation.cpp
new file mode 100644
index 0000000000..39c2194f7d
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXSourceLocation.cpp
@@ -0,0 +1,374 @@
+//===- CXSourceLocation.cpp - CXSourceLocations APIs ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXSourceLocations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXSourceLocation.h"
+#include "CIndexer.h"
+#include "CLog.h"
+#include "CXLoadedDiagnostic.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
+
+using namespace clang;
+using namespace clang::cxindex;
+
+//===----------------------------------------------------------------------===//
+// Internal predicates on CXSourceLocations.
+//===----------------------------------------------------------------------===//
+
+static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
+ // If the lowest bit is clear then the first ptr_data entry is a SourceManager
+ // pointer, or the CXSourceLocation is a null location.
+ return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Basic construction and comparison of CXSourceLocations and CXSourceRanges.
+//===----------------------------------------------------------------------===//
+
+CXSourceLocation clang_getNullLocation() {
+ CXSourceLocation Result = { { nullptr, nullptr }, 0 };
+ return Result;
+}
+
+unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
+ return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
+ loc1.ptr_data[1] == loc2.ptr_data[1] &&
+ loc1.int_data == loc2.int_data);
+}
+
+CXSourceRange clang_getNullRange() {
+ CXSourceRange Result = { { nullptr, nullptr }, 0, 0 };
+ return Result;
+}
+
+CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
+ if (!isASTUnitSourceLocation(begin)) {
+ if (isASTUnitSourceLocation(end))
+ return clang_getNullRange();
+ CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
+ return Result;
+ }
+
+ if (begin.ptr_data[0] != end.ptr_data[0] ||
+ begin.ptr_data[1] != end.ptr_data[1])
+ return clang_getNullRange();
+
+ CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
+ begin.int_data, end.int_data };
+
+ return Result;
+}
+
+unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
+ return range1.ptr_data[0] == range2.ptr_data[0]
+ && range1.ptr_data[1] == range2.ptr_data[1]
+ && range1.begin_int_data == range2.begin_int_data
+ && range1.end_int_data == range2.end_int_data;
+}
+
+int clang_Range_isNull(CXSourceRange range) {
+ return clang_equalRanges(range, clang_getNullRange());
+}
+
+
+CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+ // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
+ if ((uintptr_t)range.ptr_data[0] & 0x1) {
+ CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
+ return Result;
+ }
+
+ CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
+ range.begin_int_data };
+ return Result;
+}
+
+CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+ // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
+ if ((uintptr_t)range.ptr_data[0] & 0x1) {
+ CXSourceLocation Result = { { range.ptr_data[1], nullptr }, 0 };
+ return Result;
+ }
+
+ CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
+ range.end_int_data };
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Getting CXSourceLocations and CXSourceRanges from a translation unit.
+//===----------------------------------------------------------------------===//
+
+CXSourceLocation clang_getLocation(CXTranslationUnit TU,
+ CXFile file,
+ unsigned line,
+ unsigned column) {
+ if (cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullLocation();
+ }
+ if (!file)
+ return clang_getNullLocation();
+ if (line == 0 || column == 0)
+ return clang_getNullLocation();
+
+ LogRef Log = Logger::make(__func__);
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+ const FileEntry *File = static_cast<const FileEntry *>(file);
+ SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
+ if (SLoc.isInvalid()) {
+ if (Log)
+ *Log << llvm::format("(\"%s\", %d, %d) = invalid",
+ File->getName().str().c_str(), line, column);
+ return clang_getNullLocation();
+ }
+
+ CXSourceLocation CXLoc =
+ cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
+ if (Log)
+ *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName().str().c_str(),
+ line, column)
+ << CXLoc;
+
+ return CXLoc;
+}
+
+CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
+ CXFile file,
+ unsigned offset) {
+ if (cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return clang_getNullLocation();
+ }
+ if (!file)
+ return clang_getNullLocation();
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+
+ SourceLocation SLoc
+ = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
+
+ if (SLoc.isInvalid())
+ return clang_getNullLocation();
+
+ return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
+}
+
+//===----------------------------------------------------------------------===//
+// Routines for expanding and manipulating CXSourceLocations, regardless
+// of their origin.
+//===----------------------------------------------------------------------===//
+
+static void createNullLocation(CXFile *file, unsigned *line,
+ unsigned *column, unsigned *offset) {
+ if (file)
+ *file = nullptr;
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ if (offset)
+ *offset = 0;
+}
+
+static void createNullLocation(CXString *filename, unsigned *line,
+ unsigned *column, unsigned *offset = nullptr) {
+ if (filename)
+ *filename = cxstring::createEmpty();
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ if (offset)
+ *offset = 0;
+}
+
+int clang_Location_isInSystemHeader(CXSourceLocation location) {
+ const SourceLocation Loc =
+ SourceLocation::getFromRawEncoding(location.int_data);
+ if (Loc.isInvalid())
+ return 0;
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ return SM.isInSystemHeader(Loc);
+}
+
+int clang_Location_isFromMainFile(CXSourceLocation location) {
+ const SourceLocation Loc =
+ SourceLocation::getFromRawEncoding(location.int_data);
+ if (Loc.isInvalid())
+ return 0;
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ return SM.isWrittenInMainFile(Loc);
+}
+
+void clang_getExpansionLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ if (!isASTUnitSourceLocation(location)) {
+ CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
+ return;
+ }
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid()) {
+ createNullLocation(file, line, column, offset);
+ return;
+ }
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
+
+ // Check that the FileID is invalid on the expansion location.
+ // This can manifest in invalid code.
+ FileID fileID = SM.getFileID(ExpansionLoc);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
+ if (Invalid || !sloc.isFile()) {
+ createNullLocation(file, line, column, offset);
+ return;
+ }
+
+ if (file)
+ *file = const_cast<FileEntry *>(SM.getFileEntryForSLocEntry(sloc));
+ if (line)
+ *line = SM.getExpansionLineNumber(ExpansionLoc);
+ if (column)
+ *column = SM.getExpansionColumnNumber(ExpansionLoc);
+ if (offset)
+ *offset = SM.getDecomposedLoc(ExpansionLoc).second;
+}
+
+void clang_getPresumedLocation(CXSourceLocation location,
+ CXString *filename,
+ unsigned *line,
+ unsigned *column) {
+ if (!isASTUnitSourceLocation(location)) {
+ // Other SourceLocation implementations do not support presumed locations
+ // at this time.
+ createNullLocation(filename, line, column);
+ return;
+ }
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid()) {
+ createNullLocation(filename, line, column);
+ return;
+ }
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager *>(location.ptr_data[0]);
+ PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
+ if (PreLoc.isInvalid()) {
+ createNullLocation(filename, line, column);
+ return;
+ }
+
+ if (filename) *filename = cxstring::createRef(PreLoc.getFilename());
+ if (line) *line = PreLoc.getLine();
+ if (column) *column = PreLoc.getColumn();
+}
+
+void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ // Redirect to new API.
+ clang_getExpansionLocation(location, file, line, column, offset);
+}
+
+void clang_getSpellingLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ if (!isASTUnitSourceLocation(location)) {
+ CXLoadedDiagnostic::decodeLocation(location, file, line,
+ column, offset);
+ return;
+ }
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ // FIXME: This should call SourceManager::getSpellingLoc().
+ SourceLocation SpellLoc = SM.getFileLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (FID.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ if (file)
+ *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
+ if (line)
+ *line = SM.getLineNumber(FID, FileOffset);
+ if (column)
+ *column = SM.getColumnNumber(FID, FileOffset);
+ if (offset)
+ *offset = FileOffset;
+}
+
+void clang_getFileLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ if (!isASTUnitSourceLocation(location)) {
+ CXLoadedDiagnostic::decodeLocation(location, file, line,
+ column, offset);
+ return;
+ }
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ SourceLocation FileLoc = SM.getFileLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(FileLoc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (FID.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ if (file)
+ *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
+ if (line)
+ *line = SM.getLineNumber(FID, FileOffset);
+ if (column)
+ *column = SM.getColumnNumber(FID, FileOffset);
+ if (offset)
+ *offset = FileOffset;
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXSourceLocation.h b/contrib/libs/clang14/tools/libclang/CXSourceLocation.h
new file mode 100644
index 0000000000..c86f685037
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXSourceLocation.h
@@ -0,0 +1,81 @@
+//===- CXSourceLocation.h - CXSourceLocations Utilities ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXSourceLocations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXSOURCELOCATION_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXSOURCELOCATION_H
+
+#include "clang-c/Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+class SourceManager;
+
+namespace cxloc {
+
+/// Translate a Clang source location into a CIndex source location.
+static inline CXSourceLocation
+translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts,
+ SourceLocation Loc) {
+ if (Loc.isInvalid())
+ return clang_getNullLocation();
+
+ CXSourceLocation Result = { { &SM, &LangOpts, },
+ Loc.getRawEncoding() };
+ return Result;
+}
+
+/// Translate a Clang source location into a CIndex source location.
+static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
+ SourceLocation Loc) {
+ return translateSourceLocation(Context.getSourceManager(),
+ Context.getLangOpts(),
+ Loc);
+}
+
+/// Translate a Clang source range into a CIndex source range.
+///
+/// Clang internally represents ranges where the end location points to the
+/// start of the token at the end. However, for external clients it is more
+/// useful to have a CXSourceRange be a proper half-open interval. This routine
+/// does the appropriate translation.
+CXSourceRange translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const CharSourceRange &R);
+
+/// Translate a Clang source range into a CIndex source range.
+static inline CXSourceRange translateSourceRange(ASTContext &Context,
+ SourceRange R) {
+ return translateSourceRange(Context.getSourceManager(),
+ Context.getLangOpts(),
+ CharSourceRange::getTokenRange(R));
+}
+
+static inline SourceLocation translateSourceLocation(CXSourceLocation L) {
+ return SourceLocation::getFromRawEncoding(L.int_data);
+}
+
+static inline SourceRange translateCXSourceRange(CXSourceRange R) {
+ return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data),
+ SourceLocation::getFromRawEncoding(R.end_int_data));
+}
+
+/// Translates CXSourceRange to CharSourceRange.
+/// The semantics of \p R are:
+/// R.begin_int_data is first character of the range.
+/// R.end_int_data is one character past the end of the range.
+CharSourceRange translateCXRangeToCharRange(CXSourceRange R);
+}} // end namespace: clang::cxloc
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXStoredDiagnostic.cpp b/contrib/libs/clang14/tools/libclang/CXStoredDiagnostic.cpp
new file mode 100644
index 0000000000..c4c24876e7
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXStoredDiagnostic.cpp
@@ -0,0 +1,111 @@
+//===- CXStoredDiagnostic.cpp - Diagnostics C Interface -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements part of the diagnostic functions of the Clang C interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CXTranslationUnit.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/ADT/Twine.h"
+
+using namespace clang;
+using namespace clang::cxloc;
+
+CXDiagnosticSeverity CXStoredDiagnostic::getSeverity() const {
+ switch (Diag.getLevel()) {
+ case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
+ case DiagnosticsEngine::Note: return CXDiagnostic_Note;
+ case DiagnosticsEngine::Remark:
+ // The 'Remark' level isn't represented in the stable API.
+ case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
+ case DiagnosticsEngine::Error: return CXDiagnostic_Error;
+ case DiagnosticsEngine::Fatal: return CXDiagnostic_Fatal;
+ }
+
+ llvm_unreachable("Invalid diagnostic level");
+}
+
+CXSourceLocation CXStoredDiagnostic::getLocation() const {
+ if (Diag.getLocation().isInvalid())
+ return clang_getNullLocation();
+
+ return translateSourceLocation(Diag.getLocation().getManager(),
+ LangOpts, Diag.getLocation());
+}
+
+CXString CXStoredDiagnostic::getSpelling() const {
+ return cxstring::createRef(Diag.getMessage());
+}
+
+CXString CXStoredDiagnostic::getDiagnosticOption(CXString *Disable) const {
+ unsigned ID = Diag.getID();
+ StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID);
+ if (!Option.empty()) {
+ if (Disable)
+ *Disable = cxstring::createDup((Twine("-Wno-") + Option).str());
+ return cxstring::createDup((Twine("-W") + Option).str());
+ }
+
+ if (ID == diag::fatal_too_many_errors) {
+ if (Disable)
+ *Disable = cxstring::createRef("-ferror-limit=0");
+ return cxstring::createRef("-ferror-limit=");
+ }
+
+ return cxstring::createEmpty();
+}
+
+unsigned CXStoredDiagnostic::getCategory() const {
+ return DiagnosticIDs::getCategoryNumberForDiag(Diag.getID());
+}
+
+CXString CXStoredDiagnostic::getCategoryText() const {
+ unsigned catID = DiagnosticIDs::getCategoryNumberForDiag(Diag.getID());
+ return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(catID));
+}
+
+unsigned CXStoredDiagnostic::getNumRanges() const {
+ if (Diag.getLocation().isInvalid())
+ return 0;
+
+ return Diag.range_size();
+}
+
+CXSourceRange CXStoredDiagnostic::getRange(unsigned int Range) const {
+ assert(Diag.getLocation().isValid());
+ return translateSourceRange(Diag.getLocation().getManager(),
+ LangOpts,
+ Diag.range_begin()[Range]);
+}
+
+unsigned CXStoredDiagnostic::getNumFixIts() const {
+ if (Diag.getLocation().isInvalid())
+ return 0;
+ return Diag.fixit_size();
+}
+
+CXString CXStoredDiagnostic::getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const {
+ const FixItHint &Hint = Diag.fixit_begin()[FixIt];
+ if (ReplacementRange) {
+ // Create a range that covers the entire replacement (or
+ // removal) range, adjusting the end of the range to point to
+ // the end of the token.
+ *ReplacementRange = translateSourceRange(Diag.getLocation().getManager(),
+ LangOpts, Hint.RemoveRange);
+ }
+ return cxstring::createDup(Hint.CodeToInsert);
+}
+
diff --git a/contrib/libs/clang14/tools/libclang/CXString.cpp b/contrib/libs/clang14/tools/libclang/CXString.cpp
new file mode 100644
index 0000000000..2754795f4a
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXString.cpp
@@ -0,0 +1,191 @@
+//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXStrings. It should be the
+// only file that has internal knowledge of the encoding of the data in
+// CXStrings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "clang-c/Index.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+/// Describes the kind of underlying data in CXString.
+enum CXStringFlag {
+ /// CXString contains a 'const char *' that it doesn't own.
+ CXS_Unmanaged,
+
+ /// CXString contains a 'const char *' that it allocated with malloc().
+ CXS_Malloc,
+
+ /// CXString contains a CXStringBuf that needs to be returned to the
+ /// CXStringPool.
+ CXS_StringBuf
+};
+
+namespace clang {
+namespace cxstring {
+
+//===----------------------------------------------------------------------===//
+// Basic generation of CXStrings.
+//===----------------------------------------------------------------------===//
+
+CXString createEmpty() {
+ CXString Str;
+ Str.data = "";
+ Str.private_flags = CXS_Unmanaged;
+ return Str;
+}
+
+CXString createNull() {
+ CXString Str;
+ Str.data = nullptr;
+ Str.private_flags = CXS_Unmanaged;
+ return Str;
+}
+
+CXString createRef(const char *String) {
+ if (String && String[0] == '\0')
+ return createEmpty();
+
+ CXString Str;
+ Str.data = String;
+ Str.private_flags = CXS_Unmanaged;
+ return Str;
+}
+
+CXString createDup(const char *String) {
+ if (!String)
+ return createNull();
+
+ if (String[0] == '\0')
+ return createEmpty();
+
+ CXString Str;
+ Str.data = strdup(String);
+ Str.private_flags = CXS_Malloc;
+ return Str;
+}
+
+CXString createRef(StringRef String) {
+ // If the string is not nul-terminated, we have to make a copy.
+
+ // FIXME: This is doing a one past end read, and should be removed! For memory
+ // we don't manage, the API string can become unterminated at any time outside
+ // our control.
+
+ if (!String.empty() && String.data()[String.size()] != 0)
+ return createDup(String);
+
+ CXString Result;
+ Result.data = String.data();
+ Result.private_flags = (unsigned) CXS_Unmanaged;
+ return Result;
+}
+
+CXString createDup(StringRef String) {
+ CXString Result;
+ char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
+ memmove(Spelling, String.data(), String.size());
+ Spelling[String.size()] = 0;
+ Result.data = Spelling;
+ Result.private_flags = (unsigned) CXS_Malloc;
+ return Result;
+}
+
+CXString createCXString(CXStringBuf *buf) {
+ CXString Str;
+ Str.data = buf;
+ Str.private_flags = (unsigned) CXS_StringBuf;
+ return Str;
+}
+
+CXStringSet *createSet(const std::vector<std::string> &Strings) {
+ CXStringSet *Set = new CXStringSet;
+ Set->Count = Strings.size();
+ Set->Strings = new CXString[Set->Count];
+ for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
+ Set->Strings[SI] = createDup(Strings[SI]);
+ return Set;
+}
+
+
+//===----------------------------------------------------------------------===//
+// String pools.
+//===----------------------------------------------------------------------===//
+
+CXStringPool::~CXStringPool() {
+ for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
+ I != E; ++I) {
+ delete *I;
+ }
+}
+
+CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
+ if (Pool.empty())
+ return new CXStringBuf(TU);
+
+ CXStringBuf *Buf = Pool.back();
+ Buf->Data.clear();
+ Pool.pop_back();
+ return Buf;
+}
+
+CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
+ return TU->StringPool->getCXStringBuf(TU);
+}
+
+void CXStringBuf::dispose() {
+ TU->StringPool->Pool.push_back(this);
+}
+
+bool isManagedByPool(CXString str) {
+ return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
+}
+
+} // end namespace cxstring
+} // end namespace clang
+
+//===----------------------------------------------------------------------===//
+// libClang public APIs.
+//===----------------------------------------------------------------------===//
+
+const char *clang_getCString(CXString string) {
+ if (string.private_flags == (unsigned) CXS_StringBuf) {
+ return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
+ }
+ return static_cast<const char *>(string.data);
+}
+
+void clang_disposeString(CXString string) {
+ switch ((CXStringFlag) string.private_flags) {
+ case CXS_Unmanaged:
+ break;
+ case CXS_Malloc:
+ if (string.data)
+ free(const_cast<void *>(string.data));
+ break;
+ case CXS_StringBuf:
+ static_cast<cxstring::CXStringBuf *>(
+ const_cast<void *>(string.data))->dispose();
+ break;
+ }
+}
+
+void clang_disposeStringSet(CXStringSet *set) {
+ for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
+ clang_disposeString(set->Strings[SI]);
+ delete[] set->Strings;
+ delete set;
+}
+
diff --git a/contrib/libs/clang14/tools/libclang/CXString.h b/contrib/libs/clang14/tools/libclang/CXString.h
new file mode 100644
index 0000000000..809bdec3d6
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXString.h
@@ -0,0 +1,108 @@
+//===- CXString.h - Routines for manipulating CXStrings -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXStrings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXSTRING_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXSTRING_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace cxstring {
+
+struct CXStringBuf;
+
+/// Create a CXString object for an empty "" string.
+CXString createEmpty();
+
+/// Create a CXString object for an NULL string.
+///
+/// A NULL string should be used as an "invalid" value in case of errors.
+CXString createNull();
+
+/// Create a CXString object from a nul-terminated C string. New
+/// CXString may contain a pointer to \p String.
+///
+/// \p String should not be changed by the caller afterwards.
+CXString createRef(const char *String);
+
+/// Create a CXString object from a nul-terminated C string. New
+/// CXString will contain a copy of \p String.
+///
+/// \p String can be changed or freed by the caller.
+CXString createDup(const char *String);
+
+/// Create a CXString object from a StringRef. New CXString may
+/// contain a pointer to the undrelying data of \p String.
+///
+/// \p String should not be changed by the caller afterwards.
+CXString createRef(StringRef String);
+
+/// Create a CXString object from a StringRef. New CXString will
+/// contain a copy of \p String.
+///
+/// \p String can be changed or freed by the caller.
+CXString createDup(StringRef String);
+
+// Usually std::string is intended to be used as backing storage for CXString.
+// In this case, call \c createRef(String.c_str()).
+//
+// If you need to make a copy, call \c createDup(StringRef(String)).
+CXString createRef(std::string String) = delete;
+
+/// Create a CXString object that is backed by a string buffer.
+CXString createCXString(CXStringBuf *buf);
+
+CXStringSet *createSet(const std::vector<std::string> &Strings);
+
+/// A string pool used for fast allocation/deallocation of strings.
+class CXStringPool {
+public:
+ ~CXStringPool();
+
+ CXStringBuf *getCXStringBuf(CXTranslationUnit TU);
+
+private:
+ std::vector<CXStringBuf *> Pool;
+
+ friend struct CXStringBuf;
+};
+
+struct CXStringBuf {
+ SmallString<128> Data;
+ CXTranslationUnit TU;
+
+ CXStringBuf(CXTranslationUnit TU) : TU(TU) {}
+
+ /// Return this buffer to the pool.
+ void dispose();
+};
+
+CXStringBuf *getCXStringBuf(CXTranslationUnit TU);
+
+/// Returns true if the CXString data is managed by a pool.
+bool isManagedByPool(CXString str);
+
+}
+
+static inline StringRef getContents(const CXUnsavedFile &UF) {
+ return StringRef(UF.Contents, UF.Length);
+}
+}
+
+#endif
+
diff --git a/contrib/libs/clang14/tools/libclang/CXTranslationUnit.h b/contrib/libs/clang14/tools/libclang/CXTranslationUnit.h
new file mode 100644
index 0000000000..3424bf2997
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXTranslationUnit.h
@@ -0,0 +1,89 @@
+//===- CXTranslationUnit.h - Routines for manipulating CXTranslationUnits -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXTranslationUnits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXTRANSLATIONUNIT_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXTRANSLATIONUNIT_H
+
+#include "CLog.h"
+#include "CXString.h"
+#include "clang-c/Index.h"
+
+namespace clang {
+ class ASTUnit;
+ class CIndexer;
+namespace index {
+class CommentToXMLConverter;
+} // namespace index
+} // namespace clang
+
+struct CXTranslationUnitImpl {
+ clang::CIndexer *CIdx;
+ clang::ASTUnit *TheASTUnit;
+ clang::cxstring::CXStringPool *StringPool;
+ void *Diagnostics;
+ void *OverridenCursorsPool;
+ clang::index::CommentToXMLConverter *CommentToXML;
+ unsigned ParsingOptions;
+ std::vector<std::string> Arguments;
+};
+
+struct CXTargetInfoImpl {
+ CXTranslationUnit TranslationUnit;
+};
+
+namespace clang {
+namespace cxtu {
+
+CXTranslationUnitImpl *MakeCXTranslationUnit(CIndexer *CIdx,
+ std::unique_ptr<ASTUnit> AU);
+
+static inline ASTUnit *getASTUnit(CXTranslationUnit TU) {
+ if (!TU)
+ return nullptr;
+ return TU->TheASTUnit;
+}
+
+/// \returns true if the ASTUnit has a diagnostic about the AST file being
+/// corrupted.
+bool isASTReadError(ASTUnit *AU);
+
+static inline bool isNotUsableTU(CXTranslationUnit TU) {
+ return !TU;
+}
+
+#define LOG_BAD_TU(TU) \
+ do { \
+ LOG_FUNC_SECTION { \
+ *Log << "called with a bad TU: " << TU; \
+ } \
+ } while(false)
+
+class CXTUOwner {
+ CXTranslationUnitImpl *TU;
+
+public:
+ CXTUOwner(CXTranslationUnitImpl *tu) : TU(tu) { }
+ ~CXTUOwner();
+
+ CXTranslationUnitImpl *getTU() const { return TU; }
+
+ CXTranslationUnitImpl *takeTU() {
+ CXTranslationUnitImpl *retTU = TU;
+ TU = nullptr;
+ return retTU;
+ }
+};
+
+
+}} // end namespace clang::cxtu
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CXType.cpp b/contrib/libs/clang14/tools/libclang/CXType.cpp
new file mode 100644
index 0000000000..822ab3bb64
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXType.cpp
@@ -0,0 +1,1338 @@
+//===- CXType.cpp - Implements 'CXTypes' aspect of libclang ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--------------------------------------------------------------------===//
+//
+// This file implements the 'CXTypes' API hooks in the Clang-C library.
+//
+//===--------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "CXType.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Frontend/ASTUnit.h"
+
+using namespace clang;
+
+static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
+#define BTCASE(K) case BuiltinType::K: return CXType_##K
+ switch (BT->getKind()) {
+ BTCASE(Void);
+ BTCASE(Bool);
+ BTCASE(Char_U);
+ BTCASE(UChar);
+ BTCASE(Char16);
+ BTCASE(Char32);
+ BTCASE(UShort);
+ BTCASE(UInt);
+ BTCASE(ULong);
+ BTCASE(ULongLong);
+ BTCASE(UInt128);
+ BTCASE(Char_S);
+ BTCASE(SChar);
+ case BuiltinType::WChar_S: return CXType_WChar;
+ case BuiltinType::WChar_U: return CXType_WChar;
+ BTCASE(Short);
+ BTCASE(Int);
+ BTCASE(Long);
+ BTCASE(LongLong);
+ BTCASE(Int128);
+ BTCASE(Half);
+ BTCASE(Float);
+ BTCASE(Double);
+ BTCASE(LongDouble);
+ BTCASE(ShortAccum);
+ BTCASE(Accum);
+ BTCASE(LongAccum);
+ BTCASE(UShortAccum);
+ BTCASE(UAccum);
+ BTCASE(ULongAccum);
+ BTCASE(Float16);
+ BTCASE(Float128);
+ BTCASE(Ibm128);
+ BTCASE(NullPtr);
+ BTCASE(Overload);
+ BTCASE(Dependent);
+ BTCASE(ObjCId);
+ BTCASE(ObjCClass);
+ BTCASE(ObjCSel);
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) BTCASE(Id);
+#include "clang/Basic/OpenCLImageTypes.def"
+#undef IMAGE_TYPE
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) BTCASE(Id);
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ BTCASE(OCLSampler);
+ BTCASE(OCLEvent);
+ BTCASE(OCLQueue);
+ BTCASE(OCLReserveID);
+ default:
+ return CXType_Unexposed;
+ }
+#undef BTCASE
+}
+
+static CXTypeKind GetTypeKind(QualType T) {
+ const Type *TP = T.getTypePtrOrNull();
+ if (!TP)
+ return CXType_Invalid;
+
+#define TKCASE(K) case Type::K: return CXType_##K
+ switch (TP->getTypeClass()) {
+ case Type::Builtin:
+ return GetBuiltinTypeKind(cast<BuiltinType>(TP));
+ TKCASE(Complex);
+ TKCASE(Pointer);
+ TKCASE(BlockPointer);
+ TKCASE(LValueReference);
+ TKCASE(RValueReference);
+ TKCASE(Record);
+ TKCASE(Enum);
+ TKCASE(Typedef);
+ TKCASE(ObjCInterface);
+ TKCASE(ObjCObject);
+ TKCASE(ObjCObjectPointer);
+ TKCASE(ObjCTypeParam);
+ TKCASE(FunctionNoProto);
+ TKCASE(FunctionProto);
+ TKCASE(ConstantArray);
+ TKCASE(IncompleteArray);
+ TKCASE(VariableArray);
+ TKCASE(DependentSizedArray);
+ TKCASE(Vector);
+ TKCASE(ExtVector);
+ TKCASE(MemberPointer);
+ TKCASE(Auto);
+ TKCASE(Elaborated);
+ TKCASE(Pipe);
+ TKCASE(Attributed);
+ TKCASE(Atomic);
+ default:
+ return CXType_Unexposed;
+ }
+#undef TKCASE
+}
+
+
+CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
+ CXTypeKind TK = CXType_Invalid;
+
+ if (TU && !T.isNull()) {
+ // Handle attributed types as the original type
+ if (auto *ATT = T->getAs<AttributedType>()) {
+ if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes)) {
+ // Return the equivalent type which represents the canonically
+ // equivalent type.
+ return MakeCXType(ATT->getEquivalentType(), TU);
+ }
+ }
+ // Handle paren types as the original type
+ if (auto *PTT = T->getAs<ParenType>()) {
+ return MakeCXType(PTT->getInnerType(), TU);
+ }
+
+ ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
+ if (Ctx.getLangOpts().ObjC) {
+ QualType UnqualT = T.getUnqualifiedType();
+ if (Ctx.isObjCIdType(UnqualT))
+ TK = CXType_ObjCId;
+ else if (Ctx.isObjCClassType(UnqualT))
+ TK = CXType_ObjCClass;
+ else if (Ctx.isObjCSelType(UnqualT))
+ TK = CXType_ObjCSel;
+ }
+
+ /* Handle decayed types as the original type */
+ if (const DecayedType *DT = T->getAs<DecayedType>()) {
+ return MakeCXType(DT->getOriginalType(), TU);
+ }
+ }
+ if (TK == CXType_Invalid)
+ TK = GetTypeKind(T);
+
+ CXType CT = { TK, { TK == CXType_Invalid ? nullptr
+ : T.getAsOpaquePtr(), TU } };
+ return CT;
+}
+
+using cxtype::MakeCXType;
+
+static inline QualType GetQualType(CXType CT) {
+ return QualType::getFromOpaquePtr(CT.data[0]);
+}
+
+static inline CXTranslationUnit GetTU(CXType CT) {
+ return static_cast<CXTranslationUnit>(CT.data[1]);
+}
+
+static Optional<ArrayRef<TemplateArgument>>
+GetTemplateArguments(QualType Type) {
+ assert(!Type.isNull());
+ if (const auto *Specialization = Type->getAs<TemplateSpecializationType>())
+ return Specialization->template_arguments();
+
+ if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) {
+ const auto *TemplateDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
+ if (TemplateDecl)
+ return TemplateDecl->getTemplateArgs().asArray();
+ }
+
+ return None;
+}
+
+static Optional<QualType> TemplateArgumentToQualType(const TemplateArgument &A) {
+ if (A.getKind() == TemplateArgument::Type)
+ return A.getAsType();
+ return None;
+}
+
+static Optional<QualType>
+FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> TA, unsigned index) {
+ unsigned current = 0;
+ for (const auto &A : TA) {
+ if (A.getKind() == TemplateArgument::Pack) {
+ if (index < current + A.pack_size())
+ return TemplateArgumentToQualType(A.getPackAsArray()[index - current]);
+ current += A.pack_size();
+ continue;
+ }
+ if (current == index)
+ return TemplateArgumentToQualType(A);
+ current++;
+ }
+ return None;
+}
+
+CXType clang_getCursorType(CXCursor C) {
+ using namespace cxcursor;
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ if (!TU)
+ return MakeCXType(QualType(), TU);
+
+ ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext();
+ if (clang_isExpression(C.kind)) {
+ QualType T = cxcursor::getCursorExpr(C)->getType();
+ return MakeCXType(T, TU);
+ }
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return MakeCXType(QualType(), TU);
+
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
+ return MakeCXType(Context.getTypeDeclType(TD), TU);
+ if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+ return MakeCXType(Context.getObjCInterfaceType(ID), TU);
+ if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
+ return MakeCXType(DD->getType(), TU);
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ return MakeCXType(VD->getType(), TU);
+ if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
+ return MakeCXType(PD->getType(), TU);
+ if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ return MakeCXType(FTD->getTemplatedDecl()->getType(), TU);
+ return MakeCXType(QualType(), TU);
+ }
+
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ QualType T
+ = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
+ return MakeCXType(T, TU);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
+ return MakeCXType(T, TU);
+ }
+
+ case CXCursor_TypeRef: {
+ QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
+ return MakeCXType(T, TU);
+
+ }
+
+ case CXCursor_CXXBaseSpecifier:
+ return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
+
+ case CXCursor_MemberRef:
+ return cxtype::MakeCXType(getCursorMemberRef(C).first->getType(), TU);
+
+ case CXCursor_VariableRef:
+ return cxtype::MakeCXType(getCursorVariableRef(C).first->getType(), TU);
+
+ case CXCursor_ObjCProtocolRef:
+ case CXCursor_TemplateRef:
+ case CXCursor_NamespaceRef:
+ case CXCursor_OverloadedDeclRef:
+ default:
+ break;
+ }
+
+ return MakeCXType(QualType(), TU);
+ }
+
+ return MakeCXType(QualType(), TU);
+}
+
+CXString clang_getTypeSpelling(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return cxstring::createEmpty();
+
+ CXTranslationUnit TU = GetTU(CT);
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
+
+ T.print(OS, PP);
+
+ return cxstring::createDup(OS.str());
+}
+
+CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
+ using namespace cxcursor;
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+
+ if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
+ QualType T = TD->getUnderlyingType();
+ return MakeCXType(T, TU);
+ }
+
+ return MakeCXType(QualType(), TU);
+ }
+
+ return MakeCXType(QualType(), TU);
+}
+
+CXType clang_getEnumDeclIntegerType(CXCursor C) {
+ using namespace cxcursor;
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+
+ if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
+ QualType T = TD->getIntegerType();
+ return MakeCXType(T, TU);
+ }
+
+ return MakeCXType(QualType(), TU);
+ }
+
+ return MakeCXType(QualType(), TU);
+}
+
+long long clang_getEnumConstantDeclValue(CXCursor C) {
+ using namespace cxcursor;
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+
+ if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
+ return TD->getInitVal().getSExtValue();
+ }
+
+ return LLONG_MIN;
+ }
+
+ return LLONG_MIN;
+}
+
+unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
+ using namespace cxcursor;
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+
+ if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
+ return TD->getInitVal().getZExtValue();
+ }
+
+ return ULLONG_MAX;
+ }
+
+ return ULLONG_MAX;
+}
+
+int clang_getFieldDeclBitWidth(CXCursor C) {
+ using namespace cxcursor;
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+
+ if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
+ if (FD->isBitField())
+ return FD->getBitWidthValue(getCursorContext(C));
+ }
+ }
+
+ return -1;
+}
+
+CXType clang_getCanonicalType(CXType CT) {
+ if (CT.kind == CXType_Invalid)
+ return CT;
+
+ QualType T = GetQualType(CT);
+ CXTranslationUnit TU = GetTU(CT);
+
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ return MakeCXType(cxtu::getASTUnit(TU)->getASTContext()
+ .getCanonicalType(T),
+ TU);
+}
+
+unsigned clang_isConstQualifiedType(CXType CT) {
+ QualType T = GetQualType(CT);
+ return T.isLocalConstQualified();
+}
+
+unsigned clang_isVolatileQualifiedType(CXType CT) {
+ QualType T = GetQualType(CT);
+ return T.isLocalVolatileQualified();
+}
+
+unsigned clang_isRestrictQualifiedType(CXType CT) {
+ QualType T = GetQualType(CT);
+ return T.isLocalRestrictQualified();
+}
+
+unsigned clang_getAddressSpace(CXType CT) {
+ QualType T = GetQualType(CT);
+
+ // For non language-specific address space, use separate helper function.
+ if (T.getAddressSpace() >= LangAS::FirstTargetAddressSpace) {
+ return T.getQualifiers().getAddressSpaceAttributePrintValue();
+ }
+ // FIXME: this function returns either a LangAS or a target AS
+ // Those values can overlap which makes this function rather unpredictable
+ // for any caller
+ return (unsigned)T.getAddressSpace();
+}
+
+CXString clang_getTypedefName(CXType CT) {
+ QualType T = GetQualType(CT);
+ const TypedefType *TT = T->getAs<TypedefType>();
+ if (TT) {
+ TypedefNameDecl *TD = TT->getDecl();
+ if (TD)
+ return cxstring::createDup(TD->getNameAsString().c_str());
+ }
+ return cxstring::createEmpty();
+}
+
+CXType clang_getPointeeType(CXType CT) {
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (!TP)
+ return MakeCXType(QualType(), GetTU(CT));
+
+try_again:
+ switch (TP->getTypeClass()) {
+ case Type::Pointer:
+ T = cast<PointerType>(TP)->getPointeeType();
+ break;
+ case Type::BlockPointer:
+ T = cast<BlockPointerType>(TP)->getPointeeType();
+ break;
+ case Type::LValueReference:
+ case Type::RValueReference:
+ T = cast<ReferenceType>(TP)->getPointeeType();
+ break;
+ case Type::ObjCObjectPointer:
+ T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
+ break;
+ case Type::MemberPointer:
+ T = cast<MemberPointerType>(TP)->getPointeeType();
+ break;
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
+ if (TP)
+ goto try_again;
+ break;
+ default:
+ T = QualType();
+ break;
+ }
+ return MakeCXType(T, GetTU(CT));
+}
+
+CXCursor clang_getTypeDeclaration(CXType CT) {
+ if (CT.kind == CXType_Invalid)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (!TP)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ Decl *D = nullptr;
+
+try_again:
+ switch (TP->getTypeClass()) {
+ case Type::Typedef:
+ D = cast<TypedefType>(TP)->getDecl();
+ break;
+ case Type::ObjCObject:
+ D = cast<ObjCObjectType>(TP)->getInterface();
+ break;
+ case Type::ObjCInterface:
+ D = cast<ObjCInterfaceType>(TP)->getDecl();
+ break;
+ case Type::Record:
+ case Type::Enum:
+ D = cast<TagType>(TP)->getDecl();
+ break;
+ case Type::TemplateSpecialization:
+ if (const RecordType *Record = TP->getAs<RecordType>())
+ D = Record->getDecl();
+ else
+ D = cast<TemplateSpecializationType>(TP)->getTemplateName()
+ .getAsTemplateDecl();
+ break;
+
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ TP = cast<DeducedType>(TP)->getDeducedType().getTypePtrOrNull();
+ if (TP)
+ goto try_again;
+ break;
+
+ case Type::InjectedClassName:
+ D = cast<InjectedClassNameType>(TP)->getDecl();
+ break;
+
+ // FIXME: Template type parameters!
+
+ case Type::Elaborated:
+ TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
+ goto try_again;
+
+ default:
+ break;
+ }
+
+ if (!D)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ return cxcursor::MakeCXCursor(D, GetTU(CT));
+}
+
+CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
+ const char *s = nullptr;
+#define TKIND(X) case CXType_##X: s = "" #X ""; break
+ switch (K) {
+ TKIND(Invalid);
+ TKIND(Unexposed);
+ TKIND(Void);
+ TKIND(Bool);
+ TKIND(Char_U);
+ TKIND(UChar);
+ TKIND(Char16);
+ TKIND(Char32);
+ TKIND(UShort);
+ TKIND(UInt);
+ TKIND(ULong);
+ TKIND(ULongLong);
+ TKIND(UInt128);
+ TKIND(Char_S);
+ TKIND(SChar);
+ case CXType_WChar: s = "WChar"; break;
+ TKIND(Short);
+ TKIND(Int);
+ TKIND(Long);
+ TKIND(LongLong);
+ TKIND(Int128);
+ TKIND(Half);
+ TKIND(Float);
+ TKIND(Double);
+ TKIND(LongDouble);
+ TKIND(ShortAccum);
+ TKIND(Accum);
+ TKIND(LongAccum);
+ TKIND(UShortAccum);
+ TKIND(UAccum);
+ TKIND(ULongAccum);
+ TKIND(Float16);
+ TKIND(Float128);
+ TKIND(Ibm128);
+ TKIND(NullPtr);
+ TKIND(Overload);
+ TKIND(Dependent);
+ TKIND(ObjCId);
+ TKIND(ObjCClass);
+ TKIND(ObjCSel);
+ TKIND(Complex);
+ TKIND(Pointer);
+ TKIND(BlockPointer);
+ TKIND(LValueReference);
+ TKIND(RValueReference);
+ TKIND(Record);
+ TKIND(Enum);
+ TKIND(Typedef);
+ TKIND(ObjCInterface);
+ TKIND(ObjCObject);
+ TKIND(ObjCObjectPointer);
+ TKIND(ObjCTypeParam);
+ TKIND(FunctionNoProto);
+ TKIND(FunctionProto);
+ TKIND(ConstantArray);
+ TKIND(IncompleteArray);
+ TKIND(VariableArray);
+ TKIND(DependentSizedArray);
+ TKIND(Vector);
+ TKIND(ExtVector);
+ TKIND(MemberPointer);
+ TKIND(Auto);
+ TKIND(Elaborated);
+ TKIND(Pipe);
+ TKIND(Attributed);
+ TKIND(BFloat16);
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id);
+#include "clang/Basic/OpenCLImageTypes.def"
+#undef IMAGE_TYPE
+#define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) TKIND(Id);
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ TKIND(OCLSampler);
+ TKIND(OCLEvent);
+ TKIND(OCLQueue);
+ TKIND(OCLReserveID);
+ TKIND(Atomic);
+ }
+#undef TKIND
+ return cxstring::createRef(s);
+}
+
+unsigned clang_equalTypes(CXType A, CXType B) {
+ return A.data[0] == B.data[0] && A.data[1] == B.data[1];
+}
+
+unsigned clang_isFunctionTypeVariadic(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return 0;
+
+ if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
+ return (unsigned)FD->isVariadic();
+
+ if (T->getAs<FunctionNoProtoType>())
+ return 1;
+
+ return 0;
+}
+
+CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return CXCallingConv_Invalid;
+
+ if (const FunctionType *FD = T->getAs<FunctionType>()) {
+#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
+ switch (FD->getCallConv()) {
+ TCALLINGCONV(C);
+ TCALLINGCONV(X86StdCall);
+ TCALLINGCONV(X86FastCall);
+ TCALLINGCONV(X86ThisCall);
+ TCALLINGCONV(X86Pascal);
+ TCALLINGCONV(X86RegCall);
+ TCALLINGCONV(X86VectorCall);
+ TCALLINGCONV(AArch64VectorCall);
+ TCALLINGCONV(Win64);
+ TCALLINGCONV(X86_64SysV);
+ TCALLINGCONV(AAPCS);
+ TCALLINGCONV(AAPCS_VFP);
+ TCALLINGCONV(IntelOclBicc);
+ TCALLINGCONV(Swift);
+ TCALLINGCONV(SwiftAsync);
+ TCALLINGCONV(PreserveMost);
+ TCALLINGCONV(PreserveAll);
+ case CC_SpirFunction: return CXCallingConv_Unexposed;
+ case CC_OpenCLKernel: return CXCallingConv_Unexposed;
+ break;
+ }
+#undef TCALLINGCONV
+ }
+
+ return CXCallingConv_Invalid;
+}
+
+int clang_getNumArgTypes(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return -1;
+
+ if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
+ return FD->getNumParams();
+ }
+
+ if (T->getAs<FunctionNoProtoType>()) {
+ return 0;
+ }
+
+ return -1;
+}
+
+CXType clang_getArgType(CXType X, unsigned i) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(X));
+
+ if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
+ unsigned numParams = FD->getNumParams();
+ if (i >= numParams)
+ return MakeCXType(QualType(), GetTU(X));
+
+ return MakeCXType(FD->getParamType(i), GetTU(X));
+ }
+
+ return MakeCXType(QualType(), GetTU(X));
+}
+
+CXType clang_getResultType(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(X));
+
+ if (const FunctionType *FD = T->getAs<FunctionType>())
+ return MakeCXType(FD->getReturnType(), GetTU(X));
+
+ return MakeCXType(QualType(), GetTU(X));
+}
+
+CXType clang_getCursorResultType(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
+ return MakeCXType(MD->getReturnType(), cxcursor::getCursorTU(C));
+
+ return clang_getResultType(clang_getCursorType(C));
+ }
+
+ return MakeCXType(QualType(), cxcursor::getCursorTU(C));
+}
+
+// FIXME: We should expose the canThrow(...) result instead of the EST.
+static CXCursor_ExceptionSpecificationKind
+getExternalExceptionSpecificationKind(ExceptionSpecificationType EST) {
+ switch (EST) {
+ case EST_None:
+ return CXCursor_ExceptionSpecificationKind_None;
+ case EST_DynamicNone:
+ return CXCursor_ExceptionSpecificationKind_DynamicNone;
+ case EST_Dynamic:
+ return CXCursor_ExceptionSpecificationKind_Dynamic;
+ case EST_MSAny:
+ return CXCursor_ExceptionSpecificationKind_MSAny;
+ case EST_BasicNoexcept:
+ return CXCursor_ExceptionSpecificationKind_BasicNoexcept;
+ case EST_NoThrow:
+ return CXCursor_ExceptionSpecificationKind_NoThrow;
+ case EST_NoexceptFalse:
+ case EST_NoexceptTrue:
+ case EST_DependentNoexcept:
+ return CXCursor_ExceptionSpecificationKind_ComputedNoexcept;
+ case EST_Unevaluated:
+ return CXCursor_ExceptionSpecificationKind_Unevaluated;
+ case EST_Uninstantiated:
+ return CXCursor_ExceptionSpecificationKind_Uninstantiated;
+ case EST_Unparsed:
+ return CXCursor_ExceptionSpecificationKind_Unparsed;
+ }
+ llvm_unreachable("invalid EST value");
+}
+
+int clang_getExceptionSpecificationType(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return -1;
+
+ if (const auto *FD = T->getAs<FunctionProtoType>())
+ return getExternalExceptionSpecificationKind(FD->getExceptionSpecType());
+
+ return -1;
+}
+
+int clang_getCursorExceptionSpecificationType(CXCursor C) {
+ if (clang_isDeclaration(C.kind))
+ return clang_getExceptionSpecificationType(clang_getCursorType(C));
+
+ return -1;
+}
+
+unsigned clang_isPODType(CXType X) {
+ QualType T = GetQualType(X);
+ if (T.isNull())
+ return 0;
+
+ CXTranslationUnit TU = GetTU(X);
+
+ return T.isPODType(cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
+}
+
+CXType clang_getElementType(CXType CT) {
+ QualType ET = QualType();
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP) {
+ switch (TP->getTypeClass()) {
+ case Type::ConstantArray:
+ ET = cast<ConstantArrayType> (TP)->getElementType();
+ break;
+ case Type::IncompleteArray:
+ ET = cast<IncompleteArrayType> (TP)->getElementType();
+ break;
+ case Type::VariableArray:
+ ET = cast<VariableArrayType> (TP)->getElementType();
+ break;
+ case Type::DependentSizedArray:
+ ET = cast<DependentSizedArrayType> (TP)->getElementType();
+ break;
+ case Type::Vector:
+ ET = cast<VectorType> (TP)->getElementType();
+ break;
+ case Type::ExtVector:
+ ET = cast<ExtVectorType>(TP)->getElementType();
+ break;
+ case Type::Complex:
+ ET = cast<ComplexType> (TP)->getElementType();
+ break;
+ default:
+ break;
+ }
+ }
+ return MakeCXType(ET, GetTU(CT));
+}
+
+long long clang_getNumElements(CXType CT) {
+ long long result = -1;
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP) {
+ switch (TP->getTypeClass()) {
+ case Type::ConstantArray:
+ result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
+ break;
+ case Type::Vector:
+ result = cast<VectorType> (TP)->getNumElements();
+ break;
+ case Type::ExtVector:
+ result = cast<ExtVectorType>(TP)->getNumElements();
+ break;
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+CXType clang_getArrayElementType(CXType CT) {
+ QualType ET = QualType();
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP) {
+ switch (TP->getTypeClass()) {
+ case Type::ConstantArray:
+ ET = cast<ConstantArrayType> (TP)->getElementType();
+ break;
+ case Type::IncompleteArray:
+ ET = cast<IncompleteArrayType> (TP)->getElementType();
+ break;
+ case Type::VariableArray:
+ ET = cast<VariableArrayType> (TP)->getElementType();
+ break;
+ case Type::DependentSizedArray:
+ ET = cast<DependentSizedArrayType> (TP)->getElementType();
+ break;
+ default:
+ break;
+ }
+ }
+ return MakeCXType(ET, GetTU(CT));
+}
+
+long long clang_getArraySize(CXType CT) {
+ long long result = -1;
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP) {
+ switch (TP->getTypeClass()) {
+ case Type::ConstantArray:
+ result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
+ break;
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+static bool isIncompleteTypeWithAlignment(QualType QT) {
+ return QT->isIncompleteArrayType() || !QT->isIncompleteType();
+}
+
+long long clang_Type_getAlignOf(CXType T) {
+ if (T.kind == CXType_Invalid)
+ return CXTypeLayoutError_Invalid;
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
+ QualType QT = GetQualType(T);
+ // [expr.alignof] p1: return size_t value for complete object type, reference
+ // or array.
+ // [expr.alignof] p3: if reference type, return size of referenced type
+ if (QT->isReferenceType())
+ QT = QT.getNonReferenceType();
+ if (!isIncompleteTypeWithAlignment(QT))
+ return CXTypeLayoutError_Incomplete;
+ if (QT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ if (const auto *Deduced = dyn_cast<DeducedType>(QT))
+ if (Deduced->getDeducedType().isNull())
+ return CXTypeLayoutError_Undeduced;
+ // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
+ // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
+ // if (QT->isVoidType()) return 1;
+ return Ctx.getTypeAlignInChars(QT).getQuantity();
+}
+
+CXType clang_Type_getClassType(CXType CT) {
+ QualType ET = QualType();
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP && TP->getTypeClass() == Type::MemberPointer) {
+ ET = QualType(cast<MemberPointerType> (TP)->getClass(), 0);
+ }
+ return MakeCXType(ET, GetTU(CT));
+}
+
+long long clang_Type_getSizeOf(CXType T) {
+ if (T.kind == CXType_Invalid)
+ return CXTypeLayoutError_Invalid;
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
+ QualType QT = GetQualType(T);
+ // [expr.sizeof] p2: if reference type, return size of referenced type
+ if (QT->isReferenceType())
+ QT = QT.getNonReferenceType();
+ // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
+ // enumeration
+ // Note: We get the cxtype, not the cxcursor, so we can't call
+ // FieldDecl->isBitField()
+ // [expr.sizeof] p3: pointer ok, function not ok.
+ // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
+ if (QT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (QT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ if (!QT->isConstantSizeType())
+ return CXTypeLayoutError_NotConstantSize;
+ if (const auto *Deduced = dyn_cast<DeducedType>(QT))
+ if (Deduced->getDeducedType().isNull())
+ return CXTypeLayoutError_Undeduced;
+ // [gcc extension] lib/AST/ExprConstant.cpp:1372
+ // HandleSizeof : {voidtype,functype} == 1
+ // not handled by ASTContext.cpp:1313 getTypeInfoImpl
+ if (QT->isVoidType() || QT->isFunctionType())
+ return 1;
+ return Ctx.getTypeSizeInChars(QT).getQuantity();
+}
+
+static bool isTypeIncompleteForLayout(QualType QT) {
+ return QT->isIncompleteType() && !QT->isIncompleteArrayType();
+}
+
+static long long visitRecordForValidation(const RecordDecl *RD) {
+ for (const auto *I : RD->fields()){
+ QualType FQT = I->getType();
+ if (isTypeIncompleteForLayout(FQT))
+ return CXTypeLayoutError_Incomplete;
+ if (FQT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ // recurse
+ if (const RecordType *ChildType = I->getType()->getAs<RecordType>()) {
+ if (const RecordDecl *Child = ChildType->getDecl()) {
+ long long ret = visitRecordForValidation(Child);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ // else try next field
+ }
+ return 0;
+}
+
+static long long validateFieldParentType(CXCursor PC, CXType PT){
+ if (clang_isInvalid(PC.kind))
+ return CXTypeLayoutError_Invalid;
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ // validate parent declaration
+ if (!RD || RD->isInvalidDecl())
+ return CXTypeLayoutError_Invalid;
+ RD = RD->getDefinition();
+ if (!RD)
+ return CXTypeLayoutError_Incomplete;
+ if (RD->isInvalidDecl())
+ return CXTypeLayoutError_Invalid;
+ // validate parent type
+ QualType RT = GetQualType(PT);
+ if (RT->isIncompleteType())
+ return CXTypeLayoutError_Incomplete;
+ if (RT->isDependentType())
+ return CXTypeLayoutError_Dependent;
+ // We recurse into all record fields to detect incomplete and dependent types.
+ long long Error = visitRecordForValidation(RD);
+ if (Error < 0)
+ return Error;
+ return 0;
+}
+
+long long clang_Type_getOffsetOf(CXType PT, const char *S) {
+ // check that PT is not incomplete/dependent
+ CXCursor PC = clang_getTypeDeclaration(PT);
+ long long Error = validateFieldParentType(PC,PT);
+ if (Error < 0)
+ return Error;
+ if (!S)
+ return CXTypeLayoutError_InvalidFieldName;
+ // lookup field
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();
+ IdentifierInfo *II = &Ctx.Idents.get(S);
+ DeclarationName FieldName(II);
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ // verified in validateFieldParentType
+ RD = RD->getDefinition();
+ RecordDecl::lookup_result Res = RD->lookup(FieldName);
+ // If a field of the parent record is incomplete, lookup will fail.
+ // and we would return InvalidFieldName instead of Incomplete.
+ // But this erroneous results does protects again a hidden assertion failure
+ // in the RecordLayoutBuilder
+ if (!Res.isSingleResult())
+ return CXTypeLayoutError_InvalidFieldName;
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(Res.front()))
+ return Ctx.getFieldOffset(FD);
+ if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Res.front()))
+ return Ctx.getFieldOffset(IFD);
+ // we don't want any other Decl Type.
+ return CXTypeLayoutError_InvalidFieldName;
+}
+
+CXType clang_Type_getModifiedType(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ if (auto *ATT = T->getAs<AttributedType>())
+ return MakeCXType(ATT->getModifiedType(), GetTU(CT));
+
+ return MakeCXType(QualType(), GetTU(CT));
+}
+
+long long clang_Cursor_getOffsetOfField(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ // we need to validate the parent type
+ CXCursor PC = clang_getCursorSemanticParent(C);
+ CXType PT = clang_getCursorType(PC);
+ long long Error = validateFieldParentType(PC,PT);
+ if (Error < 0)
+ return Error;
+ // proceed with the offset calculation
+ const Decl *D = cxcursor::getCursorDecl(C);
+ ASTContext &Ctx = cxcursor::getCursorContext(C);
+ if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D))
+ return Ctx.getFieldOffset(FD);
+ if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(D))
+ return Ctx.getFieldOffset(IFD);
+ }
+ return -1;
+}
+
+enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {
+ QualType QT = GetQualType(T);
+ if (QT.isNull())
+ return CXRefQualifier_None;
+ const FunctionProtoType *FD = QT->getAs<FunctionProtoType>();
+ if (!FD)
+ return CXRefQualifier_None;
+ switch (FD->getRefQualifier()) {
+ case RQ_None:
+ return CXRefQualifier_None;
+ case RQ_LValue:
+ return CXRefQualifier_LValue;
+ case RQ_RValue:
+ return CXRefQualifier_RValue;
+ }
+ return CXRefQualifier_None;
+}
+
+unsigned clang_Cursor_isBitField(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(cxcursor::getCursorDecl(C));
+ if (!FD)
+ return 0;
+ return FD->isBitField();
+}
+
+CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return cxstring::createEmpty();
+
+ const Decl *D = cxcursor::getCursorDecl(C);
+ ASTContext &Ctx = cxcursor::getCursorContext(C);
+ std::string encoding;
+
+ if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+ encoding = Ctx.getObjCEncodingForMethodDecl(OMD);
+ } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
+ encoding = Ctx.getObjCEncodingForPropertyDecl(OPD, nullptr);
+ else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ encoding = Ctx.getObjCEncodingForFunctionDecl(FD);
+ else {
+ QualType Ty;
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
+ Ty = Ctx.getTypeDeclType(TD);
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ Ty = VD->getType();
+ else return cxstring::createRef("?");
+ Ctx.getObjCEncodingForType(Ty, encoding);
+ }
+
+ return cxstring::createDup(encoding);
+}
+
+static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> TA) {
+ unsigned size = TA.size();
+ for (const auto &Arg : TA)
+ if (Arg.getKind() == TemplateArgument::Pack)
+ size += Arg.pack_size() - 1;
+ return size;
+}
+
+int clang_Type_getNumTemplateArguments(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return -1;
+
+ auto TA = GetTemplateArguments(T);
+ if (!TA)
+ return -1;
+
+ return GetTemplateArgumentArraySize(TA.getValue());
+}
+
+CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ auto TA = GetTemplateArguments(T);
+ if (!TA)
+ return MakeCXType(QualType(), GetTU(CT));
+
+ Optional<QualType> QT = FindTemplateArgumentTypeAt(TA.getValue(), index);
+ return MakeCXType(QT.getValueOr(QualType()), GetTU(CT));
+}
+
+CXType clang_Type_getObjCObjectBaseType(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return MakeCXType(QualType(), GetTU(CT));
+
+ return MakeCXType(OT->getBaseType(), GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return 0;
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return 0;
+
+ return OT->getNumProtocols();
+}
+
+CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ const ObjCProtocolDecl *PD = OT->getProtocol(i);
+ if (!PD)
+ return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+ return cxcursor::MakeCXCursor(PD, GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCTypeArgs(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return 0;
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return 0;
+
+ return OT->getTypeArgs().size();
+}
+
+CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+ if (!OT)
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const ArrayRef<QualType> TA = OT->getTypeArgs();
+ if ((size_t)i >= TA.size())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ return MakeCXType(TA[i], GetTU(CT));
+}
+
+unsigned clang_Type_visitFields(CXType PT,
+ CXFieldVisitor visitor,
+ CXClientData client_data){
+ CXCursor PC = clang_getTypeDeclaration(PT);
+ if (clang_isInvalid(PC.kind))
+ return false;
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ if (!RD || RD->isInvalidDecl())
+ return false;
+ RD = RD->getDefinition();
+ if (!RD || RD->isInvalidDecl())
+ return false;
+
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I){
+ const FieldDecl *FD = dyn_cast_or_null<FieldDecl>((*I));
+ // Callback to the client.
+ switch (visitor(cxcursor::MakeCXCursor(FD, GetTU(PT)), client_data)){
+ case CXVisit_Break:
+ return true;
+ case CXVisit_Continue:
+ break;
+ }
+ }
+ return true;
+}
+
+unsigned clang_Cursor_isAnonymous(CXCursor C){
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(D)) {
+ return ND->isAnonymousNamespace();
+ } else if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(D)) {
+ return TD->getTypedefNameForAnonDecl() == nullptr &&
+ TD->getIdentifier() == nullptr;
+ }
+
+ return 0;
+}
+
+unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C){
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(D))
+ return FD->isAnonymousStructOrUnion();
+ return 0;
+}
+
+unsigned clang_Cursor_isInlineNamespace(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const Decl *D = cxcursor::getCursorDecl(C);
+ const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(D);
+ return ND ? ND->isInline() : 0;
+}
+
+CXType clang_Type_getNamedType(CXType CT){
+ QualType T = GetQualType(CT);
+ const Type *TP = T.getTypePtrOrNull();
+
+ if (TP && TP->getTypeClass() == Type::Elaborated)
+ return MakeCXType(cast<ElaboratedType>(TP)->getNamedType(), GetTU(CT));
+
+ return MakeCXType(QualType(), GetTU(CT));
+}
+
+unsigned clang_Type_isTransparentTagTypedef(CXType TT){
+ QualType T = GetQualType(TT);
+ if (auto *TT = dyn_cast_or_null<TypedefType>(T.getTypePtrOrNull())) {
+ if (auto *D = TT->getDecl())
+ return D->isTransparentTag();
+ }
+ return false;
+}
+
+enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) {
+ QualType T = GetQualType(CT);
+ if (T.isNull())
+ return CXTypeNullability_Invalid;
+
+ ASTContext &Ctx = cxtu::getASTUnit(GetTU(CT))->getASTContext();
+ if (auto nullability = T->getNullability(Ctx)) {
+ switch (*nullability) {
+ case NullabilityKind::NonNull:
+ return CXTypeNullability_NonNull;
+ case NullabilityKind::Nullable:
+ return CXTypeNullability_Nullable;
+ case NullabilityKind::NullableResult:
+ return CXTypeNullability_NullableResult;
+ case NullabilityKind::Unspecified:
+ return CXTypeNullability_Unspecified;
+ }
+ }
+ return CXTypeNullability_Invalid;
+}
+
+CXType clang_Type_getValueType(CXType CT) {
+ QualType T = GetQualType(CT);
+
+ if (T.isNull() || !T->isAtomicType())
+ return MakeCXType(QualType(), GetTU(CT));
+
+ const auto *AT = T->castAs<AtomicType>();
+ return MakeCXType(AT->getValueType(), GetTU(CT));
+}
diff --git a/contrib/libs/clang14/tools/libclang/CXType.h b/contrib/libs/clang14/tools/libclang/CXType.h
new file mode 100644
index 0000000000..ffe70a9b1c
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CXType.h
@@ -0,0 +1,25 @@
+//===- CXTypes.h - Routines for manipulating CXTypes ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXTYPE_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CXTYPE_H
+
+#include "clang-c/Index.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace cxtype {
+
+CXType MakeCXType(QualType T, CXTranslationUnit TU);
+
+}} // end namespace clang::cxtype
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/CursorVisitor.h b/contrib/libs/clang14/tools/libclang/CursorVisitor.h
new file mode 100644
index 0000000000..364d9fdebd
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/CursorVisitor.h
@@ -0,0 +1,278 @@
+//===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
+
+#include "CXCursor.h"
+#include "CXTranslationUnit.h"
+#include "Index_Internal.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeLocVisitor.h"
+
+namespace clang {
+class PreprocessingRecord;
+class ASTUnit;
+
+namespace cxcursor {
+
+class VisitorJob {
+public:
+ enum Kind {
+ DeclVisitKind,
+ StmtVisitKind,
+ MemberExprPartsKind,
+ TypeLocVisitKind,
+ OverloadExprPartsKind,
+ DeclRefExprPartsKind,
+ LabelRefVisitKind,
+ ExplicitTemplateArgsVisitKind,
+ NestedNameSpecifierLocVisitKind,
+ DeclarationNameInfoVisitKind,
+ MemberRefVisitKind,
+ SizeOfPackExprPartsKind,
+ LambdaExprPartsKind,
+ PostChildrenVisitKind
+ };
+
+protected:
+ const void *data[3];
+ CXCursor parent;
+ Kind K;
+ VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
+ const void *d3 = nullptr)
+ : parent(C), K(k) {
+ data[0] = d1;
+ data[1] = d2;
+ data[2] = d3;
+ }
+
+public:
+ Kind getKind() const { return K; }
+ const CXCursor &getParent() const { return parent; }
+};
+
+typedef SmallVector<VisitorJob, 10> VisitorWorkList;
+
+// Cursor visitor.
+class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
+ public TypeLocVisitor<CursorVisitor, bool> {
+public:
+ /// Callback called after child nodes of a cursor have been visited.
+ /// Return true to break visitation or false to continue.
+ typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
+ CXClientData client_data);
+
+private:
+ /// The translation unit we are traversing.
+ CXTranslationUnit TU;
+ ASTUnit *AU;
+
+ /// The parent cursor whose children we are traversing.
+ CXCursor Parent;
+
+ /// The declaration that serves at the parent of any statement or
+ /// expression nodes.
+ const Decl *StmtParent;
+
+ /// The visitor function.
+ CXCursorVisitor Visitor;
+
+ PostChildrenVisitorTy PostChildrenVisitor;
+
+ /// The opaque client data, to be passed along to the visitor.
+ CXClientData ClientData;
+
+ /// Whether we should visit the preprocessing record entries last,
+ /// after visiting other declarations.
+ bool VisitPreprocessorLast;
+
+ /// Whether we should visit declarations or preprocessing record
+ /// entries that are #included inside the \arg RegionOfInterest.
+ bool VisitIncludedEntities;
+
+ /// When valid, a source range to which the cursor should restrict
+ /// its search.
+ SourceRange RegionOfInterest;
+
+ /// Whether we should only visit declarations and not preprocessing
+ /// record entries.
+ bool VisitDeclsOnly;
+
+ // FIXME: Eventually remove. This part of a hack to support proper
+ // iteration over all Decls contained lexically within an ObjC container.
+ DeclContext::decl_iterator *DI_current;
+ DeclContext::decl_iterator DE_current;
+ SmallVectorImpl<Decl *>::iterator *FileDI_current;
+ SmallVectorImpl<Decl *>::iterator FileDE_current;
+
+ // Cache of pre-allocated worklists for data-recursion walk of Stmts.
+ SmallVector<VisitorWorkList *, 5> WorkListFreeList;
+ SmallVector<VisitorWorkList *, 5> WorkListCache;
+
+ using DeclVisitor<CursorVisitor, bool>::Visit;
+ using TypeLocVisitor<CursorVisitor, bool>::Visit;
+
+ /// Determine whether this particular source range comes before, comes
+ /// after, or overlaps the region of interest.
+ ///
+ /// \param R a half-open source range retrieved from the abstract syntax tree.
+ RangeComparisonResult CompareRegionOfInterest(SourceRange R);
+
+ bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
+
+ class SetParentRAII {
+ CXCursor &Parent;
+ const Decl *&StmtParent;
+ CXCursor OldParent;
+
+ public:
+ SetParentRAII(CXCursor &Parent, const Decl *&StmtParent, CXCursor NewParent)
+ : Parent(Parent), StmtParent(StmtParent), OldParent(Parent) {
+ Parent = NewParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+
+ ~SetParentRAII() {
+ Parent = OldParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+ };
+
+public:
+ CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
+ CXClientData ClientData, bool VisitPreprocessorLast,
+ bool VisitIncludedPreprocessingEntries = false,
+ SourceRange RegionOfInterest = SourceRange(),
+ bool VisitDeclsOnly = false,
+ PostChildrenVisitorTy PostChildrenVisitor = nullptr)
+ : TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor),
+ PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData),
+ VisitPreprocessorLast(VisitPreprocessorLast),
+ VisitIncludedEntities(VisitIncludedPreprocessingEntries),
+ RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly),
+ DI_current(nullptr), FileDI_current(nullptr) {
+ Parent.kind = CXCursor_NoDeclFound;
+ Parent.data[0] = nullptr;
+ Parent.data[1] = nullptr;
+ Parent.data[2] = nullptr;
+ StmtParent = nullptr;
+ }
+
+ ~CursorVisitor() {
+ // Free the pre-allocated worklists for data-recursion.
+ for (SmallVectorImpl<VisitorWorkList *>::iterator I = WorkListCache.begin(),
+ E = WorkListCache.end();
+ I != E; ++I) {
+ delete *I;
+ }
+ }
+
+ ASTUnit *getASTUnit() const { return AU; }
+ CXTranslationUnit getTU() const { return TU; }
+
+ bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
+
+ /// Visit declarations and preprocessed entities for the file region
+ /// designated by \see RegionOfInterest.
+ bool visitFileRegion();
+
+ bool visitPreprocessedEntitiesInRegion();
+
+ bool shouldVisitIncludedEntities() const { return VisitIncludedEntities; }
+
+ template <typename InputIterator>
+ bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
+ PreprocessingRecord &PPRec,
+ FileID FID = FileID());
+
+ bool VisitChildren(CXCursor Parent);
+
+ // Declaration visitors
+ bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
+ bool VisitTypeAliasDecl(TypeAliasDecl *D);
+ bool VisitAttributes(Decl *D);
+ bool VisitBlockDecl(BlockDecl *B);
+ bool VisitCXXRecordDecl(CXXRecordDecl *D);
+ Optional<bool> shouldVisitCursor(CXCursor C);
+ bool VisitDeclContext(DeclContext *DC);
+ bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ bool VisitTypedefDecl(TypedefDecl *D);
+ bool VisitTagDecl(TagDecl *D);
+ bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
+ bool VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ bool VisitEnumConstantDecl(EnumConstantDecl *D);
+ bool VisitDeclaratorDecl(DeclaratorDecl *DD);
+ bool VisitFunctionDecl(FunctionDecl *ND);
+ bool VisitFieldDecl(FieldDecl *D);
+ bool VisitVarDecl(VarDecl *);
+ bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ bool VisitClassTemplateDecl(ClassTemplateDecl *D);
+ bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
+ bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
+ bool VisitObjCContainerDecl(ObjCContainerDecl *D);
+ bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
+ bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
+ bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
+ bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
+ bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ bool VisitObjCImplDecl(ObjCImplDecl *D);
+ bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
+ bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
+ bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ bool VisitNamespaceDecl(NamespaceDecl *D);
+ bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ bool VisitUsingDecl(UsingDecl *D);
+ bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ bool VisitStaticAssertDecl(StaticAssertDecl *D);
+ bool VisitFriendDecl(FriendDecl *D);
+ bool VisitDecompositionDecl(DecompositionDecl *D);
+
+ // Name visitor
+ bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
+ bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
+ // Template visitors
+ bool VisitTemplateParameters(const TemplateParameterList *Params);
+ bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
+ bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
+
+ // Type visitors
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ bool VisitTagTypeLoc(TagTypeLoc TL);
+ bool VisitArrayTypeLoc(ArrayTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
+
+ // Data-recursive visitor functions.
+ bool IsInRegionOfInterest(CXCursor C);
+ bool RunVisitorWorkList(VisitorWorkList &WL);
+ void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
+ LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
+
+private:
+ Optional<bool> handleDeclForVisitation(const Decl *D);
+};
+
+} // namespace cxcursor
+} // namespace clang
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/FatalErrorHandler.cpp b/contrib/libs/clang14/tools/libclang/FatalErrorHandler.cpp
new file mode 100644
index 0000000000..506b047c1b
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/FatalErrorHandler.cpp
@@ -0,0 +1,32 @@
+/*===-- clang-c/FatalErrorHandler.cpp - Fatal Error Handling ------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#include "clang-c/FatalErrorHandler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static void aborting_fatal_error_handler(void *, const char *reason,
+ bool) {
+ // Write the result out to stderr avoiding errs() because raw_ostreams can
+ // call report_fatal_error.
+ fprintf(stderr, "LIBCLANG FATAL ERROR: %s\n", reason);
+ ::abort();
+}
+
+extern "C" {
+void clang_install_aborting_llvm_fatal_error_handler(void) {
+ llvm::remove_fatal_error_handler();
+ llvm::install_fatal_error_handler(aborting_fatal_error_handler, nullptr);
+}
+
+void clang_uninstall_llvm_fatal_error_handler(void) {
+ llvm::remove_fatal_error_handler();
+}
+}
diff --git a/contrib/libs/clang14/tools/libclang/Index_Internal.h b/contrib/libs/clang14/tools/libclang/Index_Internal.h
new file mode 100644
index 0000000000..d28438770e
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/Index_Internal.h
@@ -0,0 +1,54 @@
+//===- CXString.h - Routines for manipulating CXStrings -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXStrings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_LIBCLANG_INDEX_INTERNAL_H
+#define LLVM_CLANG_TOOLS_LIBCLANG_INDEX_INTERNAL_H
+
+#include "clang-c/Index.h"
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#if __has_feature(blocks)
+
+#define INVOKE_BLOCK2(block, arg1, arg2) block(arg1, arg2)
+
+#else
+// If we are compiled with a compiler that doesn't have native blocks support,
+// define and call the block manually.
+
+#define INVOKE_BLOCK2(block, arg1, arg2) block->invoke(block, arg1, arg2)
+
+typedef struct _CXCursorAndRangeVisitorBlock {
+ void *isa;
+ int flags;
+ int reserved;
+ enum CXVisitorResult (*invoke)(_CXCursorAndRangeVisitorBlock *,
+ CXCursor, CXSourceRange);
+} *CXCursorAndRangeVisitorBlock;
+
+#endif // !__has_feature(blocks)
+
+/// The result of comparing two source ranges.
+enum RangeComparisonResult {
+ /// Either the ranges overlap or one of the ranges is invalid.
+ RangeOverlap,
+
+ /// The first range ends before the second range starts.
+ RangeBefore,
+
+ /// The first range starts after the second range ends.
+ RangeAfter
+};
+
+#endif
diff --git a/contrib/libs/clang14/tools/libclang/Indexing.cpp b/contrib/libs/clang14/tools/libclang/Indexing.cpp
new file mode 100644
index 0000000000..0e83ec6ca7
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/Indexing.cpp
@@ -0,0 +1,997 @@
+//===- Indexing.cpp - Higher level API functions --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CLog.h"
+#include "CXCursor.h"
+#include "CXIndexDataConsumer.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PPConditionalDirectiveRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cstdio>
+#include <mutex>
+#include <utility>
+
+using namespace clang;
+using namespace clang::index;
+using namespace cxtu;
+using namespace cxindex;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// Skip Parsed Bodies
+//===----------------------------------------------------------------------===//
+
+/// A "region" in source code identified by the file/offset of the
+/// preprocessor conditional directive that it belongs to.
+/// Multiple, non-consecutive ranges can be parts of the same region.
+///
+/// As an example of different regions separated by preprocessor directives:
+///
+/// \code
+/// #1
+/// #ifdef BLAH
+/// #2
+/// #ifdef CAKE
+/// #3
+/// #endif
+/// #2
+/// #endif
+/// #1
+/// \endcode
+///
+/// There are 3 regions, with non-consecutive parts:
+/// #1 is identified as the beginning of the file
+/// #2 is identified as the location of "#ifdef BLAH"
+/// #3 is identified as the location of "#ifdef CAKE"
+///
+class PPRegion {
+ llvm::sys::fs::UniqueID UniqueID;
+ time_t ModTime;
+ unsigned Offset;
+public:
+ PPRegion() : UniqueID(0, 0), ModTime(), Offset() {}
+ PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime)
+ : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {}
+
+ const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
+ unsigned getOffset() const { return Offset; }
+ time_t getModTime() const { return ModTime; }
+
+ bool isInvalid() const { return *this == PPRegion(); }
+
+ friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) {
+ return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset &&
+ lhs.ModTime == rhs.ModTime;
+ }
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+ template <>
+ struct DenseMapInfo<PPRegion> {
+ static inline PPRegion getEmptyKey() {
+ return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0);
+ }
+ static inline PPRegion getTombstoneKey() {
+ return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0);
+ }
+
+ static unsigned getHashValue(const PPRegion &S) {
+ llvm::FoldingSetNodeID ID;
+ const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID();
+ ID.AddInteger(UniqueID.getFile());
+ ID.AddInteger(UniqueID.getDevice());
+ ID.AddInteger(S.getOffset());
+ ID.AddInteger(S.getModTime());
+ return ID.ComputeHash();
+ }
+
+ static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
+ return LHS == RHS;
+ }
+ };
+}
+
+namespace {
+
+/// Keeps track of function bodies that have already been parsed.
+///
+/// Is thread-safe.
+class ThreadSafeParsedRegions {
+ mutable std::mutex Mutex;
+ llvm::DenseSet<PPRegion> ParsedRegions;
+
+public:
+ ~ThreadSafeParsedRegions() = default;
+
+ llvm::DenseSet<PPRegion> getParsedRegions() const {
+ std::lock_guard<std::mutex> MG(Mutex);
+ return ParsedRegions;
+ }
+
+ void addParsedRegions(ArrayRef<PPRegion> Regions) {
+ std::lock_guard<std::mutex> MG(Mutex);
+ ParsedRegions.insert(Regions.begin(), Regions.end());
+ }
+};
+
+/// Provides information whether source locations have already been parsed in
+/// another FrontendAction.
+///
+/// Is NOT thread-safe.
+class ParsedSrcLocationsTracker {
+ ThreadSafeParsedRegions &ParsedRegionsStorage;
+ PPConditionalDirectiveRecord &PPRec;
+ Preprocessor &PP;
+
+ /// Snapshot of the shared state at the point when this instance was
+ /// constructed.
+ llvm::DenseSet<PPRegion> ParsedRegionsSnapshot;
+ /// Regions that were queried during this instance lifetime.
+ SmallVector<PPRegion, 32> NewParsedRegions;
+
+ /// Caching the last queried region.
+ PPRegion LastRegion;
+ bool LastIsParsed;
+
+public:
+ /// Creates snapshot of \p ParsedRegionsStorage.
+ ParsedSrcLocationsTracker(ThreadSafeParsedRegions &ParsedRegionsStorage,
+ PPConditionalDirectiveRecord &ppRec,
+ Preprocessor &pp)
+ : ParsedRegionsStorage(ParsedRegionsStorage), PPRec(ppRec), PP(pp),
+ ParsedRegionsSnapshot(ParsedRegionsStorage.getParsedRegions()) {}
+
+ /// \returns true iff \p Loc has already been parsed.
+ ///
+ /// Can provide false-negative in case the location was parsed after this
+ /// instance had been constructed.
+ bool hasAlredyBeenParsed(SourceLocation Loc, FileID FID,
+ const FileEntry *FE) {
+ assert(FE);
+ PPRegion region = getRegion(Loc, FID, FE);
+ if (region.isInvalid())
+ return false;
+
+ // Check common case, consecutive functions in the same region.
+ if (LastRegion == region)
+ return LastIsParsed;
+
+ LastRegion = region;
+ // Source locations can't be revisited during single TU parsing.
+ // That means if we hit the same region again, it's a different location in
+ // the same region and so the "is parsed" value from the snapshot is still
+ // correct.
+ LastIsParsed = ParsedRegionsSnapshot.count(region);
+ if (!LastIsParsed)
+ NewParsedRegions.emplace_back(std::move(region));
+ return LastIsParsed;
+ }
+
+ /// Updates ParsedRegionsStorage with newly parsed regions.
+ void syncWithStorage() {
+ ParsedRegionsStorage.addParsedRegions(NewParsedRegions);
+ }
+
+private:
+ PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
+ assert(FE);
+ auto Bail = [this, FE]() {
+ if (isParsedOnceInclude(FE)) {
+ const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
+ return PPRegion(ID, 0, FE->getModificationTime());
+ }
+ return PPRegion();
+ };
+
+ SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
+ assert(RegionLoc.isFileID());
+ if (RegionLoc.isInvalid())
+ return Bail();
+
+ FileID RegionFID;
+ unsigned RegionOffset;
+ std::tie(RegionFID, RegionOffset) =
+ PPRec.getSourceManager().getDecomposedLoc(RegionLoc);
+
+ if (RegionFID != FID)
+ return Bail();
+
+ const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
+ return PPRegion(ID, RegionOffset, FE->getModificationTime());
+ }
+
+ bool isParsedOnceInclude(const FileEntry *FE) {
+ return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE) ||
+ PP.getHeaderSearchInfo().hasFileBeenImported(FE);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// IndexPPCallbacks
+//===----------------------------------------------------------------------===//
+
+class IndexPPCallbacks : public PPCallbacks {
+ Preprocessor &PP;
+ CXIndexDataConsumer &DataConsumer;
+ bool IsMainFileEntered;
+
+public:
+ IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer)
+ : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { }
+
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType, FileID PrevFID) override {
+ if (IsMainFileEntered)
+ return;
+
+ SourceManager &SM = PP.getSourceManager();
+ SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
+
+ if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
+ IsMainFileEntered = true;
+ DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
+ }
+ }
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
+ bool isImport = (IncludeTok.is(tok::identifier) &&
+ IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
+ DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
+ Imported);
+ }
+
+ /// MacroDefined - This hook is called whenever a macro definition is seen.
+ void MacroDefined(const Token &Id, const MacroDirective *MD) override {}
+
+ /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ /// MI is released immediately following this callback.
+ void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD,
+ const MacroDirective *UD) override {}
+
+ /// MacroExpands - This is called by when a macro invocation is found.
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {}
+
+ /// SourceRangeSkipped - This hook is called when a source range is skipped.
+ /// \param Range The SourceRange that was skipped. The range begins at the
+ /// #if/#else directive and ends after the #endif/#else directive.
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override {
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// IndexingConsumer
+//===----------------------------------------------------------------------===//
+
+class IndexingConsumer : public ASTConsumer {
+ CXIndexDataConsumer &DataConsumer;
+
+public:
+ IndexingConsumer(CXIndexDataConsumer &dataConsumer,
+ ParsedSrcLocationsTracker *parsedLocsTracker)
+ : DataConsumer(dataConsumer) {}
+
+ void Initialize(ASTContext &Context) override {
+ DataConsumer.setASTContext(Context);
+ DataConsumer.startedTranslationUnit();
+ }
+
+ bool HandleTopLevelDecl(DeclGroupRef DG) override {
+ return !DataConsumer.shouldAbort();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// CaptureDiagnosticConsumer
+//===----------------------------------------------------------------------===//
+
+class CaptureDiagnosticConsumer : public DiagnosticConsumer {
+ SmallVector<StoredDiagnostic, 4> Errors;
+public:
+
+ void HandleDiagnostic(DiagnosticsEngine::Level level,
+ const Diagnostic &Info) override {
+ if (level >= DiagnosticsEngine::Error)
+ Errors.push_back(StoredDiagnostic(level, Info));
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// IndexingFrontendAction
+//===----------------------------------------------------------------------===//
+
+class IndexingFrontendAction : public ASTFrontendAction {
+ std::shared_ptr<CXIndexDataConsumer> DataConsumer;
+ IndexingOptions Opts;
+
+ ThreadSafeParsedRegions *SKData;
+ std::unique_ptr<ParsedSrcLocationsTracker> ParsedLocsTracker;
+
+public:
+ IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
+ const IndexingOptions &Opts,
+ ThreadSafeParsedRegions *skData)
+ : DataConsumer(std::move(dataConsumer)), Opts(Opts), SKData(skData) {}
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+
+ if (!PPOpts.ImplicitPCHInclude.empty()) {
+ auto File = CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude);
+ if (File)
+ DataConsumer->importedPCH(*File);
+ }
+
+ DataConsumer->setASTContext(CI.getASTContext());
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.addPPCallbacks(std::make_unique<IndexPPCallbacks>(PP, *DataConsumer));
+ DataConsumer->setPreprocessor(CI.getPreprocessorPtr());
+
+ if (SKData) {
+ auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
+ ParsedLocsTracker =
+ std::make_unique<ParsedSrcLocationsTracker>(*SKData, *PPRec, PP);
+ }
+
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(std::make_unique<IndexingConsumer>(
+ *DataConsumer, ParsedLocsTracker.get()));
+ Consumers.push_back(createIndexingASTConsumer(
+ DataConsumer, Opts, CI.getPreprocessorPtr(),
+ [this](const Decl *D) { return this->shouldSkipFunctionBody(D); }));
+ return std::make_unique<MultiplexConsumer>(std::move(Consumers));
+ }
+
+ bool shouldSkipFunctionBody(const Decl *D) {
+ if (!ParsedLocsTracker) {
+ // Always skip bodies.
+ return true;
+ }
+
+ const SourceManager &SM = D->getASTContext().getSourceManager();
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isMacroID())
+ return false;
+ if (SM.isInSystemHeader(Loc))
+ return true; // always skip bodies from system headers.
+
+ FileID FID;
+ unsigned Offset;
+ std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+ // Don't skip bodies from main files; this may be revisited.
+ if (SM.getMainFileID() == FID)
+ return false;
+ const FileEntry *FE = SM.getFileEntryForID(FID);
+ if (!FE)
+ return false;
+
+ return ParsedLocsTracker->hasAlredyBeenParsed(Loc, FID, FE);
+ }
+
+ TranslationUnitKind getTranslationUnitKind() override {
+ if (DataConsumer->shouldIndexImplicitTemplateInsts())
+ return TU_Complete;
+ else
+ return TU_Prefix;
+ }
+ bool hasCodeCompletionSupport() const override { return false; }
+
+ void EndSourceFileAction() override {
+ if (ParsedLocsTracker)
+ ParsedLocsTracker->syncWithStorage();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// clang_indexSourceFileUnit Implementation
+//===----------------------------------------------------------------------===//
+
+static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
+ IndexingOptions IdxOpts;
+ if (index_options & CXIndexOpt_IndexFunctionLocalSymbols)
+ IdxOpts.IndexFunctionLocals = true;
+ if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations)
+ IdxOpts.IndexImplicitInstantiation = true;
+ return IdxOpts;
+}
+
+struct IndexSessionData {
+ CXIndex CIdx;
+ std::unique_ptr<ThreadSafeParsedRegions> SkipBodyData =
+ std::make_unique<ThreadSafeParsedRegions>();
+
+ explicit IndexSessionData(CXIndex cIdx) : CIdx(cIdx) {}
+};
+
+} // anonymous namespace
+
+static CXErrorCode clang_indexSourceFile_Impl(
+ CXIndexAction cxIdxAction, CXClientData client_data,
+ IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU,
+ unsigned TU_options) {
+ if (out_TU)
+ *out_TU = nullptr;
+ bool requestedToGetTU = (out_TU != nullptr);
+
+ if (!cxIdxAction) {
+ return CXError_InvalidArguments;
+ }
+ if (!client_index_callbacks || index_callbacks_size == 0) {
+ return CXError_InvalidArguments;
+ }
+
+ IndexerCallbacks CB;
+ memset(&CB, 0, sizeof(CB));
+ unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
+ ? index_callbacks_size : sizeof(CB);
+ memcpy(&CB, client_index_callbacks, ClientCBSize);
+
+ IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction);
+ CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx);
+
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::All;
+ if (TU_options & CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles)
+ CaptureDiagnostics = CaptureDiagsKind::AllWithoutNonErrorsFromIncludes;
+ if (Logger::isLoggingEnabled())
+ CaptureDiagnostics = CaptureDiagsKind::None;
+
+ CaptureDiagnosticConsumer *CaptureDiag = nullptr;
+ if (CaptureDiagnostics != CaptureDiagsKind::None)
+ CaptureDiag = new CaptureDiagnosticConsumer();
+
+ // Configure the diagnostics.
+ IntrusiveRefCntPtr<DiagnosticsEngine>
+ Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
+ CaptureDiag,
+ /*ShouldOwnClient=*/true));
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ DiagCleanup(Diags.get());
+
+ std::unique_ptr<std::vector<const char *>> Args(
+ new std::vector<const char *>());
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
+ ArgsCleanup(Args.get());
+
+ Args->insert(Args->end(), command_line_args,
+ command_line_args + num_command_line_args);
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ // Put the source file after command_line_args otherwise if '-x' flag is
+ // present it will be unused.
+ if (source_filename)
+ Args->push_back(source_filename);
+
+ std::shared_ptr<CompilerInvocation> CInvok =
+ createInvocationFromCommandLine(*Args, Diags);
+
+ if (!CInvok)
+ return CXError_Failure;
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ std::shared_ptr<CompilerInvocation>,
+ llvm::CrashRecoveryContextDestructorCleanup<
+ std::shared_ptr<CompilerInvocation>>>
+ CInvokCleanup(&CInvok);
+
+ if (CInvok->getFrontendOpts().Inputs.empty())
+ return CXError_Failure;
+
+ typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner;
+ std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner);
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup(
+ BufOwner.get());
+
+ for (auto &UF : unsaved_files) {
+ std::unique_ptr<llvm::MemoryBuffer> MB =
+ llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
+ CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get());
+ BufOwner->push_back(std::move(MB));
+ }
+
+ // Since libclang is primarily used by batch tools dealing with
+ // (often very broken) source code, where spell-checking can have a
+ // significant negative impact on performance (particularly when
+ // precompiled headers are involved), we disable it.
+ CInvok->getLangOpts()->SpellChecking = false;
+
+ if (index_options & CXIndexOpt_SuppressWarnings)
+ CInvok->getDiagnosticOpts().IgnoreWarnings = true;
+
+ // Make sure to use the raw module format.
+ CInvok->getHeaderSearchOpts().ModuleFormat = std::string(
+ CXXIdx->getPCHContainerOperations()->getRawReader().getFormat());
+
+ auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics,
+ /*UserFilesAreVolatile=*/true);
+ if (!Unit)
+ return CXError_InvalidArguments;
+
+ auto *UPtr = Unit.get();
+ std::unique_ptr<CXTUOwner> CXTU(
+ new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit))));
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
+ CXTUCleanup(CXTU.get());
+
+ // Enable the skip-parsed-bodies optimization only for C++; this may be
+ // revisited.
+ bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) &&
+ CInvok->getLangOpts()->CPlusPlus;
+ if (SkipBodies)
+ CInvok->getFrontendOpts().SkipFunctionBodies = true;
+
+ auto DataConsumer =
+ std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options,
+ CXTU->getTU());
+ auto IndexAction = std::make_unique<IndexingFrontendAction>(
+ DataConsumer, getIndexingOptionsFromCXOptions(index_options),
+ SkipBodies ? IdxSession->SkipBodyData.get() : nullptr);
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction>
+ IndexActionCleanup(IndexAction.get());
+
+ bool Persistent = requestedToGetTU;
+ bool OnlyLocalDecls = false;
+ bool PrecompilePreamble = false;
+ bool CreatePreambleOnFirstParse = false;
+ bool CacheCodeCompletionResults = false;
+ PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
+ PPOpts.AllowPCHWithCompilerErrors = true;
+
+ if (requestedToGetTU) {
+ OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
+ PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
+ CreatePreambleOnFirstParse =
+ TU_options & CXTranslationUnit_CreatePreambleOnFirstParse;
+ // FIXME: Add a flag for modules.
+ CacheCodeCompletionResults
+ = TU_options & CXTranslationUnit_CacheCompletionResults;
+ }
+
+ if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ PPOpts.DetailedRecord = true;
+ }
+
+ if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
+ PPOpts.DetailedRecord = false;
+
+ // Unless the user specified that they want the preamble on the first parse
+ // set it up to be created on the first reparse. This makes the first parse
+ // faster, trading for a slower (first) reparse.
+ unsigned PrecompilePreambleAfterNParses =
+ !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
+ DiagnosticErrorTrap DiagTrap(*Diags);
+ bool Success = ASTUnit::LoadFromCompilerInvocationAction(
+ std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags,
+ IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(),
+ OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses,
+ CacheCodeCompletionResults, /*UserFilesAreVolatile=*/true);
+ if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
+ printDiagsToStderr(UPtr);
+
+ if (isASTReadError(UPtr))
+ return CXError_ASTReadError;
+
+ if (!Success)
+ return CXError_Failure;
+
+ if (out_TU)
+ *out_TU = CXTU->takeTU();
+
+ return CXError_Success;
+}
+
+//===----------------------------------------------------------------------===//
+// clang_indexTranslationUnit Implementation
+//===----------------------------------------------------------------------===//
+
+static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) {
+ Preprocessor &PP = Unit.getPreprocessor();
+ if (!PP.getPreprocessingRecord())
+ return;
+
+ // FIXME: Only deserialize inclusion directives.
+
+ bool isModuleFile = Unit.isModuleFile();
+ for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) {
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
+ SourceLocation Loc = ID->getSourceRange().getBegin();
+ // Modules have synthetic main files as input, give an invalid location
+ // if the location points to such a file.
+ if (isModuleFile && Unit.isInMainFileID(Loc))
+ Loc = SourceLocation();
+ IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
+ ID->getFile(),
+ ID->getKind() == InclusionDirective::Import,
+ !ID->wasInQuotes(), ID->importedModule());
+ }
+ }
+}
+
+static CXErrorCode clang_indexTranslationUnit_Impl(
+ CXIndexAction idxAction, CXClientData client_data,
+ IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, CXTranslationUnit TU) {
+ // Check arguments.
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return CXError_InvalidArguments;
+ }
+ if (!client_index_callbacks || index_callbacks_size == 0) {
+ return CXError_InvalidArguments;
+ }
+
+ CIndexer *CXXIdx = TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ IndexerCallbacks CB;
+ memset(&CB, 0, sizeof(CB));
+ unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
+ ? index_callbacks_size : sizeof(CB);
+ memcpy(&CB, client_index_callbacks, ClientCBSize);
+
+ CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU);
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ if (!Unit)
+ return CXError_Failure;
+
+ ASTUnit::ConcurrencyCheck Check(*Unit);
+
+ if (const FileEntry *PCHFile = Unit->getPCHFile())
+ DataConsumer.importedPCH(PCHFile);
+
+ FileManager &FileMgr = Unit->getFileManager();
+
+ if (Unit->getOriginalSourceFileName().empty())
+ DataConsumer.enteredMainFile(nullptr);
+ else if (auto MainFile = FileMgr.getFile(Unit->getOriginalSourceFileName()))
+ DataConsumer.enteredMainFile(*MainFile);
+ else
+ DataConsumer.enteredMainFile(nullptr);
+
+ DataConsumer.setASTContext(Unit->getASTContext());
+ DataConsumer.startedTranslationUnit();
+
+ indexPreprocessingRecord(*Unit, DataConsumer);
+ indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options));
+ DataConsumer.indexDiagnostics();
+
+ return CXError_Success;
+}
+
+//===----------------------------------------------------------------------===//
+// libclang public APIs.
+//===----------------------------------------------------------------------===//
+
+int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
+ return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
+}
+
+const CXIdxObjCContainerDeclInfo *
+clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+ if (const ObjCContainerDeclInfo *
+ ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
+ return &ContInfo->ObjCContDeclInfo;
+
+ return nullptr;
+}
+
+const CXIdxObjCInterfaceDeclInfo *
+clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+ if (const ObjCInterfaceDeclInfo *
+ InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
+ return &InterInfo->ObjCInterDeclInfo;
+
+ return nullptr;
+}
+
+const CXIdxObjCCategoryDeclInfo *
+clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+ if (const ObjCCategoryDeclInfo *
+ CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
+ return &CatInfo->ObjCCatDeclInfo;
+
+ return nullptr;
+}
+
+const CXIdxObjCProtocolRefListInfo *
+clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+
+ if (const ObjCInterfaceDeclInfo *
+ InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
+ return InterInfo->ObjCInterDeclInfo.protocols;
+
+ if (const ObjCProtocolDeclInfo *
+ ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
+ return &ProtInfo->ObjCProtoRefListInfo;
+
+ if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
+ return CatInfo->ObjCCatDeclInfo.protocols;
+
+ return nullptr;
+}
+
+const CXIdxObjCPropertyDeclInfo *
+clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+ if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
+ return &PropInfo->ObjCPropDeclInfo;
+
+ return nullptr;
+}
+
+const CXIdxIBOutletCollectionAttrInfo *
+clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
+ if (!AInfo)
+ return nullptr;
+
+ const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
+ if (const IBOutletCollectionInfo *
+ IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
+ return &IBInfo->IBCollInfo;
+
+ return nullptr;
+}
+
+const CXIdxCXXClassDeclInfo *
+clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
+ if (!DInfo)
+ return nullptr;
+
+ const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
+ if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
+ return &ClassInfo->CXXClassInfo;
+
+ return nullptr;
+}
+
+CXIdxClientContainer
+clang_index_getClientContainer(const CXIdxContainerInfo *info) {
+ if (!info)
+ return nullptr;
+ const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
+ return Container->IndexCtx->getClientContainerForDC(Container->DC);
+}
+
+void clang_index_setClientContainer(const CXIdxContainerInfo *info,
+ CXIdxClientContainer client) {
+ if (!info)
+ return;
+ const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
+ Container->IndexCtx->addContainerInMap(Container->DC, client);
+}
+
+CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
+ if (!info)
+ return nullptr;
+ const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
+ return Entity->IndexCtx->getClientEntity(Entity->Dcl);
+}
+
+void clang_index_setClientEntity(const CXIdxEntityInfo *info,
+ CXIdxClientEntity client) {
+ if (!info)
+ return;
+ const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
+ Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
+}
+
+CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
+ return new IndexSessionData(CIdx);
+}
+
+void clang_IndexAction_dispose(CXIndexAction idxAction) {
+ if (idxAction)
+ delete static_cast<IndexSessionData *>(idxAction);
+}
+
+int clang_indexSourceFile(CXIndexAction idxAction,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ CXTranslationUnit *out_TU,
+ unsigned TU_options) {
+ SmallVector<const char *, 4> Args;
+ Args.push_back("clang");
+ Args.append(command_line_args, command_line_args + num_command_line_args);
+ return clang_indexSourceFileFullArgv(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, source_filename, Args.data(), Args.size(), unsaved_files,
+ num_unsaved_files, out_TU, TU_options);
+}
+
+int clang_indexSourceFileFullArgv(
+ CXIndexAction idxAction, CXClientData client_data,
+ IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
+ unsigned index_options, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ CXTranslationUnit *out_TU, unsigned TU_options) {
+ LOG_FUNC_SECTION {
+ *Log << source_filename << ": ";
+ for (int i = 0; i != num_command_line_args; ++i)
+ *Log << command_line_args[i] << " ";
+ }
+
+ if (num_unsaved_files && !unsaved_files)
+ return CXError_InvalidArguments;
+
+ CXErrorCode result = CXError_Failure;
+ auto IndexSourceFileImpl = [=, &result]() {
+ result = clang_indexSourceFile_Impl(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, source_filename, command_line_args,
+ num_command_line_args,
+ llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU,
+ TU_options);
+ };
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, IndexSourceFileImpl)) {
+ fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
+ fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
+ fprintf(stderr, " 'command_line_args' : [");
+ for (int i = 0; i != num_command_line_args; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "'%s'", command_line_args[i]);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'unsaved_files' : [");
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
+ unsaved_files[i].Length);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'options' : %d,\n", TU_options);
+ fprintf(stderr, "}\n");
+
+ return 1;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
+ if (out_TU)
+ PrintLibclangResourceUsage(*out_TU);
+ }
+
+ return result;
+}
+
+int clang_indexTranslationUnit(CXIndexAction idxAction,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options,
+ CXTranslationUnit TU) {
+ LOG_FUNC_SECTION {
+ *Log << TU;
+ }
+
+ CXErrorCode result;
+ auto IndexTranslationUnitImpl = [=, &result]() {
+ result = clang_indexTranslationUnit_Impl(
+ idxAction, client_data, index_callbacks, index_callbacks_size,
+ index_options, TU);
+ };
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, IndexTranslationUnitImpl)) {
+ fprintf(stderr, "libclang: crash detected during indexing TU\n");
+
+ return 1;
+ }
+
+ return result;
+}
+
+void clang_indexLoc_getFileLocation(CXIdxLoc location,
+ CXIdxClientFile *indexFile,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ if (indexFile) *indexFile = nullptr;
+ if (file) *file = nullptr;
+ if (line) *line = 0;
+ if (column) *column = 0;
+ if (offset) *offset = 0;
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ return;
+
+ CXIndexDataConsumer &DataConsumer =
+ *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
+ DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset);
+}
+
+CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ return clang_getNullLocation();
+
+ CXIndexDataConsumer &DataConsumer =
+ *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]);
+ return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
+}
diff --git a/contrib/libs/clang14/tools/libclang/Rewrite.cpp b/contrib/libs/clang14/tools/libclang/Rewrite.cpp
new file mode 100644
index 0000000000..389232d97a
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/Rewrite.cpp
@@ -0,0 +1,63 @@
+//===- Rewrite.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-c/Rewrite.h"
+#include "CXSourceLocation.h"
+#include "CXTranslationUnit.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+
+CXRewriter clang_CXRewriter_create(CXTranslationUnit TU) {
+ if (clang::cxtu::isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return {};
+ }
+ clang::ASTUnit *AU = clang::cxtu::getASTUnit(TU);
+ assert(AU);
+ return reinterpret_cast<CXRewriter>(
+ new clang::Rewriter(AU->getSourceManager(), AU->getLangOpts()));
+}
+
+void clang_CXRewriter_insertTextBefore(CXRewriter Rew, CXSourceLocation Loc,
+ const char *Insert) {
+ assert(Rew);
+ clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+ R.InsertTextBefore(clang::cxloc::translateSourceLocation(Loc), Insert);
+}
+
+void clang_CXRewriter_replaceText(CXRewriter Rew, CXSourceRange ToBeReplaced,
+ const char *Replacement) {
+ assert(Rew);
+ clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+ R.ReplaceText(clang::cxloc::translateCXRangeToCharRange(ToBeReplaced),
+ Replacement);
+}
+
+void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved) {
+ assert(Rew);
+ clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+ R.RemoveText(clang::cxloc::translateCXRangeToCharRange(ToBeRemoved));
+}
+
+int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew) {
+ assert(Rew);
+ clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+ return R.overwriteChangedFiles();
+}
+
+void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew) {
+ assert(Rew);
+ clang::Rewriter &R = *reinterpret_cast<clang::Rewriter *>(Rew);
+ R.getEditBuffer(R.getSourceMgr().getMainFileID()).write(llvm::outs());
+}
+
+void clang_CXRewriter_dispose(CXRewriter Rew) {
+ if (Rew)
+ delete reinterpret_cast<clang::Rewriter *>(Rew);
+}
diff --git a/contrib/libs/clang14/tools/libclang/dynamic/ya.make b/contrib/libs/clang14/tools/libclang/dynamic/ya.make
new file mode 100644
index 0000000000..04a7fdf688
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/dynamic/ya.make
@@ -0,0 +1,3 @@
+# Generated by devtools/yamaker.
+
+DLL_FOR(contrib/libs/clang14/tools/libclang clang EXPORTS ../libclang-generic.exports)
diff --git a/contrib/libs/clang14/tools/libclang/libclang-generic.exports b/contrib/libs/clang14/tools/libclang/libclang-generic.exports
new file mode 100644
index 0000000000..639d13d21d
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/libclang-generic.exports
@@ -0,0 +1,395 @@
+clang_BlockCommandComment_getArgText
+clang_BlockCommandComment_getCommandName
+clang_BlockCommandComment_getNumArgs
+clang_BlockCommandComment_getParagraph
+clang_CXCursorSet_contains
+clang_CXCursorSet_insert
+clang_CXIndex_getGlobalOptions
+clang_CXIndex_setGlobalOptions
+clang_CXIndex_setInvocationEmissionPathOption
+clang_CXRewriter_create
+clang_CXRewriter_dispose
+clang_CXRewriter_insertTextBefore
+clang_CXRewriter_overwriteChangedFiles
+clang_CXRewriter_removeText
+clang_CXRewriter_replaceText
+clang_CXRewriter_writeMainFileToStdOut
+clang_CXXConstructor_isConvertingConstructor
+clang_CXXConstructor_isCopyConstructor
+clang_CXXConstructor_isDefaultConstructor
+clang_CXXConstructor_isMoveConstructor
+clang_CXXField_isMutable
+clang_CXXMethod_isConst
+clang_CXXMethod_isDefaulted
+clang_CXXMethod_isPureVirtual
+clang_CXXMethod_isStatic
+clang_CXXMethod_isVirtual
+clang_CXXRecord_isAbstract
+clang_Comment_getChild
+clang_Comment_getKind
+clang_Comment_getNumChildren
+clang_Comment_isWhitespace
+clang_CompilationDatabase_dispose
+clang_CompilationDatabase_fromDirectory
+clang_CompilationDatabase_getAllCompileCommands
+clang_CompilationDatabase_getCompileCommands
+clang_CompileCommand_getArg
+clang_CompileCommand_getDirectory
+clang_CompileCommand_getFilename
+clang_CompileCommand_getMappedSourceContent
+clang_CompileCommand_getMappedSourcePath
+clang_CompileCommand_getNumArgs
+clang_CompileCommand_getNumMappedSources
+clang_CompileCommands_dispose
+clang_CompileCommands_getCommand
+clang_CompileCommands_getSize
+clang_Cursor_Evaluate
+clang_Cursor_getArgument
+clang_Cursor_getBriefCommentText
+clang_Cursor_getCXXManglings
+clang_Cursor_getCommentRange
+clang_Cursor_getMangling
+clang_Cursor_getModule
+clang_Cursor_getNumArguments
+clang_Cursor_getNumTemplateArguments
+clang_Cursor_getObjCDeclQualifiers
+clang_Cursor_getObjCManglings
+clang_Cursor_getObjCPropertyAttributes
+clang_Cursor_getObjCPropertyGetterName
+clang_Cursor_getObjCPropertySetterName
+clang_Cursor_getObjCSelectorIndex
+clang_Cursor_getOffsetOfField
+clang_Cursor_getParsedComment
+clang_Cursor_getRawCommentText
+clang_Cursor_getReceiverType
+clang_Cursor_getSpellingNameRange
+clang_Cursor_getStorageClass
+clang_Cursor_getTemplateArgumentKind
+clang_Cursor_getTemplateArgumentType
+clang_Cursor_getTemplateArgumentUnsignedValue
+clang_Cursor_getTemplateArgumentValue
+clang_Cursor_getTranslationUnit
+clang_Cursor_getVarDeclInitializer
+clang_Cursor_hasAttrs
+clang_Cursor_hasVarDeclExternalStorage
+clang_Cursor_hasVarDeclGlobalStorage
+clang_Cursor_isAnonymous
+clang_Cursor_isAnonymousRecordDecl
+clang_Cursor_isBitField
+clang_Cursor_isDynamicCall
+clang_Cursor_isExternalSymbol
+clang_Cursor_isFunctionInlined
+clang_Cursor_isInlineNamespace
+clang_Cursor_isMacroBuiltin
+clang_Cursor_isMacroFunctionLike
+clang_Cursor_isNull
+clang_Cursor_isObjCOptional
+clang_Cursor_isVariadic
+clang_EnumDecl_isScoped
+clang_EvalResult_dispose
+clang_EvalResult_getAsDouble
+clang_EvalResult_getAsInt
+clang_EvalResult_getAsLongLong
+clang_EvalResult_getAsStr
+clang_EvalResult_getAsUnsigned
+clang_EvalResult_getKind
+clang_EvalResult_isUnsignedInt
+clang_File_isEqual
+clang_File_tryGetRealPathName
+clang_FullComment_getAsHTML
+clang_FullComment_getAsXML
+clang_HTMLStartTagComment_isSelfClosing
+clang_HTMLStartTag_getAttrName
+clang_HTMLStartTag_getAttrValue
+clang_HTMLStartTag_getNumAttrs
+clang_HTMLTagComment_getAsString
+clang_HTMLTagComment_getTagName
+clang_IndexAction_create
+clang_IndexAction_dispose
+clang_InlineCommandComment_getArgText
+clang_InlineCommandComment_getCommandName
+clang_InlineCommandComment_getNumArgs
+clang_InlineCommandComment_getRenderKind
+clang_InlineContentComment_hasTrailingNewline
+clang_Location_isFromMainFile
+clang_Location_isInSystemHeader
+clang_ModuleMapDescriptor_create
+clang_ModuleMapDescriptor_dispose
+clang_ModuleMapDescriptor_setFrameworkModuleName
+clang_ModuleMapDescriptor_setUmbrellaHeader
+clang_ModuleMapDescriptor_writeToBuffer
+clang_Module_getASTFile
+clang_Module_getFullName
+clang_Module_getName
+clang_Module_getNumTopLevelHeaders
+clang_Module_getParent
+clang_Module_getTopLevelHeader
+clang_Module_isSystem
+clang_ParamCommandComment_getDirection
+clang_ParamCommandComment_getParamIndex
+clang_ParamCommandComment_getParamName
+clang_ParamCommandComment_isDirectionExplicit
+clang_ParamCommandComment_isParamIndexValid
+clang_PrintingPolicy_dispose
+clang_PrintingPolicy_getProperty
+clang_PrintingPolicy_setProperty
+clang_Range_isNull
+clang_TParamCommandComment_getDepth
+clang_TParamCommandComment_getIndex
+clang_TParamCommandComment_getParamName
+clang_TParamCommandComment_isParamPositionValid
+clang_TargetInfo_dispose
+clang_TargetInfo_getPointerWidth
+clang_TargetInfo_getTriple
+clang_TextComment_getText
+clang_Type_getAlignOf
+clang_Type_getCXXRefQualifier
+clang_Type_getClassType
+clang_Type_getModifiedType
+clang_Type_getNamedType
+clang_Type_getNullability
+clang_Type_getNumObjCProtocolRefs
+clang_Type_getNumObjCTypeArgs
+clang_Type_getNumTemplateArguments
+clang_Type_getObjCEncoding
+clang_Type_getObjCObjectBaseType
+clang_Type_getObjCProtocolDecl
+clang_Type_getObjCTypeArg
+clang_Type_getOffsetOf
+clang_Type_getSizeOf
+clang_Type_getTemplateArgumentAsType
+clang_Type_getValueType
+clang_Type_isTransparentTagTypedef
+clang_Type_visitFields
+clang_VerbatimBlockLineComment_getText
+clang_VerbatimLineComment_getText
+clang_VirtualFileOverlay_addFileMapping
+clang_VirtualFileOverlay_create
+clang_VirtualFileOverlay_dispose
+clang_VirtualFileOverlay_setCaseSensitivity
+clang_VirtualFileOverlay_writeToBuffer
+clang_annotateTokens
+clang_codeCompleteAt
+clang_codeCompleteGetContainerKind
+clang_codeCompleteGetContainerUSR
+clang_codeCompleteGetContexts
+clang_codeCompleteGetDiagnostic
+clang_codeCompleteGetNumDiagnostics
+clang_codeCompleteGetObjCSelector
+clang_constructUSR_ObjCCategory
+clang_constructUSR_ObjCClass
+clang_constructUSR_ObjCIvar
+clang_constructUSR_ObjCMethod
+clang_constructUSR_ObjCProperty
+clang_constructUSR_ObjCProtocol
+clang_createCXCursorSet
+clang_createIndex
+clang_createTranslationUnit
+clang_createTranslationUnit2
+clang_createTranslationUnitFromSourceFile
+clang_defaultCodeCompleteOptions
+clang_defaultDiagnosticDisplayOptions
+clang_defaultEditingTranslationUnitOptions
+clang_defaultReparseOptions
+clang_defaultSaveOptions
+clang_disposeCXCursorSet
+clang_disposeCXPlatformAvailability
+clang_disposeCXTUResourceUsage
+clang_disposeCodeCompleteResults
+clang_disposeDiagnostic
+clang_disposeDiagnosticSet
+clang_disposeIndex
+clang_disposeOverriddenCursors
+clang_disposeSourceRangeList
+clang_disposeString
+clang_disposeStringSet
+clang_disposeTokens
+clang_disposeTranslationUnit
+clang_enableStackTraces
+clang_equalCursors
+clang_equalLocations
+clang_equalRanges
+clang_equalTypes
+clang_executeOnThread
+clang_findIncludesInFile
+clang_findIncludesInFileWithBlock
+clang_findReferencesInFile
+clang_findReferencesInFileWithBlock
+clang_formatDiagnostic
+clang_free
+clang_getAddressSpace
+clang_getAllSkippedRanges
+clang_getArgType
+clang_getArrayElementType
+clang_getArraySize
+clang_getBuildSessionTimestamp
+clang_getCString
+clang_getCXTUResourceUsage
+clang_getCXXAccessSpecifier
+clang_getCanonicalCursor
+clang_getCanonicalType
+clang_getChildDiagnostics
+clang_getClangVersion
+clang_getCompletionAnnotation
+clang_getCompletionAvailability
+clang_getCompletionBriefComment
+clang_getCompletionChunkCompletionString
+clang_getCompletionChunkKind
+clang_getCompletionChunkText
+clang_getCompletionFixIt
+clang_getCompletionNumAnnotations
+clang_getCompletionNumFixIts
+clang_getCompletionParent
+clang_getCompletionPriority
+clang_getCursor
+clang_getCursorAvailability
+clang_getCursorCompletionString
+clang_getCursorDefinition
+clang_getCursorDisplayName
+clang_getCursorExceptionSpecificationType
+clang_getCursorExtent
+clang_getCursorKind
+clang_getCursorKindSpelling
+clang_getCursorLanguage
+clang_getCursorLexicalParent
+clang_getCursorLinkage
+clang_getCursorLocation
+clang_getCursorPlatformAvailability
+clang_getCursorPrettyPrinted
+clang_getCursorPrintingPolicy
+clang_getCursorReferenceNameRange
+clang_getCursorReferenced
+clang_getCursorResultType
+clang_getCursorSemanticParent
+clang_getCursorSpelling
+clang_getCursorTLSKind
+clang_getCursorType
+clang_getCursorUSR
+clang_getCursorVisibility
+clang_getDeclObjCTypeEncoding
+clang_getDefinitionSpellingAndExtent
+clang_getDiagnostic
+clang_getDiagnosticCategory
+clang_getDiagnosticCategoryName
+clang_getDiagnosticCategoryText
+clang_getDiagnosticFixIt
+clang_getDiagnosticInSet
+clang_getDiagnosticLocation
+clang_getDiagnosticNumFixIts
+clang_getDiagnosticNumRanges
+clang_getDiagnosticOption
+clang_getDiagnosticRange
+clang_getDiagnosticSetFromTU
+clang_getDiagnosticSeverity
+clang_getDiagnosticSpelling
+clang_getElementType
+clang_getEnumConstantDeclUnsignedValue
+clang_getEnumConstantDeclValue
+clang_getEnumDeclIntegerType
+clang_getExceptionSpecificationType
+clang_getExpansionLocation
+clang_getFieldDeclBitWidth
+clang_getFile
+clang_getFileContents
+clang_getFileLocation
+clang_getFileName
+clang_getFileTime
+clang_getFileUniqueID
+clang_getFunctionTypeCallingConv
+clang_getIBOutletCollectionType
+clang_getIncludedFile
+clang_getInclusions
+clang_getInstantiationLocation
+clang_getLocation
+clang_getLocationForOffset
+clang_getModuleForFile
+clang_getNullCursor
+clang_getNullLocation
+clang_getNullRange
+clang_getNumArgTypes
+clang_getNumCompletionChunks
+clang_getNumDiagnostics
+clang_getNumDiagnosticsInSet
+clang_getNumElements
+clang_getNumOverloadedDecls
+clang_getOverloadedDecl
+clang_getOverriddenCursors
+clang_getPointeeType
+clang_getPresumedLocation
+clang_getRange
+clang_getRangeEnd
+clang_getRangeStart
+clang_getRemappings
+clang_getRemappingsFromFileList
+clang_getResultType
+clang_getSkippedRanges
+clang_getSpecializedCursorTemplate
+clang_getSpellingLocation
+clang_getTUResourceUsageName
+clang_getTemplateCursorKind
+clang_getToken
+clang_getTokenExtent
+clang_getTokenKind
+clang_getTokenLocation
+clang_getTokenSpelling
+clang_getTranslationUnitCursor
+clang_getTranslationUnitSpelling
+clang_getTranslationUnitTargetInfo
+clang_getTypeDeclaration
+clang_getTypeKindSpelling
+clang_getTypeSpelling
+clang_getTypedefDeclUnderlyingType
+clang_getTypedefName
+clang_hashCursor
+clang_indexLoc_getCXSourceLocation
+clang_indexLoc_getFileLocation
+clang_indexSourceFile
+clang_indexSourceFileFullArgv
+clang_indexTranslationUnit
+clang_index_getCXXClassDeclInfo
+clang_index_getClientContainer
+clang_index_getClientEntity
+clang_index_getIBOutletCollectionAttrInfo
+clang_index_getObjCCategoryDeclInfo
+clang_index_getObjCContainerDeclInfo
+clang_index_getObjCInterfaceDeclInfo
+clang_index_getObjCPropertyDeclInfo
+clang_index_getObjCProtocolRefListInfo
+clang_index_isEntityObjCContainerKind
+clang_index_setClientContainer
+clang_index_setClientEntity
+clang_install_aborting_llvm_fatal_error_handler
+clang_isAttribute
+clang_isConstQualifiedType
+clang_isCursorDefinition
+clang_isDeclaration
+clang_isExpression
+clang_isFileMultipleIncludeGuarded
+clang_isFunctionTypeVariadic
+clang_isInvalid
+clang_isInvalidDeclaration
+clang_isPODType
+clang_isPreprocessing
+clang_isReference
+clang_isRestrictQualifiedType
+clang_isStatement
+clang_isTranslationUnit
+clang_isUnexposed
+clang_isVirtualBase
+clang_isVolatileQualifiedType
+clang_loadDiagnostics
+clang_parseTranslationUnit
+clang_parseTranslationUnit2
+clang_parseTranslationUnit2FullArgv
+clang_remap_dispose
+clang_remap_getFilenames
+clang_remap_getNumFiles
+clang_reparseTranslationUnit
+clang_saveTranslationUnit
+clang_sortCodeCompletionResults
+clang_suspendTranslationUnit
+clang_toggleCrashRecovery
+clang_tokenize
+clang_uninstall_llvm_fatal_error_handler
+clang_visitChildren
+clang_visitChildrenWithBlock
diff --git a/contrib/libs/clang14/tools/libclang/ya.make b/contrib/libs/clang14/tools/libclang/ya.make
new file mode 100644
index 0000000000..3377a83c1d
--- /dev/null
+++ b/contrib/libs/clang14/tools/libclang/ya.make
@@ -0,0 +1,87 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(Apache-2.0 WITH LLVM-exception)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+PEERDIR(
+ contrib/libs/clang14
+ contrib/libs/clang14/include
+ contrib/libs/clang14/lib/ARCMigrate
+ contrib/libs/clang14/lib/AST
+ contrib/libs/clang14/lib/Basic
+ contrib/libs/clang14/lib/Driver
+ contrib/libs/clang14/lib/Frontend
+ contrib/libs/clang14/lib/Index
+ contrib/libs/clang14/lib/Lex
+ contrib/libs/clang14/lib/Rewrite
+ contrib/libs/clang14/lib/Sema
+ contrib/libs/clang14/lib/Serialization
+ contrib/libs/clang14/lib/Tooling
+ contrib/libs/llvm14
+ contrib/libs/llvm14/lib/Support
+ contrib/libs/llvm14/lib/Target/AArch64
+ contrib/libs/llvm14/lib/Target/AArch64/AsmParser
+ contrib/libs/llvm14/lib/Target/AArch64/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/AArch64/TargetInfo
+ contrib/libs/llvm14/lib/Target/ARM
+ contrib/libs/llvm14/lib/Target/ARM/AsmParser
+ contrib/libs/llvm14/lib/Target/ARM/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/ARM/TargetInfo
+ contrib/libs/llvm14/lib/Target/BPF
+ contrib/libs/llvm14/lib/Target/BPF/AsmParser
+ contrib/libs/llvm14/lib/Target/BPF/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/BPF/TargetInfo
+ contrib/libs/llvm14/lib/Target/NVPTX
+ contrib/libs/llvm14/lib/Target/NVPTX/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/NVPTX/TargetInfo
+ contrib/libs/llvm14/lib/Target/PowerPC
+ contrib/libs/llvm14/lib/Target/PowerPC/AsmParser
+ contrib/libs/llvm14/lib/Target/PowerPC/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/PowerPC/TargetInfo
+ contrib/libs/llvm14/lib/Target/X86
+ contrib/libs/llvm14/lib/Target/X86/AsmParser
+ contrib/libs/llvm14/lib/Target/X86/MCTargetDesc
+ contrib/libs/llvm14/lib/Target/X86/TargetInfo
+)
+
+ADDINCL(
+ contrib/libs/clang14/tools/libclang
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+CFLAGS(
+ -D_CINDEX_LIB_
+)
+
+SRCS(
+ ARCMigrate.cpp
+ BuildSystem.cpp
+ CIndex.cpp
+ CIndexCXX.cpp
+ CIndexCodeCompletion.cpp
+ CIndexDiagnostic.cpp
+ CIndexHigh.cpp
+ CIndexInclusionStack.cpp
+ CIndexUSRs.cpp
+ CIndexer.cpp
+ CXComment.cpp
+ CXCompilationDatabase.cpp
+ CXCursor.cpp
+ CXIndexDataConsumer.cpp
+ CXLoadedDiagnostic.cpp
+ CXSourceLocation.cpp
+ CXStoredDiagnostic.cpp
+ CXString.cpp
+ CXType.cpp
+ FatalErrorHandler.cpp
+ Indexing.cpp
+ Rewrite.cpp
+)
+
+END()