summaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Index
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Index')
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp195
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp1143
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexBody.cpp348
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp482
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp425
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp202
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp176
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp326
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexingContext.h121
-rw-r--r--contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h75
-rw-r--r--contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp931
11 files changed, 4424 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp
new file mode 100644
index 000000000000..92740b05703b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/CodegenNameGenerator.cpp
@@ -0,0 +1,195 @@
+//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Determines the name that the symbol will get for code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/CodegenNameGenerator.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/VTableBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::index;
+
+struct CodegenNameGenerator::Implementation {
+ std::unique_ptr<MangleContext> MC;
+ llvm::DataLayout DL;
+
+ Implementation(ASTContext &Ctx)
+ : MC(Ctx.createMangleContext()),
+ DL(Ctx.getTargetInfo().getDataLayout()) {}
+
+ bool writeName(const Decl *D, raw_ostream &OS) {
+ // First apply frontend mangling.
+ SmallString<128> FrontendBuf;
+ llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isDependentContext())
+ return true;
+ if (writeFuncOrVarName(FD, FrontendBufOS))
+ return true;
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ if (writeFuncOrVarName(VD, FrontendBufOS))
+ return true;
+ } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ MC->mangleObjCMethodNameWithoutSize(MD, OS);
+ return false;
+ } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+ writeObjCClassName(ID, FrontendBufOS);
+ } else {
+ return true;
+ }
+
+ // Now apply backend mangling.
+ llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
+ return false;
+ }
+
+ std::string getName(const Decl *D) {
+ std::string Name;
+ {
+ llvm::raw_string_ostream OS(Name);
+ writeName(D, OS);
+ }
+ return Name;
+ }
+
+ std::vector<std::string> getAllManglings(const Decl *D) {
+ if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
+ return {};
+
+ const NamedDecl *ND = cast<NamedDecl>(D);
+
+ ASTContext &Ctx = ND->getASTContext();
+ std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
+
+ std::vector<std::string> Manglings;
+
+ auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
+ auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCSSMethod=*/true);
+ auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
+ return CC == DefaultCC;
+ };
+
+ if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
+ Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
+
+ if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
+ if (!CD->getParent()->isAbstract())
+ Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
+
+ if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
+ if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
+ if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
+ Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
+ } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
+ Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
+ if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
+ Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
+ if (DD->isVirtual())
+ Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
+ }
+ } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
+ Manglings.emplace_back(getName(ND));
+ if (MD->isVirtual())
+ if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
+ for (const auto &T : *TIV)
+ Manglings.emplace_back(getMangledThunk(MD, T));
+ }
+
+ return Manglings;
+ }
+
+private:
+ bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
+ if (MC->shouldMangleDeclName(D)) {
+ if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
+ MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
+ else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
+ MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
+ else
+ MC->mangleName(D, OS);
+ return false;
+ } else {
+ IdentifierInfo *II = D->getIdentifier();
+ if (!II)
+ return true;
+ OS << II->getName();
+ return false;
+ }
+ }
+
+ void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
+ OS << getClassSymbolPrefix();
+ OS << D->getObjCRuntimeNameAsString();
+ }
+
+ static StringRef getClassSymbolPrefix() {
+ return "OBJC_CLASS_$_";
+ }
+
+ std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
+ std::string FrontendBuf;
+ llvm::raw_string_ostream FOS(FrontendBuf);
+
+ if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
+ MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
+ else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
+ MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
+
+ std::string BackendBuf;
+ llvm::raw_string_ostream BOS(BackendBuf);
+
+ llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
+
+ return BOS.str();
+ }
+
+ std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
+ std::string FrontendBuf;
+ llvm::raw_string_ostream FOS(FrontendBuf);
+
+ MC->mangleThunk(MD, T, FOS);
+
+ std::string BackendBuf;
+ llvm::raw_string_ostream BOS(BackendBuf);
+
+ llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
+
+ return BOS.str();
+ }
+};
+
+CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
+ : Impl(new Implementation(Ctx)) {
+}
+
+CodegenNameGenerator::~CodegenNameGenerator() {
+}
+
+bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
+ return Impl->writeName(D, OS);
+}
+
+std::string CodegenNameGenerator::getName(const Decl *D) {
+ return Impl->getName(D);
+}
+
+std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
+ return Impl->getAllManglings(D);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
new file mode 100644
index 000000000000..ee066cc6d985
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
@@ -0,0 +1,1143 @@
+//===--- CommentToXML.cpp - Convert comments to XML representation --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/CommentToXML.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/CommentVisitor.h"
+#include "clang/Format/Format.h"
+#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::comments;
+using namespace clang::index;
+
+namespace {
+
+/// This comparison will sort parameters with valid index by index, then vararg
+/// parameters, and invalid (unresolved) parameters last.
+class ParamCommandCommentCompareIndex {
+public:
+ bool operator()(const ParamCommandComment *LHS,
+ const ParamCommandComment *RHS) const {
+ unsigned LHSIndex = UINT_MAX;
+ unsigned RHSIndex = UINT_MAX;
+
+ if (LHS->isParamIndexValid()) {
+ if (LHS->isVarArgParam())
+ LHSIndex = UINT_MAX - 1;
+ else
+ LHSIndex = LHS->getParamIndex();
+ }
+ if (RHS->isParamIndexValid()) {
+ if (RHS->isVarArgParam())
+ RHSIndex = UINT_MAX - 1;
+ else
+ RHSIndex = RHS->getParamIndex();
+ }
+ return LHSIndex < RHSIndex;
+ }
+};
+
+/// This comparison will sort template parameters in the following order:
+/// \li real template parameters (depth = 1) in index order;
+/// \li all other names (depth > 1);
+/// \li unresolved names.
+class TParamCommandCommentComparePosition {
+public:
+ bool operator()(const TParamCommandComment *LHS,
+ const TParamCommandComment *RHS) const {
+ // Sort unresolved names last.
+ if (!LHS->isPositionValid())
+ return false;
+ if (!RHS->isPositionValid())
+ return true;
+
+ if (LHS->getDepth() > 1)
+ return false;
+ if (RHS->getDepth() > 1)
+ return true;
+
+ // Sort template parameters in index order.
+ if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
+ return LHS->getIndex(0) < RHS->getIndex(0);
+
+ // Leave all other names in source order.
+ return true;
+ }
+};
+
+/// Separate parts of a FullComment.
+struct FullCommentParts {
+ /// Take a full comment apart and initialize members accordingly.
+ FullCommentParts(const FullComment *C,
+ const CommandTraits &Traits);
+
+ const BlockContentComment *Brief;
+ const BlockContentComment *Headerfile;
+ const ParagraphComment *FirstParagraph;
+ SmallVector<const BlockCommandComment *, 4> Returns;
+ SmallVector<const ParamCommandComment *, 8> Params;
+ SmallVector<const TParamCommandComment *, 4> TParams;
+ llvm::TinyPtrVector<const BlockCommandComment *> Exceptions;
+ SmallVector<const BlockContentComment *, 8> MiscBlocks;
+};
+
+FullCommentParts::FullCommentParts(const FullComment *C,
+ const CommandTraits &Traits) :
+ Brief(nullptr), Headerfile(nullptr), FirstParagraph(nullptr) {
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ const Comment *Child = *I;
+ if (!Child)
+ continue;
+ switch (Child->getCommentKind()) {
+ case Comment::NoCommentKind:
+ continue;
+
+ case Comment::ParagraphCommentKind: {
+ const ParagraphComment *PC = cast<ParagraphComment>(Child);
+ if (PC->isWhitespace())
+ break;
+ if (!FirstParagraph)
+ FirstParagraph = PC;
+
+ MiscBlocks.push_back(PC);
+ break;
+ }
+
+ case Comment::BlockCommandCommentKind: {
+ const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
+ const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID());
+ if (!Brief && Info->IsBriefCommand) {
+ Brief = BCC;
+ break;
+ }
+ if (!Headerfile && Info->IsHeaderfileCommand) {
+ Headerfile = BCC;
+ break;
+ }
+ if (Info->IsReturnsCommand) {
+ Returns.push_back(BCC);
+ break;
+ }
+ if (Info->IsThrowsCommand) {
+ Exceptions.push_back(BCC);
+ break;
+ }
+ MiscBlocks.push_back(BCC);
+ break;
+ }
+
+ case Comment::ParamCommandCommentKind: {
+ const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
+ if (!PCC->hasParamName())
+ break;
+
+ if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
+ break;
+
+ Params.push_back(PCC);
+ break;
+ }
+
+ case Comment::TParamCommandCommentKind: {
+ const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
+ if (!TPCC->hasParamName())
+ break;
+
+ if (!TPCC->hasNonWhitespaceParagraph())
+ break;
+
+ TParams.push_back(TPCC);
+ break;
+ }
+
+ case Comment::VerbatimBlockCommentKind:
+ MiscBlocks.push_back(cast<BlockCommandComment>(Child));
+ break;
+
+ case Comment::VerbatimLineCommentKind: {
+ const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
+ const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID());
+ if (!Info->IsDeclarationCommand)
+ MiscBlocks.push_back(VLC);
+ break;
+ }
+
+ case Comment::TextCommentKind:
+ case Comment::InlineCommandCommentKind:
+ case Comment::HTMLStartTagCommentKind:
+ case Comment::HTMLEndTagCommentKind:
+ case Comment::VerbatimBlockLineCommentKind:
+ case Comment::FullCommentKind:
+ llvm_unreachable("AST node of this kind can't be a child of "
+ "a FullComment");
+ }
+ }
+
+ // Sort params in order they are declared in the function prototype.
+ // Unresolved parameters are put at the end of the list in the same order
+ // they were seen in the comment.
+ std::stable_sort(Params.begin(), Params.end(),
+ ParamCommandCommentCompareIndex());
+
+ std::stable_sort(TParams.begin(), TParams.end(),
+ TParamCommandCommentComparePosition());
+}
+
+void printHTMLStartTagComment(const HTMLStartTagComment *C,
+ llvm::raw_svector_ostream &Result) {
+ Result << "<" << C->getTagName();
+
+ if (C->getNumAttrs() != 0) {
+ for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
+ Result << " ";
+ const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
+ Result << Attr.Name;
+ if (!Attr.Value.empty())
+ Result << "=\"" << Attr.Value << "\"";
+ }
+ }
+
+ if (!C->isSelfClosing())
+ Result << ">";
+ else
+ Result << "/>";
+}
+
+class CommentASTToHTMLConverter :
+ public ConstCommentVisitor<CommentASTToHTMLConverter> {
+public:
+ /// \param Str accumulator for HTML.
+ CommentASTToHTMLConverter(const FullComment *FC,
+ SmallVectorImpl<char> &Str,
+ const CommandTraits &Traits) :
+ FC(FC), Result(Str), Traits(Traits)
+ { }
+
+ // Inline content.
+ void visitTextComment(const TextComment *C);
+ void visitInlineCommandComment(const InlineCommandComment *C);
+ void visitHTMLStartTagComment(const HTMLStartTagComment *C);
+ void visitHTMLEndTagComment(const HTMLEndTagComment *C);
+
+ // Block content.
+ void visitParagraphComment(const ParagraphComment *C);
+ void visitBlockCommandComment(const BlockCommandComment *C);
+ void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
+ void visitVerbatimBlockComment(const VerbatimBlockComment *C);
+ void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
+ void visitVerbatimLineComment(const VerbatimLineComment *C);
+
+ void visitFullComment(const FullComment *C);
+
+ // Helpers.
+
+ /// Convert a paragraph that is not a block by itself (an argument to some
+ /// command).
+ void visitNonStandaloneParagraphComment(const ParagraphComment *C);
+
+ void appendToResultWithHTMLEscaping(StringRef S);
+
+private:
+ const FullComment *FC;
+ /// Output stream for HTML.
+ llvm::raw_svector_ostream Result;
+
+ const CommandTraits &Traits;
+};
+} // end unnamed namespace
+
+void CommentASTToHTMLConverter::visitTextComment(const TextComment *C) {
+ appendToResultWithHTMLEscaping(C->getText());
+}
+
+void CommentASTToHTMLConverter::visitInlineCommandComment(
+ const InlineCommandComment *C) {
+ // Nothing to render if no arguments supplied.
+ if (C->getNumArgs() == 0)
+ return;
+
+ // Nothing to render if argument is empty.
+ StringRef Arg0 = C->getArgText(0);
+ if (Arg0.empty())
+ return;
+
+ switch (C->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
+ appendToResultWithHTMLEscaping(C->getArgText(i));
+ Result << " ";
+ }
+ return;
+
+ case InlineCommandComment::RenderBold:
+ assert(C->getNumArgs() == 1);
+ Result << "<b>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result << "</b>";
+ return;
+ case InlineCommandComment::RenderMonospaced:
+ assert(C->getNumArgs() == 1);
+ Result << "<tt>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result<< "</tt>";
+ return;
+ case InlineCommandComment::RenderEmphasized:
+ assert(C->getNumArgs() == 1);
+ Result << "<em>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result << "</em>";
+ return;
+ }
+}
+
+void CommentASTToHTMLConverter::visitHTMLStartTagComment(
+ const HTMLStartTagComment *C) {
+ printHTMLStartTagComment(C, Result);
+}
+
+void CommentASTToHTMLConverter::visitHTMLEndTagComment(
+ const HTMLEndTagComment *C) {
+ Result << "</" << C->getTagName() << ">";
+}
+
+void CommentASTToHTMLConverter::visitParagraphComment(
+ const ParagraphComment *C) {
+ if (C->isWhitespace())
+ return;
+
+ Result << "<p>";
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+ Result << "</p>";
+}
+
+void CommentASTToHTMLConverter::visitBlockCommandComment(
+ const BlockCommandComment *C) {
+ const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID());
+ if (Info->IsBriefCommand) {
+ Result << "<p class=\"para-brief\">";
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</p>";
+ return;
+ }
+ if (Info->IsReturnsCommand) {
+ Result << "<p class=\"para-returns\">"
+ "<span class=\"word-returns\">Returns</span> ";
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</p>";
+ return;
+ }
+ // We don't know anything about this command. Just render the paragraph.
+ visit(C->getParagraph());
+}
+
+void CommentASTToHTMLConverter::visitParamCommandComment(
+ const ParamCommandComment *C) {
+ if (C->isParamIndexValid()) {
+ if (C->isVarArgParam()) {
+ Result << "<dt class=\"param-name-index-vararg\">";
+ appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
+ } else {
+ Result << "<dt class=\"param-name-index-"
+ << C->getParamIndex()
+ << "\">";
+ appendToResultWithHTMLEscaping(C->getParamName(FC));
+ }
+ } else {
+ Result << "<dt class=\"param-name-index-invalid\">";
+ appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
+ }
+ Result << "</dt>";
+
+ if (C->isParamIndexValid()) {
+ if (C->isVarArgParam())
+ Result << "<dd class=\"param-descr-index-vararg\">";
+ else
+ Result << "<dd class=\"param-descr-index-"
+ << C->getParamIndex()
+ << "\">";
+ } else
+ Result << "<dd class=\"param-descr-index-invalid\">";
+
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</dd>";
+}
+
+void CommentASTToHTMLConverter::visitTParamCommandComment(
+ const TParamCommandComment *C) {
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dt class=\"tparam-name-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dt class=\"tparam-name-index-other\">";
+ appendToResultWithHTMLEscaping(C->getParamName(FC));
+ } else {
+ Result << "<dt class=\"tparam-name-index-invalid\">";
+ appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
+ }
+
+ Result << "</dt>";
+
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dd class=\"tparam-descr-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dd class=\"tparam-descr-index-other\">";
+ } else
+ Result << "<dd class=\"tparam-descr-index-invalid\">";
+
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</dd>";
+}
+
+void CommentASTToHTMLConverter::visitVerbatimBlockComment(
+ const VerbatimBlockComment *C) {
+ unsigned NumLines = C->getNumLines();
+ if (NumLines == 0)
+ return;
+
+ Result << "<pre>";
+ for (unsigned i = 0; i != NumLines; ++i) {
+ appendToResultWithHTMLEscaping(C->getText(i));
+ if (i + 1 != NumLines)
+ Result << '\n';
+ }
+ Result << "</pre>";
+}
+
+void CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
+ const VerbatimBlockLineComment *C) {
+ llvm_unreachable("should not see this AST node");
+}
+
+void CommentASTToHTMLConverter::visitVerbatimLineComment(
+ const VerbatimLineComment *C) {
+ Result << "<pre>";
+ appendToResultWithHTMLEscaping(C->getText());
+ Result << "</pre>";
+}
+
+void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
+ FullCommentParts Parts(C, Traits);
+
+ bool FirstParagraphIsBrief = false;
+ if (Parts.Headerfile)
+ visit(Parts.Headerfile);
+ if (Parts.Brief)
+ visit(Parts.Brief);
+ else if (Parts.FirstParagraph) {
+ Result << "<p class=\"para-brief\">";
+ visitNonStandaloneParagraphComment(Parts.FirstParagraph);
+ Result << "</p>";
+ FirstParagraphIsBrief = true;
+ }
+
+ for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
+ const Comment *C = Parts.MiscBlocks[i];
+ if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
+ continue;
+ visit(C);
+ }
+
+ if (Parts.TParams.size() != 0) {
+ Result << "<dl>";
+ for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
+ visit(Parts.TParams[i]);
+ Result << "</dl>";
+ }
+
+ if (Parts.Params.size() != 0) {
+ Result << "<dl>";
+ for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
+ visit(Parts.Params[i]);
+ Result << "</dl>";
+ }
+
+ if (Parts.Returns.size() != 0) {
+ Result << "<div class=\"result-discussion\">";
+ for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
+ visit(Parts.Returns[i]);
+ Result << "</div>";
+ }
+
+}
+
+void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
+ const ParagraphComment *C) {
+ if (!C)
+ return;
+
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+}
+
+void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ const char C = *I;
+ switch (C) {
+ case '&':
+ Result << "&amp;";
+ break;
+ case '<':
+ Result << "&lt;";
+ break;
+ case '>':
+ Result << "&gt;";
+ break;
+ case '"':
+ Result << "&quot;";
+ break;
+ case '\'':
+ Result << "&#39;";
+ break;
+ case '/':
+ Result << "&#47;";
+ break;
+ default:
+ Result << C;
+ break;
+ }
+ }
+}
+
+namespace {
+class CommentASTToXMLConverter :
+ public ConstCommentVisitor<CommentASTToXMLConverter> {
+public:
+ /// \param Str accumulator for XML.
+ CommentASTToXMLConverter(const FullComment *FC,
+ SmallVectorImpl<char> &Str,
+ const CommandTraits &Traits,
+ const SourceManager &SM) :
+ FC(FC), Result(Str), Traits(Traits), SM(SM) { }
+
+ // Inline content.
+ void visitTextComment(const TextComment *C);
+ void visitInlineCommandComment(const InlineCommandComment *C);
+ void visitHTMLStartTagComment(const HTMLStartTagComment *C);
+ void visitHTMLEndTagComment(const HTMLEndTagComment *C);
+
+ // Block content.
+ void visitParagraphComment(const ParagraphComment *C);
+
+ void appendParagraphCommentWithKind(const ParagraphComment *C,
+ StringRef Kind);
+
+ void visitBlockCommandComment(const BlockCommandComment *C);
+ void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
+ void visitVerbatimBlockComment(const VerbatimBlockComment *C);
+ void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
+ void visitVerbatimLineComment(const VerbatimLineComment *C);
+
+ void visitFullComment(const FullComment *C);
+
+ // Helpers.
+ void appendToResultWithXMLEscaping(StringRef S);
+ void appendToResultWithCDATAEscaping(StringRef S);
+
+ void formatTextOfDeclaration(const DeclInfo *DI,
+ SmallString<128> &Declaration);
+
+private:
+ const FullComment *FC;
+
+ /// Output stream for XML.
+ llvm::raw_svector_ostream Result;
+
+ const CommandTraits &Traits;
+ const SourceManager &SM;
+};
+
+void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
+ SmallVectorImpl<char> &Str) {
+ ASTContext &Context = ThisDecl->CurrentDecl->getASTContext();
+ const LangOptions &LangOpts = Context.getLangOpts();
+ llvm::raw_svector_ostream OS(Str);
+ PrintingPolicy PPolicy(LangOpts);
+ PPolicy.PolishForDeclaration = true;
+ PPolicy.TerseOutput = true;
+ ThisDecl->CurrentDecl->print(OS, PPolicy,
+ /*Indentation*/0, /*PrintInstantiation*/false);
+}
+
+void CommentASTToXMLConverter::formatTextOfDeclaration(
+ const DeclInfo *DI, SmallString<128> &Declaration) {
+ // Formatting API expects null terminated input string.
+ StringRef StringDecl(Declaration.c_str(), Declaration.size());
+
+ // Formatter specific code.
+ unsigned Offset = 0;
+ unsigned Length = Declaration.size();
+
+ bool IncompleteFormat = false;
+ tooling::Replacements Replaces =
+ reformat(format::getLLVMStyle(), StringDecl,
+ tooling::Range(Offset, Length), "xmldecl.xd", &IncompleteFormat);
+ auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces);
+ if (static_cast<bool>(FormattedStringDecl)) {
+ Declaration = *FormattedStringDecl;
+ }
+}
+
+} // end unnamed namespace
+
+void CommentASTToXMLConverter::visitTextComment(const TextComment *C) {
+ appendToResultWithXMLEscaping(C->getText());
+}
+
+void CommentASTToXMLConverter::visitInlineCommandComment(
+ const InlineCommandComment *C) {
+ // Nothing to render if no arguments supplied.
+ if (C->getNumArgs() == 0)
+ return;
+
+ // Nothing to render if argument is empty.
+ StringRef Arg0 = C->getArgText(0);
+ if (Arg0.empty())
+ return;
+
+ switch (C->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
+ appendToResultWithXMLEscaping(C->getArgText(i));
+ Result << " ";
+ }
+ return;
+ case InlineCommandComment::RenderBold:
+ assert(C->getNumArgs() == 1);
+ Result << "<bold>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</bold>";
+ return;
+ case InlineCommandComment::RenderMonospaced:
+ assert(C->getNumArgs() == 1);
+ Result << "<monospaced>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</monospaced>";
+ return;
+ case InlineCommandComment::RenderEmphasized:
+ assert(C->getNumArgs() == 1);
+ Result << "<emphasized>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</emphasized>";
+ return;
+ }
+}
+
+void CommentASTToXMLConverter::visitHTMLStartTagComment(
+ const HTMLStartTagComment *C) {
+ Result << "<rawHTML";
+ if (C->isMalformed())
+ Result << " isMalformed=\"1\"";
+ Result << ">";
+ {
+ SmallString<32> Tag;
+ {
+ llvm::raw_svector_ostream TagOS(Tag);
+ printHTMLStartTagComment(C, TagOS);
+ }
+ appendToResultWithCDATAEscaping(Tag);
+ }
+ Result << "</rawHTML>";
+}
+
+void
+CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
+ Result << "<rawHTML";
+ if (C->isMalformed())
+ Result << " isMalformed=\"1\"";
+ Result << ">&lt;/" << C->getTagName() << "&gt;</rawHTML>";
+}
+
+void
+CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
+ appendParagraphCommentWithKind(C, StringRef());
+}
+
+void CommentASTToXMLConverter::appendParagraphCommentWithKind(
+ const ParagraphComment *C,
+ StringRef ParagraphKind) {
+ if (C->isWhitespace())
+ return;
+
+ if (ParagraphKind.empty())
+ Result << "<Para>";
+ else
+ Result << "<Para kind=\"" << ParagraphKind << "\">";
+
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+ Result << "</Para>";
+}
+
+void CommentASTToXMLConverter::visitBlockCommandComment(
+ const BlockCommandComment *C) {
+ StringRef ParagraphKind;
+
+ switch (C->getCommandID()) {
+ case CommandTraits::KCI_attention:
+ case CommandTraits::KCI_author:
+ case CommandTraits::KCI_authors:
+ case CommandTraits::KCI_bug:
+ case CommandTraits::KCI_copyright:
+ case CommandTraits::KCI_date:
+ case CommandTraits::KCI_invariant:
+ case CommandTraits::KCI_note:
+ case CommandTraits::KCI_post:
+ case CommandTraits::KCI_pre:
+ case CommandTraits::KCI_remark:
+ case CommandTraits::KCI_remarks:
+ case CommandTraits::KCI_sa:
+ case CommandTraits::KCI_see:
+ case CommandTraits::KCI_since:
+ case CommandTraits::KCI_todo:
+ case CommandTraits::KCI_version:
+ case CommandTraits::KCI_warning:
+ ParagraphKind = C->getCommandName(Traits);
+ default:
+ break;
+ }
+
+ appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind);
+}
+
+void CommentASTToXMLConverter::visitParamCommandComment(
+ const ParamCommandComment *C) {
+ Result << "<Parameter><Name>";
+ appendToResultWithXMLEscaping(C->isParamIndexValid()
+ ? C->getParamName(FC)
+ : C->getParamNameAsWritten());
+ Result << "</Name>";
+
+ if (C->isParamIndexValid()) {
+ if (C->isVarArgParam())
+ Result << "<IsVarArg />";
+ else
+ Result << "<Index>" << C->getParamIndex() << "</Index>";
+ }
+
+ Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">";
+ switch (C->getDirection()) {
+ case ParamCommandComment::In:
+ Result << "in";
+ break;
+ case ParamCommandComment::Out:
+ Result << "out";
+ break;
+ case ParamCommandComment::InOut:
+ Result << "in,out";
+ break;
+ }
+ Result << "</Direction><Discussion>";
+ visit(C->getParagraph());
+ Result << "</Discussion></Parameter>";
+}
+
+void CommentASTToXMLConverter::visitTParamCommandComment(
+ const TParamCommandComment *C) {
+ Result << "<Parameter><Name>";
+ appendToResultWithXMLEscaping(C->isPositionValid() ? C->getParamName(FC)
+ : C->getParamNameAsWritten());
+ Result << "</Name>";
+
+ if (C->isPositionValid() && C->getDepth() == 1) {
+ Result << "<Index>" << C->getIndex(0) << "</Index>";
+ }
+
+ Result << "<Discussion>";
+ visit(C->getParagraph());
+ Result << "</Discussion></Parameter>";
+}
+
+void CommentASTToXMLConverter::visitVerbatimBlockComment(
+ const VerbatimBlockComment *C) {
+ unsigned NumLines = C->getNumLines();
+ if (NumLines == 0)
+ return;
+
+ switch (C->getCommandID()) {
+ case CommandTraits::KCI_code:
+ Result << "<Verbatim xml:space=\"preserve\" kind=\"code\">";
+ break;
+ default:
+ Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
+ break;
+ }
+ for (unsigned i = 0; i != NumLines; ++i) {
+ appendToResultWithXMLEscaping(C->getText(i));
+ if (i + 1 != NumLines)
+ Result << '\n';
+ }
+ Result << "</Verbatim>";
+}
+
+void CommentASTToXMLConverter::visitVerbatimBlockLineComment(
+ const VerbatimBlockLineComment *C) {
+ llvm_unreachable("should not see this AST node");
+}
+
+void CommentASTToXMLConverter::visitVerbatimLineComment(
+ const VerbatimLineComment *C) {
+ Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
+ appendToResultWithXMLEscaping(C->getText());
+ Result << "</Verbatim>";
+}
+
+void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
+ FullCommentParts Parts(C, Traits);
+
+ const DeclInfo *DI = C->getDeclInfo();
+ StringRef RootEndTag;
+ if (DI) {
+ switch (DI->getKind()) {
+ case DeclInfo::OtherKind:
+ RootEndTag = "</Other>";
+ Result << "<Other";
+ break;
+ case DeclInfo::FunctionKind:
+ RootEndTag = "</Function>";
+ Result << "<Function";
+ switch (DI->TemplateKind) {
+ case DeclInfo::NotTemplate:
+ break;
+ case DeclInfo::Template:
+ Result << " templateKind=\"template\"";
+ break;
+ case DeclInfo::TemplateSpecialization:
+ Result << " templateKind=\"specialization\"";
+ break;
+ case DeclInfo::TemplatePartialSpecialization:
+ llvm_unreachable("partial specializations of functions "
+ "are not allowed in C++");
+ }
+ if (DI->IsInstanceMethod)
+ Result << " isInstanceMethod=\"1\"";
+ if (DI->IsClassMethod)
+ Result << " isClassMethod=\"1\"";
+ break;
+ case DeclInfo::ClassKind:
+ RootEndTag = "</Class>";
+ Result << "<Class";
+ switch (DI->TemplateKind) {
+ case DeclInfo::NotTemplate:
+ break;
+ case DeclInfo::Template:
+ Result << " templateKind=\"template\"";
+ break;
+ case DeclInfo::TemplateSpecialization:
+ Result << " templateKind=\"specialization\"";
+ break;
+ case DeclInfo::TemplatePartialSpecialization:
+ Result << " templateKind=\"partialSpecialization\"";
+ break;
+ }
+ break;
+ case DeclInfo::VariableKind:
+ RootEndTag = "</Variable>";
+ Result << "<Variable";
+ break;
+ case DeclInfo::NamespaceKind:
+ RootEndTag = "</Namespace>";
+ Result << "<Namespace";
+ break;
+ case DeclInfo::TypedefKind:
+ RootEndTag = "</Typedef>";
+ Result << "<Typedef";
+ break;
+ case DeclInfo::EnumKind:
+ RootEndTag = "</Enum>";
+ Result << "<Enum";
+ break;
+ }
+
+ {
+ // Print line and column number.
+ SourceLocation Loc = DI->CurrentDecl->getLocation();
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (FID.isValid()) {
+ if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
+ Result << " file=\"";
+ appendToResultWithXMLEscaping(FE->getName());
+ Result << "\"";
+ }
+ Result << " line=\"" << SM.getLineNumber(FID, FileOffset)
+ << "\" column=\"" << SM.getColumnNumber(FID, FileOffset)
+ << "\"";
+ }
+ }
+
+ // Finish the root tag.
+ Result << ">";
+
+ bool FoundName = false;
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) {
+ if (DeclarationName DeclName = ND->getDeclName()) {
+ Result << "<Name>";
+ std::string Name = DeclName.getAsString();
+ appendToResultWithXMLEscaping(Name);
+ FoundName = true;
+ Result << "</Name>";
+ }
+ }
+ if (!FoundName)
+ Result << "<Name>&lt;anonymous&gt;</Name>";
+
+ {
+ // Print USR.
+ SmallString<128> USR;
+ generateUSRForDecl(DI->CommentDecl, USR);
+ if (!USR.empty()) {
+ Result << "<USR>";
+ appendToResultWithXMLEscaping(USR);
+ Result << "</USR>";
+ }
+ }
+ } else {
+ // No DeclInfo -- just emit some root tag and name tag.
+ RootEndTag = "</Other>";
+ Result << "<Other><Name>unknown</Name>";
+ }
+
+ if (Parts.Headerfile) {
+ Result << "<Headerfile>";
+ visit(Parts.Headerfile);
+ Result << "</Headerfile>";
+ }
+
+ {
+ // Pretty-print the declaration.
+ Result << "<Declaration>";
+ SmallString<128> Declaration;
+ getSourceTextOfDeclaration(DI, Declaration);
+ formatTextOfDeclaration(DI, Declaration);
+ appendToResultWithXMLEscaping(Declaration);
+ Result << "</Declaration>";
+ }
+
+ bool FirstParagraphIsBrief = false;
+ if (Parts.Brief) {
+ Result << "<Abstract>";
+ visit(Parts.Brief);
+ Result << "</Abstract>";
+ } else if (Parts.FirstParagraph) {
+ Result << "<Abstract>";
+ visit(Parts.FirstParagraph);
+ Result << "</Abstract>";
+ FirstParagraphIsBrief = true;
+ }
+
+ if (Parts.TParams.size() != 0) {
+ Result << "<TemplateParameters>";
+ for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
+ visit(Parts.TParams[i]);
+ Result << "</TemplateParameters>";
+ }
+
+ if (Parts.Params.size() != 0) {
+ Result << "<Parameters>";
+ for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
+ visit(Parts.Params[i]);
+ Result << "</Parameters>";
+ }
+
+ if (Parts.Exceptions.size() != 0) {
+ Result << "<Exceptions>";
+ for (unsigned i = 0, e = Parts.Exceptions.size(); i != e; ++i)
+ visit(Parts.Exceptions[i]);
+ Result << "</Exceptions>";
+ }
+
+ if (Parts.Returns.size() != 0) {
+ Result << "<ResultDiscussion>";
+ for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
+ visit(Parts.Returns[i]);
+ Result << "</ResultDiscussion>";
+ }
+
+ if (DI->CommentDecl->hasAttrs()) {
+ const AttrVec &Attrs = DI->CommentDecl->getAttrs();
+ for (unsigned i = 0, e = Attrs.size(); i != e; i++) {
+ const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]);
+ if (!AA) {
+ if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) {
+ if (DA->getMessage().empty())
+ Result << "<Deprecated/>";
+ else {
+ Result << "<Deprecated>";
+ appendToResultWithXMLEscaping(DA->getMessage());
+ Result << "</Deprecated>";
+ }
+ }
+ else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) {
+ if (UA->getMessage().empty())
+ Result << "<Unavailable/>";
+ else {
+ Result << "<Unavailable>";
+ appendToResultWithXMLEscaping(UA->getMessage());
+ Result << "</Unavailable>";
+ }
+ }
+ continue;
+ }
+
+ // 'availability' attribute.
+ Result << "<Availability";
+ StringRef Distribution;
+ if (AA->getPlatform()) {
+ Distribution = AvailabilityAttr::getPrettyPlatformName(
+ AA->getPlatform()->getName());
+ if (Distribution.empty())
+ Distribution = AA->getPlatform()->getName();
+ }
+ Result << " distribution=\"" << Distribution << "\">";
+ VersionTuple IntroducedInVersion = AA->getIntroduced();
+ if (!IntroducedInVersion.empty()) {
+ Result << "<IntroducedInVersion>"
+ << IntroducedInVersion.getAsString()
+ << "</IntroducedInVersion>";
+ }
+ VersionTuple DeprecatedInVersion = AA->getDeprecated();
+ if (!DeprecatedInVersion.empty()) {
+ Result << "<DeprecatedInVersion>"
+ << DeprecatedInVersion.getAsString()
+ << "</DeprecatedInVersion>";
+ }
+ VersionTuple RemovedAfterVersion = AA->getObsoleted();
+ if (!RemovedAfterVersion.empty()) {
+ Result << "<RemovedAfterVersion>"
+ << RemovedAfterVersion.getAsString()
+ << "</RemovedAfterVersion>";
+ }
+ StringRef DeprecationSummary = AA->getMessage();
+ if (!DeprecationSummary.empty()) {
+ Result << "<DeprecationSummary>";
+ appendToResultWithXMLEscaping(DeprecationSummary);
+ Result << "</DeprecationSummary>";
+ }
+ if (AA->getUnavailable())
+ Result << "<Unavailable/>";
+ Result << "</Availability>";
+ }
+ }
+
+ {
+ bool StartTagEmitted = false;
+ for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
+ const Comment *C = Parts.MiscBlocks[i];
+ if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
+ continue;
+ if (!StartTagEmitted) {
+ Result << "<Discussion>";
+ StartTagEmitted = true;
+ }
+ visit(C);
+ }
+ if (StartTagEmitted)
+ Result << "</Discussion>";
+ }
+
+ Result << RootEndTag;
+}
+
+void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ const char C = *I;
+ switch (C) {
+ case '&':
+ Result << "&amp;";
+ break;
+ case '<':
+ Result << "&lt;";
+ break;
+ case '>':
+ Result << "&gt;";
+ break;
+ case '"':
+ Result << "&quot;";
+ break;
+ case '\'':
+ Result << "&apos;";
+ break;
+ default:
+ Result << C;
+ break;
+ }
+ }
+}
+
+void CommentASTToXMLConverter::appendToResultWithCDATAEscaping(StringRef S) {
+ if (S.empty())
+ return;
+
+ Result << "<![CDATA[";
+ while (!S.empty()) {
+ size_t Pos = S.find("]]>");
+ if (Pos == 0) {
+ Result << "]]]]><![CDATA[>";
+ S = S.drop_front(3);
+ continue;
+ }
+ if (Pos == StringRef::npos)
+ Pos = S.size();
+
+ Result << S.substr(0, Pos);
+
+ S = S.drop_front(Pos);
+ }
+ Result << "]]>";
+}
+
+CommentToXMLConverter::CommentToXMLConverter() {}
+CommentToXMLConverter::~CommentToXMLConverter() {}
+
+void CommentToXMLConverter::convertCommentToHTML(const FullComment *FC,
+ SmallVectorImpl<char> &HTML,
+ const ASTContext &Context) {
+ CommentASTToHTMLConverter Converter(FC, HTML,
+ Context.getCommentCommandTraits());
+ Converter.visit(FC);
+}
+
+void CommentToXMLConverter::convertHTMLTagNodeToText(
+ const comments::HTMLTagComment *HTC, SmallVectorImpl<char> &Text,
+ const ASTContext &Context) {
+ CommentASTToHTMLConverter Converter(nullptr, Text,
+ Context.getCommentCommandTraits());
+ Converter.visit(HTC);
+}
+
+void CommentToXMLConverter::convertCommentToXML(const FullComment *FC,
+ SmallVectorImpl<char> &XML,
+ const ASTContext &Context) {
+ CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(),
+ Context.getSourceManager());
+ Converter.visit(FC);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
new file mode 100644
index 000000000000..3aa0152ec996
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
@@ -0,0 +1,348 @@
+//===- IndexBody.cpp - Indexing statements --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+using namespace clang;
+using namespace clang::index;
+
+namespace {
+
+class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
+ IndexingContext &IndexCtx;
+ const NamedDecl *Parent;
+ const DeclContext *ParentDC;
+ SmallVector<Stmt*, 16> StmtStack;
+
+ typedef RecursiveASTVisitor<BodyIndexer> base;
+public:
+ BodyIndexer(IndexingContext &indexCtx,
+ const NamedDecl *Parent, const DeclContext *DC)
+ : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool dataTraverseStmtPre(Stmt *S) {
+ StmtStack.push_back(S);
+ return true;
+ }
+
+ bool dataTraverseStmtPost(Stmt *S) {
+ assert(StmtStack.back() == S);
+ StmtStack.pop_back();
+ return true;
+ }
+
+ bool TraverseTypeLoc(TypeLoc TL) {
+ IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
+ return true;
+ }
+
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
+ return true;
+ }
+
+ SymbolRoleSet getRolesForRef(const Expr *E,
+ SmallVectorImpl<SymbolRelation> &Relations) {
+ SymbolRoleSet Roles{};
+ assert(!StmtStack.empty() && E == StmtStack.back());
+ if (StmtStack.size() == 1)
+ return Roles;
+ auto It = StmtStack.end()-2;
+ while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
+ if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
+ if (ICE->getCastKind() == CK_LValueToRValue)
+ Roles |= (unsigned)(unsigned)SymbolRole::Read;
+ }
+ if (It == StmtStack.begin())
+ break;
+ --It;
+ }
+ const Stmt *Parent = *It;
+
+ if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
+ if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
+ Roles |= (unsigned)SymbolRole::Write;
+
+ } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
+ if (UO->isIncrementDecrementOp()) {
+ Roles |= (unsigned)SymbolRole::Read;
+ Roles |= (unsigned)SymbolRole::Write;
+ } else if (UO->getOpcode() == UO_AddrOf) {
+ Roles |= (unsigned)SymbolRole::AddressOf;
+ }
+
+ } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
+ if (CA->getLHS()->IgnoreParenCasts() == E) {
+ Roles |= (unsigned)SymbolRole::Read;
+ Roles |= (unsigned)SymbolRole::Write;
+ }
+
+ } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
+ if (CE->getCallee()->IgnoreParenCasts() == E) {
+ addCallRole(Roles, Relations);
+ if (auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
+ if (CXXMD->isVirtual() && !ME->hasQualifier()) {
+ Roles |= (unsigned)SymbolRole::Dynamic;
+ auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
+ if (!BaseTy.isNull())
+ if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
+ Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
+ CXXRD);
+ }
+ }
+ } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
+ if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
+ OverloadedOperatorKind Op = CXXOp->getOperator();
+ if (Op == OO_Equal) {
+ Roles |= (unsigned)SymbolRole::Write;
+ } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
+ Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
+ Op == OO_PlusPlus || Op == OO_MinusMinus) {
+ Roles |= (unsigned)SymbolRole::Read;
+ Roles |= (unsigned)SymbolRole::Write;
+ } else if (Op == OO_Amp) {
+ Roles |= (unsigned)SymbolRole::AddressOf;
+ }
+ }
+ }
+ }
+
+ return Roles;
+ }
+
+ void addCallRole(SymbolRoleSet &Roles,
+ SmallVectorImpl<SymbolRelation> &Relations) {
+ Roles |= (unsigned)SymbolRole::Call;
+ if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
+ Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
+ else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
+ Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ SmallVector<SymbolRelation, 4> Relations;
+ SymbolRoleSet Roles = getRolesForRef(E, Relations);
+ return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
+ Parent, ParentDC, Roles, Relations, E);
+ }
+
+ bool VisitMemberExpr(MemberExpr *E) {
+ SourceLocation Loc = E->getMemberLoc();
+ if (Loc.isInvalid())
+ Loc = E->getLocStart();
+ SmallVector<SymbolRelation, 4> Relations;
+ SymbolRoleSet Roles = getRolesForRef(E, Relations);
+ return IndexCtx.handleReference(E->getMemberDecl(), Loc,
+ Parent, ParentDC, Roles, Relations, E);
+ }
+
+ bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
+ if (D.isFieldDesignator() && D.getField())
+ return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
+ ParentDC, SymbolRoleSet(), {}, E);
+ }
+ return true;
+ }
+
+ bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ SmallVector<SymbolRelation, 4> Relations;
+ SymbolRoleSet Roles = getRolesForRef(E, Relations);
+ return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
+ Parent, ParentDC, Roles, Relations, E);
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
+ 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 (ObjCMethodDecl *MD = E->getMethodDecl()) {
+ SymbolRoleSet Roles{};
+ SmallVector<SymbolRelation, 2> Relations;
+ addCallRole(Roles, Relations);
+ if (E->isImplicit())
+ Roles |= (unsigned)SymbolRole::Implicit;
+
+ if (isDynamic(E)) {
+ Roles |= (unsigned)SymbolRole::Dynamic;
+ if (auto *RecD = E->getReceiverInterface())
+ Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
+ }
+
+ return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
+ Parent, ParentDC, Roles, Relations, E);
+ }
+ return true;
+ }
+
+ bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ if (E->isExplicitProperty())
+ return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
+ Parent, ParentDC, SymbolRoleSet(), {}, E);
+
+ // No need to do a handleReference for the objc method, because there will
+ // be a message expr as part of PseudoObjectExpr.
+ return true;
+ }
+
+ bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
+ return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
+ Parent, ParentDC, SymbolRoleSet(), {}, E);
+ }
+
+ bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+ return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
+ Parent, ParentDC, SymbolRoleSet(), {}, E);
+ }
+
+ bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
+ SymbolRoleSet Roles{};
+ SmallVector<SymbolRelation, 2> Relations;
+ addCallRole(Roles, Relations);
+ Roles |= (unsigned)SymbolRole::Implicit;
+ return IndexCtx.handleReference(MD, E->getLocStart(),
+ Parent, ParentDC, Roles, Relations, E);
+ }
+
+ bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+ if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
+ return passObjCLiteralMethodCall(MD, E);
+ }
+ return true;
+ }
+
+ bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
+ if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
+ return passObjCLiteralMethodCall(MD, E);
+ }
+ return true;
+ }
+
+ bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
+ if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
+ return passObjCLiteralMethodCall(MD, E);
+ }
+ return true;
+ }
+
+ bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+ SymbolRoleSet Roles{};
+ SmallVector<SymbolRelation, 2> Relations;
+ addCallRole(Roles, Relations);
+ return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
+ Parent, ParentDC, Roles, Relations, E);
+ }
+
+ bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
+ DataRecursionQueue *Q = nullptr) {
+ if (E->getOperatorLoc().isInvalid())
+ return true; // implicit.
+ return base::TraverseCXXOperatorCallExpr(E, Q);
+ }
+
+ bool VisitDeclStmt(DeclStmt *S) {
+ if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
+ IndexCtx.indexDeclGroupRef(S->getDeclGroup());
+ return true;
+ }
+
+ DeclGroupRef DG = S->getDeclGroup();
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
+ const Decl *D = *I;
+ if (!D)
+ continue;
+ if (!IndexCtx.isFunctionLocalDecl(D))
+ IndexCtx.indexTopLevelDecl(D);
+ }
+
+ return true;
+ }
+
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+ Expr *Init) {
+ if (C->capturesThis() || C->capturesVLAType())
+ return true;
+
+ if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
+ return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
+ Parent, ParentDC, SymbolRoleSet());
+
+ // FIXME: Lambda init-captures.
+ return true;
+ }
+
+ // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
+ // the things that we visit. Make sure to only visit the semantic form.
+ // Also visit things that are in the syntactic form but not the semantic one,
+ // for example the indices in DesignatedInitExprs.
+ bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
+ auto visitForm = [&](InitListExpr *Form) {
+ for (Stmt *SubStmt : Form->children()) {
+ if (!TraverseStmt(SubStmt, Q))
+ return false;
+ }
+ return true;
+ };
+
+ auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
+ for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
+ if (D.isFieldDesignator())
+ return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
+ Parent, ParentDC, SymbolRoleSet(),
+ {}, E);
+ }
+ return true;
+ };
+
+ InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
+ InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
+
+ if (SemaForm) {
+ // Visit things present in syntactic form but not the semantic form.
+ if (SyntaxForm) {
+ for (Expr *init : SyntaxForm->inits()) {
+ if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
+ visitSyntacticDesignatedInitExpr(DIE);
+ }
+ }
+ return visitForm(SemaForm);
+ }
+
+ // No semantic, try the syntactic.
+ if (SyntaxForm) {
+ return visitForm(SyntaxForm);
+ }
+
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
+ const DeclContext *DC) {
+ if (!S)
+ return;
+
+ if (!DC)
+ DC = Parent->getLexicalDeclContext();
+ BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
new file mode 100644
index 000000000000..1225391dc2a6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
@@ -0,0 +1,482 @@
+//===- IndexDecl.cpp - Indexing declarations ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/AST/DeclVisitor.h"
+
+using namespace clang;
+using namespace index;
+
+#define TRY_TO(CALL_EXPR) \
+ do { \
+ if (!CALL_EXPR) \
+ return false; \
+ } while (0)
+
+namespace {
+
+class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
+ IndexingContext &IndexCtx;
+
+public:
+ explicit IndexingDeclVisitor(IndexingContext &indexCtx)
+ : IndexCtx(indexCtx) { }
+
+ bool Handled = true;
+
+ bool VisitDecl(const Decl *D) {
+ Handled = false;
+ return true;
+ }
+
+ /// \brief Returns true if the given method has been defined explicitly by the
+ /// user.
+ static bool hasUserDefined(const ObjCMethodDecl *D,
+ const ObjCImplDecl *Container) {
+ const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
+ D->isInstanceMethod());
+ return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
+ }
+
+ void handleDeclarator(const DeclaratorDecl *D,
+ const NamedDecl *Parent = nullptr) {
+ if (!Parent) Parent = D;
+
+ IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent);
+ IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
+ if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
+ // Only index parameters in definitions, parameters in declarations are
+ // not useful.
+ if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
+ auto *DC = Parm->getDeclContext();
+ if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
+ if (FD->isThisDeclarationADefinition())
+ IndexCtx.handleDecl(Parm);
+ } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
+ if (MD->isThisDeclarationADefinition())
+ IndexCtx.handleDecl(Parm);
+ } else {
+ IndexCtx.handleDecl(Parm);
+ }
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isThisDeclarationADefinition()) {
+ for (auto PI : FD->parameters()) {
+ IndexCtx.handleDecl(PI);
+ }
+ }
+ }
+ }
+ }
+
+ bool handleObjCMethod(const ObjCMethodDecl *D,
+ const ObjCPropertyDecl *AssociatedProp = nullptr) {
+ SmallVector<SymbolRelation, 4> Relations;
+ SmallVector<const ObjCMethodDecl*, 4> Overriden;
+
+ D->getOverriddenMethods(Overriden);
+ for(auto overridden: Overriden) {
+ Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
+ overridden);
+ }
+ if (AssociatedProp)
+ Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
+ AssociatedProp);
+
+ if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic, Relations))
+ return false;
+ IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
+ for (const auto *I : D->parameters())
+ handleDeclarator(I, D);
+
+ if (D->isThisDeclarationADefinition()) {
+ const Stmt *Body = D->getBody();
+ if (Body) {
+ IndexCtx.indexBody(Body, D, D);
+ }
+ }
+ return true;
+ }
+
+ bool VisitFunctionDecl(const FunctionDecl *D) {
+ if (D->isDeleted())
+ return true;
+
+ SymbolRoleSet Roles{};
+ SmallVector<SymbolRelation, 4> Relations;
+ if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
+ if (CXXMD->isVirtual())
+ Roles |= (unsigned)SymbolRole::Dynamic;
+ for (auto I = CXXMD->begin_overridden_methods(),
+ E = CXXMD->end_overridden_methods(); I != E; ++I) {
+ Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
+ }
+ }
+
+ if (!IndexCtx.handleDecl(D, Roles, Relations))
+ return false;
+ handleDeclarator(D);
+
+ if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
+ // Constructor initializers.
+ for (const auto *Init : Ctor->inits()) {
+ if (Init->isWritten()) {
+ IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
+ if (const FieldDecl *Member = Init->getAnyMember())
+ IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
+ (unsigned)SymbolRole::Write);
+ IndexCtx.indexBody(Init->getInit(), D, D);
+ }
+ }
+ }
+
+ if (D->isThisDeclarationADefinition()) {
+ const Stmt *Body = D->getBody();
+ if (Body) {
+ IndexCtx.indexBody(Body, D, D);
+ }
+ }
+ return true;
+ }
+
+ bool VisitVarDecl(const VarDecl *D) {
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ handleDeclarator(D);
+ IndexCtx.indexBody(D->getInit(), D);
+ return true;
+ }
+
+ bool VisitFieldDecl(const FieldDecl *D) {
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ handleDeclarator(D);
+ if (D->isBitField())
+ IndexCtx.indexBody(D->getBitWidth(), D);
+ else if (D->hasInClassInitializer())
+ IndexCtx.indexBody(D->getInClassInitializer(), D);
+ return true;
+ }
+
+ bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
+ if (D->getSynthesize()) {
+ // For synthesized ivars, use the location of the ObjC implementation,
+ // not the location of the property.
+ // Otherwise the header file containing the @interface will have different
+ // indexing contents based on whether the @implementation was present or
+ // not in the translation unit.
+ return IndexCtx.handleDecl(D,
+ cast<Decl>(D->getDeclContext())->getLocation(),
+ (unsigned)SymbolRole::Implicit);
+ }
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ handleDeclarator(D);
+ return true;
+ }
+
+ bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
+ handleDeclarator(D);
+ return true;
+ }
+
+ bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ IndexCtx.indexBody(D->getInitExpr(), D);
+ return true;
+ }
+
+ bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
+ return true;
+ }
+
+ bool VisitTagDecl(const TagDecl *D) {
+ // Non-free standing tags are handled in indexTypeSourceInfo.
+ if (D->isFreeStanding()) {
+ if (D->isThisDeclarationADefinition()) {
+ IndexCtx.indexTagDecl(D);
+ } else {
+ auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
+ return IndexCtx.handleReference(D, D->getLocation(), Parent,
+ D->getLexicalDeclContext(),
+ SymbolRoleSet());
+ }
+ }
+ return true;
+ }
+
+ bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
+ const ObjCContainerDecl *ContD) {
+ 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;
+ TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD,
+ SymbolRoleSet(),
+ SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
+ }
+ return true;
+ }
+
+ bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(IndexCtx.handleDecl(D));
+ if (auto *SuperD = D->getSuperClass()) {
+ TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D,
+ SymbolRoleSet(),
+ SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
+ }
+ TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
+ TRY_TO(IndexCtx.indexDeclContext(D));
+ } else {
+ return IndexCtx.handleReference(D, D->getLocation(), nullptr,
+ D->getDeclContext(), SymbolRoleSet());
+ }
+ return true;
+ }
+
+ bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(IndexCtx.handleDecl(D));
+ TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
+ TRY_TO(IndexCtx.indexDeclContext(D));
+ } else {
+ return IndexCtx.handleReference(D, D->getLocation(), nullptr,
+ D->getDeclContext(), SymbolRoleSet());
+ }
+ return true;
+ }
+
+ bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
+ const ObjCInterfaceDecl *Class = D->getClassInterface();
+ if (!Class)
+ return true;
+
+ if (Class->isImplicitInterfaceDecl())
+ IndexCtx.handleDecl(Class);
+
+ if (!IndexCtx.handleDecl(D))
+ return false;
+
+ // Index the ivars first to make sure the synthesized ivars are indexed
+ // before indexing the methods that can reference them.
+ for (const auto *IvarI : D->ivars())
+ IndexCtx.indexDecl(IvarI);
+ for (const auto *I : D->decls()) {
+ if (!isa<ObjCIvarDecl>(I))
+ IndexCtx.indexDecl(I);
+ }
+
+ return true;
+ }
+
+ bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
+ const ObjCInterfaceDecl *C = D->getClassInterface();
+ if (C)
+ TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
+ SymbolRoleSet(), SymbolRelation{
+ (unsigned)SymbolRole::RelationExtendedBy, D
+ }));
+ SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ if (!CategoryLoc.isValid())
+ CategoryLoc = D->getLocation();
+ TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
+ TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
+ TRY_TO(IndexCtx.indexDeclContext(D));
+ return true;
+ }
+
+ bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
+ const ObjCCategoryDecl *Cat = D->getCategoryDecl();
+ if (!Cat)
+ return true;
+ const ObjCInterfaceDecl *C = D->getClassInterface();
+ if (C)
+ TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
+ SymbolRoleSet()));
+ SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ if (!CategoryLoc.isValid())
+ CategoryLoc = D->getLocation();
+ if (!IndexCtx.handleDecl(D, CategoryLoc))
+ return false;
+ IndexCtx.indexDeclContext(D);
+ return true;
+ }
+
+ bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+ // Methods associated with a property, even user-declared ones, are
+ // handled when we handle the property.
+ if (D->isPropertyAccessor())
+ return true;
+
+ handleObjCMethod(D);
+ return true;
+ }
+
+ bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
+ if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
+ if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
+ handleObjCMethod(MD, D);
+ if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
+ if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
+ handleObjCMethod(MD, D);
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
+ return true;
+ }
+
+ bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
+ ObjCPropertyDecl *PD = D->getPropertyDecl();
+ if (!IndexCtx.handleReference(PD, D->getLocation(),
+ /*Parent=*/cast<NamedDecl>(D->getDeclContext()),
+ D->getDeclContext(), SymbolRoleSet(), {},
+ /*RefE=*/nullptr, D))
+ return false;
+
+ if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ return true;
+ assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
+
+ if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
+ if (!IvarD->getSynthesize())
+ IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
+ D->getDeclContext(), SymbolRoleSet());
+ }
+
+ auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext());
+ if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
+ if (MD->isPropertyAccessor() &&
+ !hasUserDefined(MD, ImplD))
+ IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
+ }
+ if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
+ if (MD->isPropertyAccessor() &&
+ !hasUserDefined(MD, ImplD))
+ IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
+ }
+ return true;
+ }
+
+ bool VisitNamespaceDecl(const NamespaceDecl *D) {
+ if (!IndexCtx.handleDecl(D))
+ return false;
+ IndexCtx.indexDeclContext(D);
+ return true;
+ }
+
+ bool VisitUsingDecl(const UsingDecl *D) {
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+
+ IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+ D->getLexicalDeclContext());
+ for (const auto *I : D->shadows())
+ IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
+ D->getLexicalDeclContext(), SymbolRoleSet());
+ return true;
+ }
+
+ bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
+
+ IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
+ D->getLexicalDeclContext());
+ return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
+ D->getLocation(), Parent,
+ D->getLexicalDeclContext(),
+ SymbolRoleSet());
+ }
+
+ bool VisitClassTemplateSpecializationDecl(const
+ ClassTemplateSpecializationDecl *D) {
+ // FIXME: Notify subsequent callbacks if info comes from implicit
+ // instantiation.
+ if (D->isThisDeclarationADefinition())
+ IndexCtx.indexTagDecl(D);
+ return true;
+ }
+
+ bool VisitTemplateDecl(const TemplateDecl *D) {
+ // FIXME: Template parameters.
+ return Visit(D->getTemplatedDecl());
+ }
+
+ bool VisitFriendDecl(const FriendDecl *D) {
+ if (auto ND = D->getFriendDecl()) {
+ // FIXME: Ignore a class template in a dependent context, these are not
+ // linked properly with their redeclarations, ending up with duplicate
+ // USRs.
+ // See comment "Friend templates are visible in fairly strange ways." in
+ // SemaTemplate.cpp which precedes code that prevents the friend template
+ // from becoming visible from the enclosing context.
+ if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
+ return true;
+ return Visit(ND);
+ }
+ if (auto Ty = D->getFriendType()) {
+ IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
+ }
+ return true;
+ }
+
+ bool VisitImportDecl(const ImportDecl *D) {
+ return IndexCtx.importedModule(D);
+ }
+};
+
+} // anonymous namespace
+
+bool IndexingContext::indexDecl(const Decl *D) {
+ if (D->isImplicit() && shouldIgnoreIfImplicit(D))
+ return true;
+
+ if (isTemplateImplicitInstantiation(D))
+ return true;
+
+ IndexingDeclVisitor Visitor(*this);
+ bool ShouldContinue = Visitor.Visit(D);
+ if (!ShouldContinue)
+ return false;
+
+ if (!Visitor.Handled && isa<DeclContext>(D))
+ return indexDeclContext(cast<DeclContext>(D));
+
+ return true;
+}
+
+bool IndexingContext::indexDeclContext(const DeclContext *DC) {
+ for (const auto *I : DC->decls())
+ if (!indexDecl(I))
+ return false;
+ return true;
+}
+
+bool IndexingContext::indexTopLevelDecl(const Decl *D) {
+ if (D->getLocation().isInvalid())
+ return true;
+
+ if (isa<ObjCMethodDecl>(D))
+ return true; // Wait for the objc container.
+
+ return indexDecl(D);
+}
+
+bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ if (!indexTopLevelDecl(*I))
+ return false;
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
new file mode 100644
index 000000000000..be847e762091
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp
@@ -0,0 +1,425 @@
+//===--- IndexSymbol.cpp - Types and functions for indexing symbols -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/IndexSymbol.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyPrinter.h"
+
+using namespace clang;
+using namespace clang::index;
+
+/// \returns true if \c D is a subclass of 'XCTestCase'.
+static bool isUnitTestCase(const ObjCInterfaceDecl *D) {
+ if (!D)
+ return false;
+ while (const ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
+ if (SuperD->getName() == "XCTestCase")
+ return true;
+ D = SuperD;
+ }
+ return false;
+}
+
+/// \returns true if \c D is in a subclass of 'XCTestCase', returns void, has
+/// no parameters, and its name starts with 'test'.
+static bool isUnitTest(const ObjCMethodDecl *D) {
+ if (!D->parameters().empty())
+ return false;
+ if (!D->getReturnType()->isVoidType())
+ return false;
+ if (!D->getSelector().getNameForSlot(0).startswith("test"))
+ return false;
+ return isUnitTestCase(D->getClassInterface());
+}
+
+static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) {
+ if (D->hasAttr<IBOutletAttr>()) {
+ PropSet |= (unsigned)SymbolProperty::IBAnnotated;
+ } else if (D->hasAttr<IBOutletCollectionAttr>()) {
+ PropSet |= (unsigned)SymbolProperty::IBAnnotated;
+ PropSet |= (unsigned)SymbolProperty::IBOutletCollection;
+ }
+}
+
+SymbolInfo index::getSymbolInfo(const Decl *D) {
+ assert(D);
+ SymbolInfo Info;
+ Info.Kind = SymbolKind::Unknown;
+ Info.SubKind = SymbolSubKind::None;
+ Info.Properties = SymbolPropertySet();
+ Info.Lang = SymbolLanguage::C;
+
+ if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TTK_Struct:
+ Info.Kind = SymbolKind::Struct; break;
+ case TTK_Union:
+ Info.Kind = SymbolKind::Union; break;
+ case TTK_Class:
+ Info.Kind = SymbolKind::Class;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case TTK_Interface:
+ Info.Kind = SymbolKind::Protocol;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case TTK_Enum:
+ Info.Kind = SymbolKind::Enum; break;
+ }
+
+ if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) {
+ if (!CXXRec->isCLike()) {
+ Info.Lang = SymbolLanguage::CXX;
+ if (CXXRec->getDescribedClassTemplate()) {
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ }
+ }
+ }
+
+ if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
+ } else if (isa<ClassTemplateSpecializationDecl>(D)) {
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ }
+
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ Info.Kind = SymbolKind::Variable;
+ if (isa<CXXRecordDecl>(D->getDeclContext())) {
+ Info.Kind = SymbolKind::StaticProperty;
+ Info.Lang = SymbolLanguage::CXX;
+ }
+ if (isa<VarTemplatePartialSpecializationDecl>(D)) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
+ } else if (isa<VarTemplateSpecializationDecl>(D)) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ } else if (VD->getDescribedVarTemplate()) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ }
+
+ } else {
+ switch (D->getKind()) {
+ case Decl::Import:
+ Info.Kind = SymbolKind::Module;
+ break;
+ case Decl::Typedef:
+ Info.Kind = SymbolKind::TypeAlias; break; // Lang = C
+ case Decl::Function:
+ Info.Kind = SymbolKind::Function;
+ break;
+ case Decl::Field:
+ Info.Kind = SymbolKind::Field;
+ if (const CXXRecordDecl *
+ CXXRec = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
+ if (!CXXRec->isCLike())
+ Info.Lang = SymbolLanguage::CXX;
+ }
+ break;
+ case Decl::EnumConstant:
+ Info.Kind = SymbolKind::EnumConstant; break;
+ case Decl::ObjCInterface:
+ case Decl::ObjCImplementation: {
+ Info.Kind = SymbolKind::Class;
+ Info.Lang = SymbolLanguage::ObjC;
+ const ObjCInterfaceDecl *ClsD = dyn_cast<ObjCInterfaceDecl>(D);
+ if (!ClsD)
+ ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface();
+ if (isUnitTestCase(ClsD))
+ Info.Properties |= (unsigned)SymbolProperty::UnitTest;
+ break;
+ }
+ case Decl::ObjCProtocol:
+ Info.Kind = SymbolKind::Protocol;
+ Info.Lang = SymbolLanguage::ObjC;
+ break;
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ Info.Kind = SymbolKind::Extension;
+ Info.Lang = SymbolLanguage::ObjC;
+ break;
+ case Decl::ObjCMethod:
+ if (cast<ObjCMethodDecl>(D)->isInstanceMethod())
+ Info.Kind = SymbolKind::InstanceMethod;
+ else
+ Info.Kind = SymbolKind::ClassMethod;
+ Info.Lang = SymbolLanguage::ObjC;
+ if (isUnitTest(cast<ObjCMethodDecl>(D)))
+ Info.Properties |= (unsigned)SymbolProperty::UnitTest;
+ if (D->hasAttr<IBActionAttr>())
+ Info.Properties |= (unsigned)SymbolProperty::IBAnnotated;
+ break;
+ case Decl::ObjCProperty:
+ Info.Kind = SymbolKind::InstanceProperty;
+ Info.Lang = SymbolLanguage::ObjC;
+ checkForIBOutlets(D, Info.Properties);
+ if (auto *Annot = D->getAttr<AnnotateAttr>()) {
+ if (Annot->getAnnotation() == "gk_inspectable")
+ Info.Properties |= (unsigned)SymbolProperty::GKInspectable;
+ }
+ break;
+ case Decl::ObjCIvar:
+ Info.Kind = SymbolKind::Field;
+ Info.Lang = SymbolLanguage::ObjC;
+ checkForIBOutlets(D, Info.Properties);
+ break;
+ case Decl::Namespace:
+ Info.Kind = SymbolKind::Namespace;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case Decl::NamespaceAlias:
+ Info.Kind = SymbolKind::NamespaceAlias;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case Decl::CXXConstructor: {
+ Info.Kind = SymbolKind::Constructor;
+ Info.Lang = SymbolLanguage::CXX;
+ auto *CD = cast<CXXConstructorDecl>(D);
+ if (CD->isCopyConstructor())
+ Info.SubKind = SymbolSubKind::CXXCopyConstructor;
+ else if (CD->isMoveConstructor())
+ Info.SubKind = SymbolSubKind::CXXMoveConstructor;
+ break;
+ }
+ case Decl::CXXDestructor:
+ Info.Kind = SymbolKind::Destructor;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case Decl::CXXConversion:
+ Info.Kind = SymbolKind::ConversionFunction;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case Decl::CXXMethod: {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
+ if (MD->isStatic())
+ Info.Kind = SymbolKind::StaticMethod;
+ else
+ Info.Kind = SymbolKind::InstanceMethod;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ }
+ case Decl::ClassTemplate:
+ Info.Kind = SymbolKind::Class;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ case Decl::FunctionTemplate:
+ Info.Kind = SymbolKind::Function;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Lang = SymbolLanguage::CXX;
+ if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
+ cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
+ if (isa<CXXConstructorDecl>(MD))
+ Info.Kind = SymbolKind::Constructor;
+ else if (isa<CXXDestructorDecl>(MD))
+ Info.Kind = SymbolKind::Destructor;
+ else if (isa<CXXConversionDecl>(MD))
+ Info.Kind = SymbolKind::ConversionFunction;
+ else {
+ if (MD->isStatic())
+ Info.Kind = SymbolKind::StaticMethod;
+ else
+ Info.Kind = SymbolKind::InstanceMethod;
+ }
+ }
+ break;
+ case Decl::TypeAliasTemplate:
+ Info.Kind = SymbolKind::TypeAlias;
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ break;
+ case Decl::TypeAlias:
+ Info.Kind = SymbolKind::TypeAlias;
+ Info.Lang = SymbolLanguage::CXX;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (Info.Kind == SymbolKind::Unknown)
+ return Info;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization) {
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ }
+ }
+
+ if (Info.Properties & (unsigned)SymbolProperty::Generic)
+ Info.Lang = SymbolLanguage::CXX;
+
+ return Info;
+}
+
+void index::applyForEachSymbolRole(SymbolRoleSet Roles,
+ llvm::function_ref<void(SymbolRole)> Fn) {
+#define APPLY_FOR_ROLE(Role) \
+ if (Roles & (unsigned)SymbolRole::Role) \
+ Fn(SymbolRole::Role)
+
+ APPLY_FOR_ROLE(Declaration);
+ APPLY_FOR_ROLE(Definition);
+ APPLY_FOR_ROLE(Reference);
+ APPLY_FOR_ROLE(Read);
+ APPLY_FOR_ROLE(Write);
+ APPLY_FOR_ROLE(Call);
+ APPLY_FOR_ROLE(Dynamic);
+ APPLY_FOR_ROLE(AddressOf);
+ APPLY_FOR_ROLE(Implicit);
+ APPLY_FOR_ROLE(RelationChildOf);
+ APPLY_FOR_ROLE(RelationBaseOf);
+ APPLY_FOR_ROLE(RelationOverrideOf);
+ APPLY_FOR_ROLE(RelationReceivedBy);
+ APPLY_FOR_ROLE(RelationCalledBy);
+ APPLY_FOR_ROLE(RelationExtendedBy);
+ APPLY_FOR_ROLE(RelationAccessorOf);
+
+#undef APPLY_FOR_ROLE
+}
+
+void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
+ bool VisitedOnce = false;
+ applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
+ if (VisitedOnce)
+ OS << ',';
+ else
+ VisitedOnce = true;
+ switch (Role) {
+ case SymbolRole::Declaration: OS << "Decl"; break;
+ case SymbolRole::Definition: OS << "Def"; break;
+ case SymbolRole::Reference: OS << "Ref"; break;
+ case SymbolRole::Read: OS << "Read"; break;
+ case SymbolRole::Write: OS << "Writ"; break;
+ case SymbolRole::Call: OS << "Call"; break;
+ case SymbolRole::Dynamic: OS << "Dyn"; break;
+ case SymbolRole::AddressOf: OS << "Addr"; break;
+ case SymbolRole::Implicit: OS << "Impl"; break;
+ case SymbolRole::RelationChildOf: OS << "RelChild"; break;
+ case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
+ case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
+ case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
+ case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
+ case SymbolRole::RelationExtendedBy: OS << "RelExt"; break;
+ case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
+ }
+ });
+}
+
+bool index::printSymbolName(const Decl *D, const LangOptions &LO,
+ raw_ostream &OS) {
+ if (auto *ND = dyn_cast<NamedDecl>(D)) {
+ PrintingPolicy Policy(LO);
+ // Forward references can have different template argument names. Suppress
+ // the template argument names in constructors to make their name more
+ // stable.
+ Policy.SuppressTemplateArgsInCXXConstructors = true;
+ DeclarationName DeclName = ND->getDeclName();
+ if (DeclName.isEmpty())
+ return true;
+ DeclName.print(OS, Policy);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+StringRef index::getSymbolKindString(SymbolKind K) {
+ switch (K) {
+ case SymbolKind::Unknown: return "<unknown>";
+ case SymbolKind::Module: return "module";
+ case SymbolKind::Namespace: return "namespace";
+ case SymbolKind::NamespaceAlias: return "namespace-alias";
+ case SymbolKind::Macro: return "macro";
+ case SymbolKind::Enum: return "enum";
+ case SymbolKind::Struct: return "struct";
+ case SymbolKind::Class: return "class";
+ case SymbolKind::Protocol: return "protocol";
+ case SymbolKind::Extension: return "extension";
+ case SymbolKind::Union: return "union";
+ case SymbolKind::TypeAlias: return "type-alias";
+ case SymbolKind::Function: return "function";
+ case SymbolKind::Variable: return "variable";
+ case SymbolKind::Field: return "field";
+ case SymbolKind::EnumConstant: return "enumerator";
+ case SymbolKind::InstanceMethod: return "instance-method";
+ case SymbolKind::ClassMethod: return "class-method";
+ case SymbolKind::StaticMethod: return "static-method";
+ case SymbolKind::InstanceProperty: return "instance-property";
+ case SymbolKind::ClassProperty: return "class-property";
+ case SymbolKind::StaticProperty: return "static-property";
+ case SymbolKind::Constructor: return "constructor";
+ case SymbolKind::Destructor: return "destructor";
+ case SymbolKind::ConversionFunction: return "coversion-func";
+ }
+ llvm_unreachable("invalid symbol kind");
+}
+
+StringRef index::getSymbolSubKindString(SymbolSubKind K) {
+ switch (K) {
+ case SymbolSubKind::None: return "<none>";
+ case SymbolSubKind::CXXCopyConstructor: return "cxx-copy-ctor";
+ case SymbolSubKind::CXXMoveConstructor: return "cxx-move-ctor";
+ }
+ llvm_unreachable("invalid symbol subkind");
+}
+
+StringRef index::getSymbolLanguageString(SymbolLanguage K) {
+ switch (K) {
+ case SymbolLanguage::C: return "C";
+ case SymbolLanguage::ObjC: return "ObjC";
+ case SymbolLanguage::CXX: return "C++";
+ }
+ llvm_unreachable("invalid symbol language kind");
+}
+
+void index::applyForEachSymbolProperty(SymbolPropertySet Props,
+ llvm::function_ref<void(SymbolProperty)> Fn) {
+#define APPLY_FOR_PROPERTY(K) \
+ if (Props & (unsigned)SymbolProperty::K) \
+ Fn(SymbolProperty::K)
+
+ APPLY_FOR_PROPERTY(Generic);
+ APPLY_FOR_PROPERTY(TemplatePartialSpecialization);
+ APPLY_FOR_PROPERTY(TemplateSpecialization);
+ APPLY_FOR_PROPERTY(UnitTest);
+ APPLY_FOR_PROPERTY(IBAnnotated);
+ APPLY_FOR_PROPERTY(IBOutletCollection);
+ APPLY_FOR_PROPERTY(GKInspectable);
+
+#undef APPLY_FOR_PROPERTY
+}
+
+void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
+ bool VisitedOnce = false;
+ applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) {
+ if (VisitedOnce)
+ OS << ',';
+ else
+ VisitedOnce = true;
+ switch (Prop) {
+ case SymbolProperty::Generic: OS << "Gen"; break;
+ case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break;
+ case SymbolProperty::TemplateSpecialization: OS << "TS"; break;
+ case SymbolProperty::UnitTest: OS << "test"; break;
+ case SymbolProperty::IBAnnotated: OS << "IB"; break;
+ case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
+ case SymbolProperty::GKInspectable: OS << "GKI"; break;
+ }
+ });
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
new file mode 100644
index 000000000000..619a9a48befd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -0,0 +1,202 @@
+//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+using namespace clang;
+using namespace index;
+
+namespace {
+
+class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
+ IndexingContext &IndexCtx;
+ const NamedDecl *Parent;
+ const DeclContext *ParentDC;
+ bool IsBase;
+ SmallVector<SymbolRelation, 3> Relations;
+
+ typedef RecursiveASTVisitor<TypeIndexer> base;
+
+public:
+ TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
+ const DeclContext *DC, bool isBase)
+ : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
+ if (IsBase) {
+ assert(Parent);
+ Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
+ }
+ }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
+ Parent, ParentDC, SymbolRoleSet(),
+ Relations);
+ }
+
+#define TRY_TO(CALL_EXPR) \
+ do { \
+ if (!CALL_EXPR) \
+ return false; \
+ } while (0)
+
+ bool traverseParamVarHelper(ParmVarDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ if (D->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ return true;
+ }
+
+ bool TraverseParmVarDecl(ParmVarDecl *D) {
+ // Avoid visiting default arguments from the definition that were already
+ // visited in the declaration.
+ // FIXME: A free function definition can have default arguments.
+ // Avoiding double visitaiton of default arguments should be handled by the
+ // visitor probably with a bit in the AST to indicate if the attached
+ // default argument was 'inherited' or written in source.
+ if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
+ if (FD->isThisDeclarationADefinition()) {
+ return traverseParamVarHelper(D);
+ }
+ }
+
+ return base::TraverseParmVarDecl(D);
+ }
+
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
+ return true;
+ }
+
+ bool VisitTagTypeLoc(TagTypeLoc TL) {
+ TagDecl *D = TL.getDecl();
+ if (D->getParentFunctionOrMethod())
+ return true;
+
+ if (TL.isDefinition()) {
+ IndexCtx.indexTagDecl(D);
+ return true;
+ }
+
+ return IndexCtx.handleReference(D, TL.getNameLoc(),
+ Parent, ParentDC, SymbolRoleSet(),
+ Relations);
+ }
+
+ bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
+ Parent, ParentDC, SymbolRoleSet());
+ }
+
+ bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
+ IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
+ Parent, ParentDC, SymbolRoleSet());
+ }
+ return true;
+ }
+
+ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+ if (const TemplateSpecializationType *T = TL.getTypePtr()) {
+ if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
+ Parent, ParentDC, SymbolRoleSet(), Relations);
+ } else {
+ if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
+ IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
+ Parent, ParentDC, SymbolRoleSet(), Relations);
+ }
+ }
+ return true;
+ }
+
+ bool TraverseStmt(Stmt *S) {
+ IndexCtx.indexBody(S, Parent, ParentDC);
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ bool isBase) {
+ if (!TInfo || TInfo->getTypeLoc().isNull())
+ return;
+
+ indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase);
+}
+
+void IndexingContext::indexTypeLoc(TypeLoc TL,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ bool isBase) {
+ if (TL.isNull())
+ return;
+
+ if (!DC)
+ DC = Parent->getLexicalDeclContext();
+ TypeIndexer(*this, Parent, DC, isBase).TraverseTypeLoc(TL);
+}
+
+void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const NamedDecl *Parent,
+ const DeclContext *DC) {
+ if (!NNS)
+ return;
+
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ indexNestedNameSpecifierLoc(Prefix, Parent, DC);
+
+ if (!DC)
+ DC = Parent->getLexicalDeclContext();
+ SourceLocation Loc = NNS.getSourceRange().getBegin();
+
+ switch (NNS.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
+ Loc, Parent, DC, SymbolRoleSet());
+ break;
+ case NestedNameSpecifier::NamespaceAlias:
+ handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
+ Loc, Parent, DC, SymbolRoleSet());
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
+ break;
+ }
+}
+
+void IndexingContext::indexTagDecl(const TagDecl *D) {
+ if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+ return;
+
+ if (handleDecl(D)) {
+ if (D->isThisDeclarationADefinition()) {
+ indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
+ if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
+ for (const auto &I : CXXRD->bases()) {
+ indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
+ }
+ }
+ indexDeclContext(D);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
new file mode 100644
index 000000000000..d7442931523f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
@@ -0,0 +1,176 @@
+//===- IndexingAction.cpp - Frontend index action -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "IndexingContext.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace clang::index;
+
+void IndexDataConsumer::_anchor() {}
+
+bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ FileID FID, unsigned Offset,
+ ASTNodeInfo ASTNode) {
+ return true;
+}
+
+bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
+ const MacroInfo *MI, SymbolRoleSet Roles,
+ FileID FID, unsigned Offset) {
+ return true;
+}
+
+bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
+ SymbolRoleSet Roles,
+ FileID FID, unsigned Offset) {
+ return true;
+}
+
+namespace {
+
+class IndexASTConsumer : public ASTConsumer {
+ IndexingContext &IndexCtx;
+
+public:
+ IndexASTConsumer(IndexingContext &IndexCtx)
+ : IndexCtx(IndexCtx) {}
+
+protected:
+ void Initialize(ASTContext &Context) override {
+ IndexCtx.setASTContext(Context);
+ IndexCtx.getDataConsumer().initialize(Context);
+ }
+
+ bool HandleTopLevelDecl(DeclGroupRef DG) override {
+ return IndexCtx.indexDeclGroupRef(DG);
+ }
+
+ void HandleInterestingDecl(DeclGroupRef DG) override {
+ // Ignore deserialized decls.
+ }
+
+ void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
+ IndexCtx.indexDeclGroupRef(DG);
+ }
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ }
+};
+
+class IndexActionBase {
+protected:
+ std::shared_ptr<IndexDataConsumer> DataConsumer;
+ IndexingContext IndexCtx;
+
+ IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
+ IndexingOptions Opts)
+ : DataConsumer(std::move(dataConsumer)),
+ IndexCtx(Opts, *DataConsumer) {}
+
+ std::unique_ptr<IndexASTConsumer> createIndexASTConsumer() {
+ return llvm::make_unique<IndexASTConsumer>(IndexCtx);
+ }
+
+ void finish() {
+ DataConsumer->finish();
+ }
+};
+
+class IndexAction : public ASTFrontendAction, IndexActionBase {
+public:
+ IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts)
+ : IndexActionBase(std::move(DataConsumer), Opts) {}
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
+ return createIndexASTConsumer();
+ }
+
+ void EndSourceFileAction() override {
+ FrontendAction::EndSourceFileAction();
+ finish();
+ }
+};
+
+class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
+ bool IndexActionFailed = false;
+
+public:
+ WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts)
+ : WrapperFrontendAction(std::move(WrappedAction)),
+ IndexActionBase(std::move(DataConsumer), Opts) {}
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ void EndSourceFileAction() override;
+};
+
+} // anonymous namespace
+
+void WrappingIndexAction::EndSourceFileAction() {
+ // Invoke wrapped action's method.
+ WrapperFrontendAction::EndSourceFileAction();
+ if (!IndexActionFailed)
+ finish();
+}
+
+std::unique_ptr<ASTConsumer>
+WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+ if (!OtherConsumer) {
+ IndexActionFailed = true;
+ return nullptr;
+ }
+
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(std::move(OtherConsumer));
+ Consumers.push_back(createIndexASTConsumer());
+ return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
+}
+
+std::unique_ptr<FrontendAction>
+index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts,
+ std::unique_ptr<FrontendAction> WrappedAction) {
+ if (WrappedAction)
+ return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
+ std::move(DataConsumer),
+ Opts);
+ return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
+}
+
+
+static bool topLevelDeclVisitor(void *context, const Decl *D) {
+ IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
+ return IndexCtx.indexTopLevelDecl(D);
+}
+
+static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
+ Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
+}
+
+void index::indexASTUnit(ASTUnit &Unit,
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ IndexingOptions Opts) {
+ IndexingContext IndexCtx(Opts, *DataConsumer);
+ IndexCtx.setASTContext(Unit.getASTContext());
+ DataConsumer->initialize(Unit.getASTContext());
+ indexTranslationUnit(Unit, IndexCtx);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
new file mode 100644
index 000000000000..e623a495b47b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
@@ -0,0 +1,326 @@
+//===- IndexingContext.cpp - Indexing context data ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IndexingContext.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+using namespace index;
+
+bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
+ return IndexOpts.IndexFunctionLocals;
+}
+
+bool IndexingContext::handleDecl(const Decl *D,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations) {
+ return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
+ cast<Decl>(D->getDeclContext()), Roles, Relations,
+ nullptr, nullptr, D->getDeclContext());
+}
+
+bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ const DeclContext *DC) {
+ if (!DC)
+ DC = D->getDeclContext();
+ return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
+ Roles, Relations,
+ nullptr, nullptr, DC);
+}
+
+bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ const Expr *RefE,
+ const Decl *RefD) {
+ if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+ return true;
+
+ if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
+ return true;
+
+ return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
+ RefE, RefD, DC);
+}
+
+bool IndexingContext::importedModule(const ImportDecl *ImportD) {
+ SourceLocation Loc;
+ auto IdLocs = ImportD->getIdentifierLocs();
+ if (!IdLocs.empty())
+ Loc = IdLocs.front();
+ else
+ Loc = ImportD->getLocation();
+ SourceManager &SM = Ctx->getSourceManager();
+ Loc = SM.getFileLoc(Loc);
+ if (Loc.isInvalid())
+ return true;
+
+ FileID FID;
+ unsigned Offset;
+ std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+ if (FID.isInvalid())
+ return true;
+
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
+ if (Invalid || !SEntry.isFile())
+ return true;
+
+ if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
+ switch (IndexOpts.SystemSymbolFilter) {
+ case IndexingOptions::SystemSymbolFilterKind::None:
+ return true;
+ case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
+ case IndexingOptions::SystemSymbolFilterKind::All:
+ break;
+ }
+ }
+
+ SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
+ if (ImportD->isImplicit())
+ Roles |= (unsigned)SymbolRole::Implicit;
+
+ return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
+}
+
+bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
+ assert(D);
+
+ if (isa<TemplateTemplateParmDecl>(D))
+ return true;
+
+ if (isa<ObjCTypeParamDecl>(D))
+ return true;
+
+ if (!D->getParentFunctionOrMethod())
+ return false;
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ switch (ND->getFormalLinkage()) {
+ case NoLinkage:
+ case VisibleNoLinkage:
+ case InternalLinkage:
+ return true;
+ case UniqueExternalLinkage:
+ llvm_unreachable("Not a sema linkage");
+ case ExternalLinkage:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
+ TemplateSpecializationKind TKind = TSK_Undeclared;
+ if (const ClassTemplateSpecializationDecl *
+ SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ TKind = SD->getSpecializationKind();
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ TKind = FD->getTemplateSpecializationKind();
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ TKind = VD->getTemplateSpecializationKind();
+ }
+ switch (TKind) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return false;
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+ }
+ llvm_unreachable("invalid TemplateSpecializationKind");
+}
+
+bool IndexingContext::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;
+}
+
+static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
+ if (const ClassTemplateSpecializationDecl *
+ SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ return SD->getTemplateInstantiationPattern();
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ return FD->getTemplateInstantiationPattern();
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ return VD->getTemplateInstantiationPattern();
+ }
+ return nullptr;
+}
+
+static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
+ if (auto VD = dyn_cast<VarDecl>(D))
+ return VD->isThisDeclarationADefinition(Ctx);
+
+ if (auto FD = dyn_cast<FunctionDecl>(D))
+ return FD->isThisDeclarationADefinition();
+
+ if (auto TD = dyn_cast<TagDecl>(D))
+ return TD->isThisDeclarationADefinition();
+
+ if (auto MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
+
+ if (isa<TypedefNameDecl>(D) ||
+ isa<EnumConstantDecl>(D) ||
+ isa<FieldDecl>(D) ||
+ isa<MSPropertyDecl>(D) ||
+ isa<ObjCImplDecl>(D) ||
+ isa<ObjCPropertyImplDecl>(D))
+ return true;
+
+ return false;
+}
+
+static const Decl *adjustParent(const Decl *Parent) {
+ if (!Parent)
+ return nullptr;
+ for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
+ if (isa<TranslationUnitDecl>(Parent))
+ return nullptr;
+ if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
+ continue;
+ if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
+ if (NS->isAnonymousNamespace())
+ continue;
+ } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
+ if (RD->isAnonymousStructOrUnion())
+ continue;
+ } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
+ if (FD->getDeclName().isEmpty())
+ continue;
+ }
+ return Parent;
+ }
+}
+
+static const Decl *getCanonicalDecl(const Decl *D) {
+ D = D->getCanonicalDecl();
+ if (auto TD = dyn_cast<TemplateDecl>(D)) {
+ D = TD->getTemplatedDecl();
+ assert(D->isCanonicalDecl());
+ }
+
+ return D;
+}
+
+bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
+ bool IsRef, const Decl *Parent,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ const Expr *OrigE,
+ const Decl *OrigD,
+ const DeclContext *ContainerDC) {
+ if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
+ return true;
+ if (!isa<NamedDecl>(D) ||
+ (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
+ !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
+ return true;
+
+ SourceManager &SM = Ctx->getSourceManager();
+ Loc = SM.getFileLoc(Loc);
+ if (Loc.isInvalid())
+ return true;
+
+ FileID FID;
+ unsigned Offset;
+ std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
+ if (FID.isInvalid())
+ return true;
+
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
+ if (Invalid || !SEntry.isFile())
+ return true;
+
+ if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
+ switch (IndexOpts.SystemSymbolFilter) {
+ case IndexingOptions::SystemSymbolFilterKind::None:
+ return true;
+ case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
+ if (IsRef)
+ return true;
+ break;
+ case IndexingOptions::SystemSymbolFilterKind::All:
+ break;
+ }
+ }
+
+ if (isTemplateImplicitInstantiation(D)) {
+ if (!IsRef)
+ return true;
+ D = adjustTemplateImplicitInstantiation(D);
+ if (!D)
+ return true;
+ assert(!isTemplateImplicitInstantiation(D));
+ }
+
+ if (!OrigD)
+ OrigD = D;
+
+ if (IsRef)
+ Roles |= (unsigned)SymbolRole::Reference;
+ else if (isDeclADefinition(D, ContainerDC, *Ctx))
+ Roles |= (unsigned)SymbolRole::Definition;
+ else
+ Roles |= (unsigned)SymbolRole::Declaration;
+
+ D = getCanonicalDecl(D);
+ Parent = adjustParent(Parent);
+ if (Parent)
+ Parent = getCanonicalDecl(Parent);
+
+ SmallVector<SymbolRelation, 6> FinalRelations;
+ FinalRelations.reserve(Relations.size()+1);
+
+ auto addRelation = [&](SymbolRelation Rel) {
+ auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
+ [&](SymbolRelation Elem)->bool {
+ return Elem.RelatedSymbol == Rel.RelatedSymbol;
+ });
+ if (It != FinalRelations.end()) {
+ It->Roles |= Rel.Roles;
+ } else {
+ FinalRelations.push_back(Rel);
+ }
+ Roles |= Rel.Roles;
+ };
+
+ if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
+ addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
+ }
+ for (auto &Rel : Relations) {
+ addRelation(SymbolRelation(Rel.Roles,
+ Rel.RelatedSymbol->getCanonicalDecl()));
+ }
+
+ IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
+ return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
+ Node);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.h b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h
new file mode 100644
index 000000000000..600fc433b58d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h
@@ -0,0 +1,121 @@
+//===- IndexingContext.h - Indexing context data ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
+#define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Index/IndexSymbol.h"
+#include "clang/Index/IndexingAction.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+ class ASTContext;
+ class Decl;
+ class DeclGroupRef;
+ class ImportDecl;
+ class TagDecl;
+ class TypeSourceInfo;
+ class NamedDecl;
+ class ObjCMethodDecl;
+ class DeclContext;
+ class NestedNameSpecifierLoc;
+ class Stmt;
+ class Expr;
+ class TypeLoc;
+ class SourceLocation;
+
+namespace index {
+ class IndexDataConsumer;
+
+class IndexingContext {
+ IndexingOptions IndexOpts;
+ IndexDataConsumer &DataConsumer;
+ ASTContext *Ctx = nullptr;
+
+public:
+ IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer)
+ : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {}
+
+ const IndexingOptions &getIndexOpts() const { return IndexOpts; }
+ IndexDataConsumer &getDataConsumer() { return DataConsumer; }
+
+ void setASTContext(ASTContext &ctx) { Ctx = &ctx; }
+
+ bool shouldSuppressRefs() const {
+ return false;
+ }
+
+ bool shouldIndexFunctionLocalSymbols() const;
+
+ bool shouldIndexImplicitTemplateInsts() const {
+ return false;
+ }
+
+ static bool isFunctionLocalDecl(const Decl *D);
+ static bool isTemplateImplicitInstantiation(const Decl *D);
+
+ bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),
+ ArrayRef<SymbolRelation> Relations = None);
+
+ bool handleDecl(const Decl *D, SourceLocation Loc,
+ SymbolRoleSet Roles = SymbolRoleSet(),
+ ArrayRef<SymbolRelation> Relations = None,
+ const DeclContext *DC = nullptr);
+
+ bool handleReference(const NamedDecl *D, SourceLocation Loc,
+ const NamedDecl *Parent,
+ const DeclContext *DC,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations = None,
+ const Expr *RefE = nullptr,
+ const Decl *RefD = nullptr);
+
+ bool importedModule(const ImportDecl *ImportD);
+
+ bool indexDecl(const Decl *D);
+
+ void indexTagDecl(const TagDecl *D);
+
+ void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
+ const DeclContext *DC = nullptr,
+ bool isBase = false);
+
+ void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
+ const DeclContext *DC = nullptr,
+ bool isBase = false);
+
+ void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const NamedDecl *Parent,
+ const DeclContext *DC = nullptr);
+
+ bool indexDeclContext(const DeclContext *DC);
+
+ void indexBody(const Stmt *S, const NamedDecl *Parent,
+ const DeclContext *DC = nullptr);
+
+ bool indexTopLevelDecl(const Decl *D);
+ bool indexDeclGroupRef(DeclGroupRef DG);
+
+private:
+ bool shouldIgnoreIfImplicit(const Decl *D);
+
+ bool handleDeclOccurrence(const Decl *D, SourceLocation Loc,
+ bool IsRef, const Decl *Parent,
+ SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ const Expr *RefE,
+ const Decl *RefD,
+ const DeclContext *ContainerDC);
+};
+
+} // end namespace index
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
new file mode 100644
index 000000000000..2c26e4d82e08
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
@@ -0,0 +1,75 @@
+//===--- SimpleFormatContext.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// \brief Defines a utility class for use of clang-format in libclang
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_INDEX_SIMPLEFORMATCONTEXT_H
+#define LLVM_CLANG_LIB_INDEX_SIMPLEFORMATCONTEXT_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace index {
+
+/// \brief A small class to be used by libclang clients to format
+/// a declaration string in memory. This object is instantiated once
+/// and used each time a formatting is needed.
+class SimpleFormatContext {
+public:
+ SimpleFormatContext(LangOptions Options)
+ : DiagOpts(new DiagnosticOptions()),
+ Diagnostics(new DiagnosticsEngine(new DiagnosticIDs,
+ DiagOpts.get())),
+ InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ Files(FileSystemOptions(), InMemoryFileSystem),
+ Sources(*Diagnostics, Files),
+ Rewrite(Sources, Options) {
+ Diagnostics->setClient(new IgnoringDiagConsumer, true);
+ }
+
+ FileID createInMemoryFile(StringRef Name, StringRef Content) {
+ InMemoryFileSystem->addFile(Name, 0,
+ llvm::MemoryBuffer::getMemBuffer(Content));
+ const FileEntry *Entry = Files.getFile(Name);
+ assert(Entry != nullptr);
+ return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
+ }
+
+ std::string getRewrittenText(FileID ID) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ Rewrite.getEditBuffer(ID).write(OS);
+ OS.flush();
+ return Result;
+ }
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ FileManager Files;
+ SourceManager Sources;
+ Rewriter Rewrite;
+};
+
+} // end namespace index
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
new file mode 100644
index 000000000000..58f61c3c65b7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
@@ -0,0 +1,931 @@
+//===- USRGeneration.cpp - Routines for USR generation --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/USRGeneration.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::index;
+
+//===----------------------------------------------------------------------===//
+// USR generation.
+//===----------------------------------------------------------------------===//
+
+/// \returns true on error.
+static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
+ const SourceManager &SM, bool IncludeOffset) {
+ if (Loc.isInvalid()) {
+ return true;
+ }
+ Loc = SM.getExpansionLoc(Loc);
+ const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
+ const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
+ if (FE) {
+ OS << llvm::sys::path::filename(FE->getName());
+ } else {
+ // This case really isn't interesting.
+ return true;
+ }
+ if (IncludeOffset) {
+ // Use the offest into the FileID to represent the location. Using
+ // a line/column can cause us to look back at the original source file,
+ // which is expensive.
+ OS << '@' << Decomposed.second;
+ }
+ return false;
+}
+
+namespace {
+class USRGenerator : public ConstDeclVisitor<USRGenerator> {
+ SmallVectorImpl<char> &Buf;
+ llvm::raw_svector_ostream Out;
+ bool IgnoreResults;
+ ASTContext *Context;
+ bool generatedLoc;
+
+ llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
+
+public:
+ explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
+ : Buf(Buf),
+ Out(Buf),
+ IgnoreResults(false),
+ Context(Ctx),
+ generatedLoc(false)
+ {
+ // Add the USR space prefix.
+ Out << getUSRSpacePrefix();
+ }
+
+ bool ignoreResults() const { return IgnoreResults; }
+
+ // Visitation methods from generating USRs from AST elements.
+ void VisitDeclContext(const DeclContext *D);
+ void VisitFieldDecl(const FieldDecl *D);
+ void VisitFunctionDecl(const FunctionDecl *D);
+ void VisitNamedDecl(const NamedDecl *D);
+ void VisitNamespaceDecl(const NamespaceDecl *D);
+ void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
+ void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
+ void VisitClassTemplateDecl(const ClassTemplateDecl *D);
+ void VisitObjCContainerDecl(const ObjCContainerDecl *CD);
+ void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
+ void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
+ void VisitTagDecl(const TagDecl *D);
+ void VisitTypedefDecl(const TypedefDecl *D);
+ void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
+ void VisitVarDecl(const VarDecl *D);
+ void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
+ void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
+
+ void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
+ IgnoreResults = true;
+ }
+
+ void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
+ IgnoreResults = true;
+ }
+
+ void VisitUsingDecl(const UsingDecl *D) {
+ IgnoreResults = true;
+ }
+
+ void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
+ IgnoreResults = true;
+ }
+
+ void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
+ IgnoreResults = true;
+ }
+
+ bool ShouldGenerateLocation(const NamedDecl *D);
+
+ bool isLocal(const NamedDecl *D) {
+ return D->getParentFunctionOrMethod() != nullptr;
+ }
+
+ /// Generate the string component containing the location of the
+ /// declaration.
+ bool GenLoc(const Decl *D, bool IncludeOffset);
+
+ /// String generation methods used both by the visitation methods
+ /// and from other clients that want to directly generate USRs. These
+ /// methods do not construct complete USRs (which incorporate the parents
+ /// of an AST element), but only the fragments concerning the AST element
+ /// itself.
+
+ /// Generate a USR for an Objective-C class.
+ void GenObjCClass(StringRef cls) {
+ generateUSRForObjCClass(cls, Out);
+ }
+
+ /// Generate a USR for an Objective-C class category.
+ void GenObjCCategory(StringRef cls, StringRef cat) {
+ generateUSRForObjCCategory(cls, cat, Out);
+ }
+
+ /// Generate a USR fragment for an Objective-C property.
+ void GenObjCProperty(StringRef prop, bool isClassProp) {
+ generateUSRForObjCProperty(prop, isClassProp, Out);
+ }
+
+ /// Generate a USR for an Objective-C protocol.
+ void GenObjCProtocol(StringRef prot) {
+ generateUSRForObjCProtocol(prot, Out);
+ }
+
+ void VisitType(QualType T);
+ void VisitTemplateParameterList(const TemplateParameterList *Params);
+ void VisitTemplateName(TemplateName Name);
+ void VisitTemplateArgument(const TemplateArgument &Arg);
+
+ /// Emit a Decl's name using NamedDecl::printName() and return true if
+ /// the decl had no name.
+ bool EmitDeclName(const NamedDecl *D);
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Generating USRs from ASTS.
+//===----------------------------------------------------------------------===//
+
+bool USRGenerator::EmitDeclName(const NamedDecl *D) {
+ const unsigned startSize = Buf.size();
+ D->printName(Out);
+ const unsigned endSize = Buf.size();
+ return startSize == endSize;
+}
+
+bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
+ if (D->isExternallyVisible())
+ return false;
+ if (D->getParentFunctionOrMethod())
+ return true;
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isInvalid())
+ return false;
+ const SourceManager &SM = Context->getSourceManager();
+ return !SM.isInSystemHeader(Loc);
+}
+
+void USRGenerator::VisitDeclContext(const DeclContext *DC) {
+ if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
+ Visit(D);
+}
+
+void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
+ // The USR for an ivar declared in a class extension is based on the
+ // ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
+ Visit(ID);
+ else
+ VisitDeclContext(D->getDeclContext());
+ Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
+ if (EmitDeclName(D)) {
+ // Bit fields can be anonymous.
+ IgnoreResults = true;
+ return;
+ }
+}
+
+void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+
+ VisitDeclContext(D->getDeclContext());
+ bool IsTemplate = false;
+ if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
+ IsTemplate = true;
+ Out << "@FT@";
+ VisitTemplateParameterList(FunTmpl->getTemplateParameters());
+ } else
+ Out << "@F@";
+
+ PrintingPolicy Policy(Context->getLangOpts());
+ // Forward references can have different template argument names. Suppress the
+ // template argument names in constructors to make their USR more stable.
+ Policy.SuppressTemplateArgsInCXXConstructors = true;
+ D->getDeclName().print(Out, Policy);
+
+ ASTContext &Ctx = *Context;
+ if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&
+ !D->hasAttr<OverloadableAttr>())
+ return;
+
+ if (const TemplateArgumentList *
+ SpecArgs = D->getTemplateSpecializationArgs()) {
+ Out << '<';
+ for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(SpecArgs->get(I));
+ }
+ Out << '>';
+ }
+
+ // Mangle in type information for the arguments.
+ for (auto PD : D->parameters()) {
+ Out << '#';
+ VisitType(PD->getType());
+ }
+ if (D->isVariadic())
+ Out << '.';
+ if (IsTemplate) {
+ // Function templates can be overloaded by return type, for example:
+ // \code
+ // template <class T> typename T::A foo() {}
+ // template <class T> typename T::B foo() {}
+ // \endcode
+ Out << '#';
+ VisitType(D->getReturnType());
+ }
+ Out << '#';
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isStatic())
+ Out << 'S';
+ if (unsigned quals = MD->getTypeQualifiers())
+ Out << (char)('0' + quals);
+ switch (MD->getRefQualifier()) {
+ case RQ_None: break;
+ case RQ_LValue: Out << '&'; break;
+ case RQ_RValue: Out << "&&"; break;
+ }
+ }
+}
+
+void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ Out << "@";
+
+ if (EmitDeclName(D)) {
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type,
+ // e.g.: void (*f)(void *);
+ // In this case, don't generate a USR.
+ IgnoreResults = true;
+ }
+}
+
+void USRGenerator::VisitVarDecl(const VarDecl *D) {
+ // VarDecls can be declared 'extern' within a function or method body,
+ // but their enclosing DeclContext is the function, not the TU. We need
+ // to check the storage class to correctly generate the USR.
+ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+
+ VisitDeclContext(D->getDeclContext());
+
+ if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
+ Out << "@VT";
+ VisitTemplateParameterList(VarTmpl->getTemplateParameters());
+ } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
+ Out << "@VP";
+ VisitTemplateParameterList(PartialSpec->getTemplateParameters());
+ }
+
+ // Variables always have simple names.
+ StringRef s = D->getName();
+
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ Out << '@' << s;
+
+ // For a template specialization, mangle the template arguments.
+ if (const VarTemplateSpecializationDecl *Spec
+ = dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
+ Out << '>';
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(Args.get(I));
+ }
+ }
+}
+
+void USRGenerator::VisitNonTypeTemplateParmDecl(
+ const NonTypeTemplateParmDecl *D) {
+ GenLoc(D, /*IncludeOffset=*/true);
+}
+
+void USRGenerator::VisitTemplateTemplateParmDecl(
+ const TemplateTemplateParmDecl *D) {
+ GenLoc(D, /*IncludeOffset=*/true);
+}
+
+void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
+ if (D->isAnonymousNamespace()) {
+ Out << "@aN";
+ return;
+ }
+
+ VisitDeclContext(D->getDeclContext());
+ if (!IgnoreResults)
+ Out << "@N@" << D->getName();
+}
+
+void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
+ VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
+ VisitTagDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ if (!IgnoreResults)
+ Out << "@NA@" << D->getName();
+}
+
+void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
+ const DeclContext *container = D->getDeclContext();
+ if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
+ Visit(pd);
+ }
+ else {
+ // The USR for a method declared in a class extension or category is based on
+ // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ const ObjCInterfaceDecl *ID = D->getClassInterface();
+ if (!ID) {
+ IgnoreResults = true;
+ return;
+ }
+ Visit(ID);
+ }
+ // Ideally we would use 'GenObjCMethod', but this is such a hot path
+ // for Objective-C code that we don't want to use
+ // DeclarationName::getAsString().
+ Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
+ << DeclarationName(D->getSelector());
+}
+
+void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) {
+ switch (D->getKind()) {
+ default:
+ llvm_unreachable("Invalid ObjC container.");
+ case Decl::ObjCInterface:
+ case Decl::ObjCImplementation:
+ GenObjCClass(D->getName());
+ break;
+ case Decl::ObjCCategory: {
+ const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
+ const ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ // Specially handle class extensions, which are anonymous categories.
+ // We want to mangle in the location to uniquely distinguish them.
+ if (CD->IsClassExtension()) {
+ Out << "objc(ext)" << ID->getName() << '@';
+ GenLoc(CD, /*IncludeOffset=*/true);
+ }
+ else
+ GenObjCCategory(ID->getName(), CD->getName());
+
+ break;
+ }
+ case Decl::ObjCCategoryImpl: {
+ const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
+ const ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ GenObjCCategory(ID->getName(), CD->getName());
+ break;
+ }
+ case Decl::ObjCProtocol:
+ GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
+ break;
+ }
+}
+
+void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
+ // The USR for a property declared in a class extension or category is based
+ // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
+ Visit(ID);
+ else
+ Visit(cast<Decl>(D->getDeclContext()));
+ GenObjCProperty(D->getName(), D->isClassProperty());
+}
+
+void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
+ if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
+ VisitObjCPropertyDecl(PD);
+ return;
+ }
+
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitTagDecl(const TagDecl *D) {
+ // Add the location of the tag decl to handle resolution across
+ // translation units.
+ if (!isa<EnumDecl>(D) &&
+ ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+
+ D = D->getCanonicalDecl();
+ VisitDeclContext(D->getDeclContext());
+
+ bool AlreadyStarted = false;
+ if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
+ if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Class:
+ case TTK_Struct: Out << "@ST"; break;
+ case TTK_Union: Out << "@UT"; break;
+ case TTK_Enum: llvm_unreachable("enum template");
+ }
+ VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
+ } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Class:
+ case TTK_Struct: Out << "@SP"; break;
+ case TTK_Union: Out << "@UP"; break;
+ case TTK_Enum: llvm_unreachable("enum partial specialization");
+ }
+ VisitTemplateParameterList(PartialSpec->getTemplateParameters());
+ }
+ }
+
+ if (!AlreadyStarted) {
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Class:
+ case TTK_Struct: Out << "@S"; break;
+ case TTK_Union: Out << "@U"; break;
+ case TTK_Enum: Out << "@E"; break;
+ }
+ }
+
+ Out << '@';
+ assert(Buf.size() > 0);
+ const unsigned off = Buf.size() - 1;
+
+ if (EmitDeclName(D)) {
+ if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
+ Buf[off] = 'A';
+ Out << '@' << *TD;
+ }
+ else {
+ if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
+ printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
+ } else {
+ Buf[off] = 'a';
+ if (auto *ED = dyn_cast<EnumDecl>(D)) {
+ // Distinguish USRs of anonymous enums by using their first enumerator.
+ auto enum_range = ED->enumerators();
+ if (enum_range.begin() != enum_range.end()) {
+ Out << '@' << **enum_range.begin();
+ }
+ }
+ }
+ }
+ }
+
+ // For a class template specialization, mangle the template arguments.
+ if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
+ Out << '>';
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(Args.get(I));
+ }
+ }
+}
+
+void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
+ return;
+ const DeclContext *DC = D->getDeclContext();
+ if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
+ Visit(DCN);
+ Out << "@T@";
+ Out << D->getName();
+}
+
+void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
+ GenLoc(D, /*IncludeOffset=*/true);
+}
+
+bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
+ if (generatedLoc)
+ return IgnoreResults;
+ generatedLoc = true;
+
+ // Guard against null declarations in invalid code.
+ if (!D) {
+ IgnoreResults = true;
+ return true;
+ }
+
+ // Use the location of canonical decl.
+ D = D->getCanonicalDecl();
+
+ IgnoreResults =
+ IgnoreResults || printLoc(Out, D->getLocStart(),
+ Context->getSourceManager(), IncludeOffset);
+
+ return IgnoreResults;
+}
+
+void USRGenerator::VisitType(QualType T) {
+ // This method mangles in USR information for types. It can possibly
+ // just reuse the naming-mangling logic used by codegen, although the
+ // requirements for USRs might not be the same.
+ ASTContext &Ctx = *Context;
+
+ do {
+ T = Ctx.getCanonicalType(T);
+ Qualifiers Q = T.getQualifiers();
+ unsigned qVal = 0;
+ if (Q.hasConst())
+ qVal |= 0x1;
+ if (Q.hasVolatile())
+ qVal |= 0x2;
+ if (Q.hasRestrict())
+ qVal |= 0x4;
+ if(qVal)
+ Out << ((char) ('0' + qVal));
+
+ // Mangle in ObjC GC qualifiers?
+
+ if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
+ Out << 'P';
+ T = Expansion->getPattern();
+ }
+
+ if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
+ unsigned char c = '\0';
+ switch (BT->getKind()) {
+ case BuiltinType::Void:
+ c = 'v'; break;
+ case BuiltinType::Bool:
+ c = 'b'; break;
+ case BuiltinType::UChar:
+ c = 'c'; break;
+ case BuiltinType::Char16:
+ c = 'q'; break;
+ case BuiltinType::Char32:
+ c = 'w'; break;
+ case BuiltinType::UShort:
+ c = 's'; break;
+ case BuiltinType::UInt:
+ c = 'i'; break;
+ case BuiltinType::ULong:
+ c = 'l'; break;
+ case BuiltinType::ULongLong:
+ c = 'k'; break;
+ case BuiltinType::UInt128:
+ c = 'j'; break;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ c = 'C'; break;
+ case BuiltinType::SChar:
+ c = 'r'; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ c = 'W'; break;
+ case BuiltinType::Short:
+ c = 'S'; break;
+ case BuiltinType::Int:
+ c = 'I'; break;
+ case BuiltinType::Long:
+ c = 'L'; break;
+ case BuiltinType::LongLong:
+ c = 'K'; break;
+ case BuiltinType::Int128:
+ c = 'J'; break;
+ case BuiltinType::Half:
+ c = 'h'; break;
+ case BuiltinType::Float:
+ c = 'f'; break;
+ case BuiltinType::Double:
+ c = 'd'; break;
+ case BuiltinType::LongDouble:
+ c = 'D'; break;
+ case BuiltinType::Float128:
+ c = 'Q'; break;
+ case BuiltinType::NullPtr:
+ c = 'n'; break;
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ case BuiltinType::Dependent:
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
+ case BuiltinType::OCLSampler:
+ IgnoreResults = true;
+ return;
+ case BuiltinType::ObjCId:
+ c = 'o'; break;
+ case BuiltinType::ObjCClass:
+ c = 'O'; break;
+ case BuiltinType::ObjCSel:
+ c = 'e'; break;
+ }
+ Out << c;
+ return;
+ }
+
+ // If we have already seen this (non-built-in) type, use a substitution
+ // encoding.
+ llvm::DenseMap<const Type *, unsigned>::iterator Substitution
+ = TypeSubstitutions.find(T.getTypePtr());
+ if (Substitution != TypeSubstitutions.end()) {
+ Out << 'S' << Substitution->second << '_';
+ return;
+ } else {
+ // Record this as a substitution.
+ unsigned Number = TypeSubstitutions.size();
+ TypeSubstitutions[T.getTypePtr()] = Number;
+ }
+
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ Out << '*';
+ T = PT->getPointeeType();
+ continue;
+ }
+ if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
+ Out << '*';
+ T = OPT->getPointeeType();
+ continue;
+ }
+ if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
+ Out << "&&";
+ T = RT->getPointeeType();
+ continue;
+ }
+ if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
+ Out << '&';
+ T = RT->getPointeeType();
+ continue;
+ }
+ if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
+ Out << 'F';
+ VisitType(FT->getReturnType());
+ for (const auto &I : FT->param_types())
+ VisitType(I);
+ if (FT->isVariadic())
+ Out << '.';
+ return;
+ }
+ if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
+ Out << 'B';
+ T = BT->getPointeeType();
+ continue;
+ }
+ if (const ComplexType *CT = T->getAs<ComplexType>()) {
+ Out << '<';
+ T = CT->getElementType();
+ continue;
+ }
+ if (const TagType *TT = T->getAs<TagType>()) {
+ Out << '$';
+ VisitTagDecl(TT->getDecl());
+ return;
+ }
+ if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
+ Out << '$';
+ VisitObjCInterfaceDecl(OIT->getDecl());
+ return;
+ }
+ if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
+ Out << 'Q';
+ VisitType(OIT->getBaseType());
+ for (auto *Prot : OIT->getProtocols())
+ VisitObjCProtocolDecl(Prot);
+ return;
+ }
+ if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>()) {
+ Out << '>';
+ VisitTemplateName(Spec->getTemplateName());
+ Out << Spec->getNumArgs();
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ VisitTemplateArgument(Spec->getArg(I));
+ return;
+ }
+ if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
+ Out << '^';
+ // FIXME: Encode the qualifier, don't just print it.
+ PrintingPolicy PO(Ctx.getLangOpts());
+ PO.SuppressTagKeyword = true;
+ PO.SuppressUnwrittenScope = true;
+ PO.ConstantArraySizeAsWritten = false;
+ PO.AnonymousTagLocations = false;
+ DNT->getQualifier()->print(Out, PO);
+ Out << ':' << DNT->getIdentifier()->getName();
+ return;
+ }
+ if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
+ T = InjT->getInjectedSpecializationType();
+ continue;
+ }
+
+ // Unhandled type.
+ Out << ' ';
+ break;
+ } while (true);
+}
+
+void USRGenerator::VisitTemplateParameterList(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return;
+ Out << '>' << Params->size();
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ Out << '#';
+ if (isa<TemplateTypeParmDecl>(*P)) {
+ if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
+ Out<< 'p';
+ Out << 'T';
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ if (NTTP->isParameterPack())
+ Out << 'p';
+ Out << 'N';
+ VisitType(NTTP->getType());
+ continue;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ if (TTP->isParameterPack())
+ Out << 'p';
+ Out << 't';
+ VisitTemplateParameterList(TTP->getTemplateParameters());
+ }
+}
+
+void USRGenerator::VisitTemplateName(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+
+ Visit(Template);
+ return;
+ }
+
+ // FIXME: Visit dependent template names.
+}
+
+void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Declaration:
+ Visit(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::NullPtr:
+ break;
+
+ case TemplateArgument::TemplateExpansion:
+ Out << 'P'; // pack expansion of...
+ // Fall through
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
+ break;
+
+ case TemplateArgument::Expression:
+ // FIXME: Visit expressions.
+ break;
+
+ case TemplateArgument::Pack:
+ Out << 'p' << Arg.pack_size();
+ for (const auto &P : Arg.pack_elements())
+ VisitTemplateArgument(P);
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Integral:
+ Out << 'V';
+ VisitType(Arg.getIntegralType());
+ Out << Arg.getAsIntegral();
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// USR generation functions.
+//===----------------------------------------------------------------------===//
+
+void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) {
+ OS << "objc(cs)" << Cls;
+}
+
+void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
+ raw_ostream &OS) {
+ OS << "objc(cy)" << Cls << '@' << Cat;
+}
+
+void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
+ OS << '@' << Ivar;
+}
+
+void clang::index::generateUSRForObjCMethod(StringRef Sel,
+ bool IsInstanceMethod,
+ raw_ostream &OS) {
+ OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
+}
+
+void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
+ raw_ostream &OS) {
+ OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
+}
+
+void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
+ OS << "objc(pl)" << Prot;
+}
+
+bool clang::index::generateUSRForDecl(const Decl *D,
+ SmallVectorImpl<char> &Buf) {
+ if (!D)
+ return true;
+ // We don't ignore decls with invalid source locations. Implicit decls, like
+ // C++'s operator new function, can have invalid locations but it is fine to
+ // create USRs that can identify them.
+
+ USRGenerator UG(&D->getASTContext(), Buf);
+ UG.Visit(D);
+ return UG.ignoreResults();
+}
+
+bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
+ const SourceManager &SM,
+ SmallVectorImpl<char> &Buf) {
+ // Don't generate USRs for things with invalid locations.
+ if (!MD || MD->getLocation().isInvalid())
+ return true;
+
+ llvm::raw_svector_ostream Out(Buf);
+
+ // Assume that system headers are sane. Don't put source location
+ // information into the USR if the macro comes from a system header.
+ SourceLocation Loc = MD->getLocation();
+ bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc);
+
+ Out << getUSRSpacePrefix();
+ if (ShouldGenerateLocation)
+ printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
+ Out << "@macro@";
+ Out << MD->getName()->getName();
+ return false;
+}