xref: /netbsd-src/external/apache2/llvm/dist/clang/tools/libclang/CXIndexDataConsumer.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "CXIndexDataConsumer.h"
107330f729Sjoerg #include "CIndexDiagnostic.h"
117330f729Sjoerg #include "CXTranslationUnit.h"
127330f729Sjoerg #include "clang/AST/Attr.h"
137330f729Sjoerg #include "clang/AST/DeclCXX.h"
147330f729Sjoerg #include "clang/AST/DeclTemplate.h"
157330f729Sjoerg #include "clang/AST/DeclVisitor.h"
167330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
177330f729Sjoerg 
187330f729Sjoerg using namespace clang;
197330f729Sjoerg using namespace clang::index;
207330f729Sjoerg using namespace cxindex;
217330f729Sjoerg using namespace cxcursor;
227330f729Sjoerg 
237330f729Sjoerg namespace {
247330f729Sjoerg class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
257330f729Sjoerg   CXIndexDataConsumer &DataConsumer;
267330f729Sjoerg   SourceLocation DeclLoc;
277330f729Sjoerg   const DeclContext *LexicalDC;
287330f729Sjoerg 
297330f729Sjoerg public:
IndexingDeclVisitor(CXIndexDataConsumer & dataConsumer,SourceLocation Loc,const DeclContext * lexicalDC)307330f729Sjoerg   IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
317330f729Sjoerg                       const DeclContext *lexicalDC)
327330f729Sjoerg     : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
337330f729Sjoerg 
VisitFunctionDecl(const FunctionDecl * D)347330f729Sjoerg   bool VisitFunctionDecl(const FunctionDecl *D) {
357330f729Sjoerg     DataConsumer.handleFunction(D);
367330f729Sjoerg     return true;
377330f729Sjoerg   }
387330f729Sjoerg 
VisitVarDecl(const VarDecl * D)397330f729Sjoerg   bool VisitVarDecl(const VarDecl *D) {
407330f729Sjoerg     DataConsumer.handleVar(D);
417330f729Sjoerg     return true;
427330f729Sjoerg   }
437330f729Sjoerg 
VisitFieldDecl(const FieldDecl * D)447330f729Sjoerg   bool VisitFieldDecl(const FieldDecl *D) {
457330f729Sjoerg     DataConsumer.handleField(D);
467330f729Sjoerg     return true;
477330f729Sjoerg   }
487330f729Sjoerg 
VisitMSPropertyDecl(const MSPropertyDecl * D)497330f729Sjoerg   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
507330f729Sjoerg     return true;
517330f729Sjoerg   }
527330f729Sjoerg 
VisitEnumConstantDecl(const EnumConstantDecl * D)537330f729Sjoerg   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
547330f729Sjoerg     DataConsumer.handleEnumerator(D);
557330f729Sjoerg     return true;
567330f729Sjoerg   }
577330f729Sjoerg 
VisitTypedefNameDecl(const TypedefNameDecl * D)587330f729Sjoerg   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
597330f729Sjoerg     DataConsumer.handleTypedefName(D);
607330f729Sjoerg     return true;
617330f729Sjoerg   }
627330f729Sjoerg 
VisitTagDecl(const TagDecl * D)637330f729Sjoerg   bool VisitTagDecl(const TagDecl *D) {
647330f729Sjoerg     DataConsumer.handleTagDecl(D);
657330f729Sjoerg     return true;
667330f729Sjoerg   }
677330f729Sjoerg 
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)687330f729Sjoerg   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
697330f729Sjoerg     DataConsumer.handleObjCInterface(D);
707330f729Sjoerg     return true;
717330f729Sjoerg   }
727330f729Sjoerg 
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)737330f729Sjoerg   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
747330f729Sjoerg     DataConsumer.handleObjCProtocol(D);
757330f729Sjoerg     return true;
767330f729Sjoerg   }
777330f729Sjoerg 
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)787330f729Sjoerg   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
797330f729Sjoerg     DataConsumer.handleObjCImplementation(D);
807330f729Sjoerg     return true;
817330f729Sjoerg   }
827330f729Sjoerg 
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)837330f729Sjoerg   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
847330f729Sjoerg     DataConsumer.handleObjCCategory(D);
857330f729Sjoerg     return true;
867330f729Sjoerg   }
877330f729Sjoerg 
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)887330f729Sjoerg   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
897330f729Sjoerg     DataConsumer.handleObjCCategoryImpl(D);
907330f729Sjoerg     return true;
917330f729Sjoerg   }
927330f729Sjoerg 
VisitObjCMethodDecl(const ObjCMethodDecl * D)937330f729Sjoerg   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
947330f729Sjoerg     if (isa<ObjCImplDecl>(LexicalDC) && !D->isThisDeclarationADefinition())
957330f729Sjoerg       DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC);
967330f729Sjoerg     else
977330f729Sjoerg       DataConsumer.handleObjCMethod(D, DeclLoc);
987330f729Sjoerg     return true;
997330f729Sjoerg   }
1007330f729Sjoerg 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)1017330f729Sjoerg   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1027330f729Sjoerg     DataConsumer.handleObjCProperty(D);
1037330f729Sjoerg     return true;
1047330f729Sjoerg   }
1057330f729Sjoerg 
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)1067330f729Sjoerg   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1077330f729Sjoerg     DataConsumer.handleSynthesizedObjCProperty(D);
1087330f729Sjoerg     return true;
1097330f729Sjoerg   }
1107330f729Sjoerg 
VisitNamespaceDecl(const NamespaceDecl * D)1117330f729Sjoerg   bool VisitNamespaceDecl(const NamespaceDecl *D) {
1127330f729Sjoerg     DataConsumer.handleNamespace(D);
1137330f729Sjoerg     return true;
1147330f729Sjoerg   }
1157330f729Sjoerg 
VisitUsingDecl(const UsingDecl * D)1167330f729Sjoerg   bool VisitUsingDecl(const UsingDecl *D) {
1177330f729Sjoerg     return true;
1187330f729Sjoerg   }
1197330f729Sjoerg 
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)1207330f729Sjoerg   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1217330f729Sjoerg     return true;
1227330f729Sjoerg   }
1237330f729Sjoerg 
VisitClassTemplateDecl(const ClassTemplateDecl * D)1247330f729Sjoerg   bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1257330f729Sjoerg     DataConsumer.handleClassTemplate(D);
1267330f729Sjoerg     return true;
1277330f729Sjoerg   }
1287330f729Sjoerg 
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)1297330f729Sjoerg   bool VisitClassTemplateSpecializationDecl(const
1307330f729Sjoerg                                            ClassTemplateSpecializationDecl *D) {
1317330f729Sjoerg     DataConsumer.handleTagDecl(D);
1327330f729Sjoerg     return true;
1337330f729Sjoerg   }
1347330f729Sjoerg 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)1357330f729Sjoerg   bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1367330f729Sjoerg     DataConsumer.handleFunctionTemplate(D);
1377330f729Sjoerg     return true;
1387330f729Sjoerg   }
1397330f729Sjoerg 
VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)1407330f729Sjoerg   bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
1417330f729Sjoerg     DataConsumer.handleTypeAliasTemplate(D);
1427330f729Sjoerg     return true;
1437330f729Sjoerg   }
1447330f729Sjoerg 
VisitImportDecl(const ImportDecl * D)1457330f729Sjoerg   bool VisitImportDecl(const ImportDecl *D) {
1467330f729Sjoerg     DataConsumer.importedModule(D);
1477330f729Sjoerg     return true;
1487330f729Sjoerg   }
1497330f729Sjoerg };
1507330f729Sjoerg 
getSymbolRole(SymbolRoleSet Role)1517330f729Sjoerg CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
1527330f729Sjoerg   // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
1537330f729Sjoerg   return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
1547330f729Sjoerg }
1557330f729Sjoerg }
1567330f729Sjoerg 
handleDeclOccurrence(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,SourceLocation Loc,ASTNodeInfo ASTNode)157*e038c9c4Sjoerg bool CXIndexDataConsumer::handleDeclOccurrence(
1587330f729Sjoerg     const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
1597330f729Sjoerg     SourceLocation Loc, ASTNodeInfo ASTNode) {
1607330f729Sjoerg   Loc = getASTContext().getSourceManager().getFileLoc(Loc);
1617330f729Sjoerg 
1627330f729Sjoerg   if (Roles & (unsigned)SymbolRole::Reference) {
1637330f729Sjoerg     const NamedDecl *ND = dyn_cast<NamedDecl>(D);
1647330f729Sjoerg     if (!ND)
1657330f729Sjoerg       return true;
1667330f729Sjoerg 
1677330f729Sjoerg     if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
1687330f729Sjoerg       if (!ObjCID->isThisDeclarationADefinition() &&
1697330f729Sjoerg           ObjCID->getLocation() == Loc) {
1707330f729Sjoerg         // The libclang API treats this as ObjCClassRef declaration.
1717330f729Sjoerg         IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
1727330f729Sjoerg         return true;
1737330f729Sjoerg       }
1747330f729Sjoerg     }
1757330f729Sjoerg     if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(ASTNode.OrigD)) {
1767330f729Sjoerg       if (!ObjCPD->isThisDeclarationADefinition() &&
1777330f729Sjoerg           ObjCPD->getLocation() == Loc) {
1787330f729Sjoerg         // The libclang API treats this as ObjCProtocolRef declaration.
1797330f729Sjoerg         IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD);
1807330f729Sjoerg         return true;
1817330f729Sjoerg       }
1827330f729Sjoerg     }
1837330f729Sjoerg 
1847330f729Sjoerg     CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
1857330f729Sjoerg     if (Roles & (unsigned)SymbolRole::Implicit) {
1867330f729Sjoerg       Kind = CXIdxEntityRef_Implicit;
1877330f729Sjoerg     }
1887330f729Sjoerg     CXSymbolRole CXRole = getSymbolRole(Roles);
1897330f729Sjoerg 
1907330f729Sjoerg     CXCursor Cursor;
1917330f729Sjoerg     if (ASTNode.OrigE) {
1927330f729Sjoerg       Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
1937330f729Sjoerg                                       cast<Decl>(ASTNode.ContainerDC),
1947330f729Sjoerg                                       getCXTU());
1957330f729Sjoerg     } else {
1967330f729Sjoerg       if (ASTNode.OrigD) {
1977330f729Sjoerg         if (auto *OrigND = dyn_cast<NamedDecl>(ASTNode.OrigD))
1987330f729Sjoerg           Cursor = getRefCursor(OrigND, Loc);
1997330f729Sjoerg         else
2007330f729Sjoerg           Cursor = MakeCXCursor(ASTNode.OrigD, CXTU);
2017330f729Sjoerg       } else {
2027330f729Sjoerg         Cursor = getRefCursor(ND, Loc);
2037330f729Sjoerg       }
2047330f729Sjoerg     }
2057330f729Sjoerg     handleReference(ND, Loc, Cursor,
2067330f729Sjoerg                     dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
2077330f729Sjoerg                     ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole);
2087330f729Sjoerg 
2097330f729Sjoerg   } else {
2107330f729Sjoerg     const DeclContext *LexicalDC = ASTNode.ContainerDC;
2117330f729Sjoerg     if (!LexicalDC) {
2127330f729Sjoerg       for (const auto &SymRel : Relations) {
2137330f729Sjoerg         if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
2147330f729Sjoerg           LexicalDC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
2157330f729Sjoerg       }
2167330f729Sjoerg     }
2177330f729Sjoerg     IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD);
2187330f729Sjoerg   }
2197330f729Sjoerg 
2207330f729Sjoerg   return !shouldAbort();
2217330f729Sjoerg }
2227330f729Sjoerg 
handleModuleOccurrence(const ImportDecl * ImportD,const Module * Mod,SymbolRoleSet Roles,SourceLocation Loc)223*e038c9c4Sjoerg bool CXIndexDataConsumer::handleModuleOccurrence(const ImportDecl *ImportD,
2247330f729Sjoerg                                                  const Module *Mod,
2257330f729Sjoerg                                                  SymbolRoleSet Roles,
2267330f729Sjoerg                                                  SourceLocation Loc) {
2277330f729Sjoerg   if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
2287330f729Sjoerg     IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
2297330f729Sjoerg   return !shouldAbort();
2307330f729Sjoerg }
2317330f729Sjoerg 
finish()2327330f729Sjoerg void CXIndexDataConsumer::finish() {
2337330f729Sjoerg   indexDiagnostics();
2347330f729Sjoerg }
2357330f729Sjoerg 
2367330f729Sjoerg 
ObjCProtocolListInfo(const ObjCProtocolList & ProtList,CXIndexDataConsumer & IdxCtx,ScratchAlloc & SA)2377330f729Sjoerg CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
2387330f729Sjoerg                                     const ObjCProtocolList &ProtList,
2397330f729Sjoerg                                     CXIndexDataConsumer &IdxCtx,
2407330f729Sjoerg                                     ScratchAlloc &SA) {
2417330f729Sjoerg   ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
2427330f729Sjoerg   for (ObjCInterfaceDecl::protocol_iterator
2437330f729Sjoerg          I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
2447330f729Sjoerg     SourceLocation Loc = *LI;
2457330f729Sjoerg     ObjCProtocolDecl *PD = *I;
2467330f729Sjoerg     ProtEntities.push_back(EntityInfo());
2477330f729Sjoerg     IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
2487330f729Sjoerg     CXIdxObjCProtocolRefInfo ProtInfo = { nullptr,
2497330f729Sjoerg                                 MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU),
2507330f729Sjoerg                                 IdxCtx.getIndexLoc(Loc) };
2517330f729Sjoerg     ProtInfos.push_back(ProtInfo);
2527330f729Sjoerg 
2537330f729Sjoerg     if (IdxCtx.shouldSuppressRefs())
2547330f729Sjoerg       IdxCtx.markEntityOccurrenceInFile(PD, Loc);
2557330f729Sjoerg   }
2567330f729Sjoerg 
2577330f729Sjoerg   for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
2587330f729Sjoerg     ProtInfos[i].protocol = &ProtEntities[i];
2597330f729Sjoerg 
2607330f729Sjoerg   for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
2617330f729Sjoerg     Prots.push_back(&ProtInfos[i]);
2627330f729Sjoerg }
2637330f729Sjoerg 
2647330f729Sjoerg 
IBOutletCollectionInfo(const IBOutletCollectionInfo & other)2657330f729Sjoerg IBOutletCollectionInfo::IBOutletCollectionInfo(
2667330f729Sjoerg                                           const IBOutletCollectionInfo &other)
2677330f729Sjoerg   : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
2687330f729Sjoerg 
2697330f729Sjoerg   IBCollInfo.attrInfo = this;
2707330f729Sjoerg   IBCollInfo.classCursor = other.IBCollInfo.classCursor;
2717330f729Sjoerg   IBCollInfo.classLoc = other.IBCollInfo.classLoc;
2727330f729Sjoerg   if (other.IBCollInfo.objcClass) {
2737330f729Sjoerg     ClassInfo = other.ClassInfo;
2747330f729Sjoerg     IBCollInfo.objcClass = &ClassInfo;
2757330f729Sjoerg   } else
2767330f729Sjoerg     IBCollInfo.objcClass = nullptr;
2777330f729Sjoerg }
2787330f729Sjoerg 
AttrListInfo(const Decl * D,CXIndexDataConsumer & IdxCtx)2797330f729Sjoerg AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
2807330f729Sjoerg   : SA(IdxCtx), ref_cnt(0) {
2817330f729Sjoerg 
2827330f729Sjoerg   if (!D->hasAttrs())
2837330f729Sjoerg     return;
2847330f729Sjoerg 
2857330f729Sjoerg   for (const auto *A : D->attrs()) {
2867330f729Sjoerg     CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU);
2877330f729Sjoerg     CXIdxLoc Loc =  IdxCtx.getIndexLoc(A->getLocation());
2887330f729Sjoerg     switch (C.kind) {
2897330f729Sjoerg     default:
2907330f729Sjoerg       Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
2917330f729Sjoerg       break;
2927330f729Sjoerg     case CXCursor_IBActionAttr:
2937330f729Sjoerg       Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
2947330f729Sjoerg       break;
2957330f729Sjoerg     case CXCursor_IBOutletAttr:
2967330f729Sjoerg       Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
2977330f729Sjoerg       break;
2987330f729Sjoerg     case CXCursor_IBOutletCollectionAttr:
2997330f729Sjoerg       IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
3007330f729Sjoerg       break;
3017330f729Sjoerg     }
3027330f729Sjoerg   }
3037330f729Sjoerg 
3047330f729Sjoerg   for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
3057330f729Sjoerg     IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
3067330f729Sjoerg     CXAttrs.push_back(&IBInfo);
3077330f729Sjoerg 
3087330f729Sjoerg     const IBOutletCollectionAttr *
3097330f729Sjoerg       IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
3107330f729Sjoerg     SourceLocation InterfaceLocStart =
3117330f729Sjoerg         IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
3127330f729Sjoerg     IBInfo.IBCollInfo.attrInfo = &IBInfo;
3137330f729Sjoerg     IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart);
3147330f729Sjoerg     IBInfo.IBCollInfo.objcClass = nullptr;
3157330f729Sjoerg     IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
3167330f729Sjoerg     QualType Ty = IBAttr->getInterface();
3177330f729Sjoerg     if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) {
3187330f729Sjoerg       if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) {
3197330f729Sjoerg         IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
3207330f729Sjoerg         IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
3217330f729Sjoerg         IBInfo.IBCollInfo.classCursor =
3227330f729Sjoerg             MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU);
3237330f729Sjoerg       }
3247330f729Sjoerg     }
3257330f729Sjoerg   }
3267330f729Sjoerg 
3277330f729Sjoerg   for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
3287330f729Sjoerg     CXAttrs.push_back(&Attrs[i]);
3297330f729Sjoerg }
3307330f729Sjoerg 
3317330f729Sjoerg IntrusiveRefCntPtr<AttrListInfo>
create(const Decl * D,CXIndexDataConsumer & IdxCtx)3327330f729Sjoerg AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
3337330f729Sjoerg   ScratchAlloc SA(IdxCtx);
3347330f729Sjoerg   AttrListInfo *attrs = SA.allocate<AttrListInfo>();
3357330f729Sjoerg   return new (attrs) AttrListInfo(D, IdxCtx);
3367330f729Sjoerg }
3377330f729Sjoerg 
CXXBasesListInfo(const CXXRecordDecl * D,CXIndexDataConsumer & IdxCtx,ScratchAlloc & SA)3387330f729Sjoerg CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
3397330f729Sjoerg                                    CXIndexDataConsumer &IdxCtx,
3407330f729Sjoerg                                    ScratchAlloc &SA) {
3417330f729Sjoerg   for (const auto &Base : D->bases()) {
3427330f729Sjoerg     BaseEntities.push_back(EntityInfo());
3437330f729Sjoerg     const NamedDecl *BaseD = nullptr;
3447330f729Sjoerg     QualType T = Base.getType();
3457330f729Sjoerg     SourceLocation Loc = getBaseLoc(Base);
3467330f729Sjoerg 
3477330f729Sjoerg     if (const TypedefType *TDT = T->getAs<TypedefType>()) {
3487330f729Sjoerg       BaseD = TDT->getDecl();
3497330f729Sjoerg     } else if (const TemplateSpecializationType *
3507330f729Sjoerg           TST = T->getAs<TemplateSpecializationType>()) {
3517330f729Sjoerg       BaseD = TST->getTemplateName().getAsTemplateDecl();
3527330f729Sjoerg     } else if (const RecordType *RT = T->getAs<RecordType>()) {
3537330f729Sjoerg       BaseD = RT->getDecl();
3547330f729Sjoerg     }
3557330f729Sjoerg 
3567330f729Sjoerg     if (BaseD)
3577330f729Sjoerg       IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA);
3587330f729Sjoerg     CXIdxBaseClassInfo BaseInfo = { nullptr,
3597330f729Sjoerg                          MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU),
3607330f729Sjoerg                          IdxCtx.getIndexLoc(Loc) };
3617330f729Sjoerg     BaseInfos.push_back(BaseInfo);
3627330f729Sjoerg   }
3637330f729Sjoerg 
3647330f729Sjoerg   for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
3657330f729Sjoerg     if (BaseEntities[i].name && BaseEntities[i].USR)
3667330f729Sjoerg       BaseInfos[i].base = &BaseEntities[i];
3677330f729Sjoerg   }
3687330f729Sjoerg 
3697330f729Sjoerg   for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
3707330f729Sjoerg     CXBases.push_back(&BaseInfos[i]);
3717330f729Sjoerg }
3727330f729Sjoerg 
getBaseLoc(const CXXBaseSpecifier & Base) const3737330f729Sjoerg SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
3747330f729Sjoerg                                            const CXXBaseSpecifier &Base) const {
3757330f729Sjoerg   SourceLocation Loc = Base.getSourceRange().getBegin();
3767330f729Sjoerg   TypeLoc TL;
3777330f729Sjoerg   if (Base.getTypeSourceInfo())
3787330f729Sjoerg     TL = Base.getTypeSourceInfo()->getTypeLoc();
3797330f729Sjoerg   if (TL.isNull())
3807330f729Sjoerg     return Loc;
3817330f729Sjoerg 
3827330f729Sjoerg   if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
3837330f729Sjoerg     TL = QL.getUnqualifiedLoc();
3847330f729Sjoerg 
3857330f729Sjoerg   if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
3867330f729Sjoerg     return EL.getNamedTypeLoc().getBeginLoc();
3877330f729Sjoerg   if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
3887330f729Sjoerg     return DL.getNameLoc();
3897330f729Sjoerg   if (DependentTemplateSpecializationTypeLoc DTL =
3907330f729Sjoerg           TL.getAs<DependentTemplateSpecializationTypeLoc>())
3917330f729Sjoerg     return DTL.getTemplateNameLoc();
3927330f729Sjoerg 
3937330f729Sjoerg   return Loc;
3947330f729Sjoerg }
3957330f729Sjoerg 
toCStr(StringRef Str)3967330f729Sjoerg const char *ScratchAlloc::toCStr(StringRef Str) {
3977330f729Sjoerg   if (Str.empty())
3987330f729Sjoerg     return "";
3997330f729Sjoerg   if (Str.data()[Str.size()] == '\0')
4007330f729Sjoerg     return Str.data();
4017330f729Sjoerg   return copyCStr(Str);
4027330f729Sjoerg }
4037330f729Sjoerg 
copyCStr(StringRef Str)4047330f729Sjoerg const char *ScratchAlloc::copyCStr(StringRef Str) {
4057330f729Sjoerg   char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1);
4067330f729Sjoerg   std::uninitialized_copy(Str.begin(), Str.end(), buf);
4077330f729Sjoerg   buf[Str.size()] = '\0';
4087330f729Sjoerg   return buf;
4097330f729Sjoerg }
4107330f729Sjoerg 
setASTContext(ASTContext & ctx)4117330f729Sjoerg void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
4127330f729Sjoerg   Ctx = &ctx;
4137330f729Sjoerg   cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
4147330f729Sjoerg }
4157330f729Sjoerg 
setPreprocessor(std::shared_ptr<Preprocessor> PP)4167330f729Sjoerg void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
4177330f729Sjoerg   cxtu::getASTUnit(CXTU)->setPreprocessor(std::move(PP));
4187330f729Sjoerg }
4197330f729Sjoerg 
isFunctionLocalDecl(const Decl * D)4207330f729Sjoerg bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
4217330f729Sjoerg   assert(D);
4227330f729Sjoerg 
4237330f729Sjoerg   if (!D->getParentFunctionOrMethod())
4247330f729Sjoerg     return false;
4257330f729Sjoerg 
4267330f729Sjoerg   if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
4277330f729Sjoerg     switch (ND->getFormalLinkage()) {
4287330f729Sjoerg     case NoLinkage:
4297330f729Sjoerg     case InternalLinkage:
4307330f729Sjoerg       return true;
4317330f729Sjoerg     case VisibleNoLinkage:
4327330f729Sjoerg     case ModuleInternalLinkage:
4337330f729Sjoerg     case UniqueExternalLinkage:
4347330f729Sjoerg       llvm_unreachable("Not a sema linkage");
4357330f729Sjoerg     case ModuleLinkage:
4367330f729Sjoerg     case ExternalLinkage:
4377330f729Sjoerg       return false;
4387330f729Sjoerg     }
4397330f729Sjoerg   }
4407330f729Sjoerg 
4417330f729Sjoerg   return true;
4427330f729Sjoerg }
4437330f729Sjoerg 
shouldAbort()4447330f729Sjoerg bool CXIndexDataConsumer::shouldAbort() {
4457330f729Sjoerg   if (!CB.abortQuery)
4467330f729Sjoerg     return false;
4477330f729Sjoerg   return CB.abortQuery(ClientData, nullptr);
4487330f729Sjoerg }
4497330f729Sjoerg 
enteredMainFile(const FileEntry * File)4507330f729Sjoerg void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
4517330f729Sjoerg   if (File && CB.enteredMainFile) {
4527330f729Sjoerg     CXIdxClientFile idxFile =
4537330f729Sjoerg       CB.enteredMainFile(ClientData,
4547330f729Sjoerg                          static_cast<CXFile>(const_cast<FileEntry *>(File)),
4557330f729Sjoerg                          nullptr);
4567330f729Sjoerg     FileMap[File] = idxFile;
4577330f729Sjoerg   }
4587330f729Sjoerg }
4597330f729Sjoerg 
ppIncludedFile(SourceLocation hashLoc,StringRef filename,const FileEntry * File,bool isImport,bool isAngled,bool isModuleImport)4607330f729Sjoerg void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
4617330f729Sjoerg                                      StringRef filename,
4627330f729Sjoerg                                      const FileEntry *File,
4637330f729Sjoerg                                      bool isImport, bool isAngled,
4647330f729Sjoerg                                      bool isModuleImport) {
4657330f729Sjoerg   if (!CB.ppIncludedFile)
4667330f729Sjoerg     return;
4677330f729Sjoerg 
4687330f729Sjoerg   ScratchAlloc SA(*this);
4697330f729Sjoerg   CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
4707330f729Sjoerg                                  SA.toCStr(filename),
4717330f729Sjoerg                                  static_cast<CXFile>(
4727330f729Sjoerg                                    const_cast<FileEntry *>(File)),
4737330f729Sjoerg                                  isImport, isAngled, isModuleImport };
4747330f729Sjoerg   CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
4757330f729Sjoerg   FileMap[File] = idxFile;
4767330f729Sjoerg }
4777330f729Sjoerg 
importedModule(const ImportDecl * ImportD)4787330f729Sjoerg void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
4797330f729Sjoerg   if (!CB.importedASTFile)
4807330f729Sjoerg     return;
4817330f729Sjoerg 
4827330f729Sjoerg   Module *Mod = ImportD->getImportedModule();
4837330f729Sjoerg   if (!Mod)
4847330f729Sjoerg     return;
4857330f729Sjoerg 
4867330f729Sjoerg   // If the imported module is part of the top-level module that we're
4877330f729Sjoerg   // indexing, it doesn't correspond to an imported AST file.
4887330f729Sjoerg   // FIXME: This assumes that AST files and top-level modules directly
4897330f729Sjoerg   // correspond, which is unlikely to remain true forever.
4907330f729Sjoerg   if (Module *SrcMod = ImportD->getImportedOwningModule())
4917330f729Sjoerg     if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
4927330f729Sjoerg       return;
4937330f729Sjoerg 
494*e038c9c4Sjoerg   FileEntry *FE = nullptr;
495*e038c9c4Sjoerg   if (auto File = Mod->getASTFile())
496*e038c9c4Sjoerg     FE = const_cast<FileEntry *>(&File->getFileEntry());
497*e038c9c4Sjoerg   CXIdxImportedASTFileInfo Info = {static_cast<CXFile>(FE), Mod,
4987330f729Sjoerg                                    getIndexLoc(ImportD->getLocation()),
499*e038c9c4Sjoerg                                    ImportD->isImplicit()};
5007330f729Sjoerg   CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
5017330f729Sjoerg   (void)astFile;
5027330f729Sjoerg }
5037330f729Sjoerg 
importedPCH(const FileEntry * File)5047330f729Sjoerg void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
5057330f729Sjoerg   if (!CB.importedASTFile)
5067330f729Sjoerg     return;
5077330f729Sjoerg 
5087330f729Sjoerg   CXIdxImportedASTFileInfo Info = {
5097330f729Sjoerg                                     static_cast<CXFile>(
5107330f729Sjoerg                                       const_cast<FileEntry *>(File)),
5117330f729Sjoerg                                     /*module=*/nullptr,
5127330f729Sjoerg                                     getIndexLoc(SourceLocation()),
5137330f729Sjoerg                                     /*isImplicit=*/false
5147330f729Sjoerg                                   };
5157330f729Sjoerg   CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
5167330f729Sjoerg   (void)astFile;
5177330f729Sjoerg }
5187330f729Sjoerg 
startedTranslationUnit()5197330f729Sjoerg void CXIndexDataConsumer::startedTranslationUnit() {
5207330f729Sjoerg   CXIdxClientContainer idxCont = nullptr;
5217330f729Sjoerg   if (CB.startedTranslationUnit)
5227330f729Sjoerg     idxCont = CB.startedTranslationUnit(ClientData, nullptr);
5237330f729Sjoerg   addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
5247330f729Sjoerg }
5257330f729Sjoerg 
indexDiagnostics()5267330f729Sjoerg void CXIndexDataConsumer::indexDiagnostics() {
5277330f729Sjoerg   if (!hasDiagnosticCallback())
5287330f729Sjoerg     return;
5297330f729Sjoerg 
5307330f729Sjoerg   CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
5317330f729Sjoerg   handleDiagnosticSet(DiagSet);
5327330f729Sjoerg }
5337330f729Sjoerg 
handleDiagnosticSet(CXDiagnostic CXDiagSet)5347330f729Sjoerg void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
5357330f729Sjoerg   if (!CB.diagnostic)
5367330f729Sjoerg     return;
5377330f729Sjoerg 
5387330f729Sjoerg   CB.diagnostic(ClientData, CXDiagSet, nullptr);
5397330f729Sjoerg }
5407330f729Sjoerg 
handleDecl(const NamedDecl * D,SourceLocation Loc,CXCursor Cursor,DeclInfo & DInfo,const DeclContext * LexicalDC,const DeclContext * SemaDC)5417330f729Sjoerg bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
5427330f729Sjoerg                                  SourceLocation Loc, CXCursor Cursor,
5437330f729Sjoerg                                  DeclInfo &DInfo,
5447330f729Sjoerg                                  const DeclContext *LexicalDC,
5457330f729Sjoerg                                  const DeclContext *SemaDC) {
5467330f729Sjoerg   if (!CB.indexDeclaration || !D)
5477330f729Sjoerg     return false;
5487330f729Sjoerg   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
5497330f729Sjoerg     return false;
5507330f729Sjoerg 
5517330f729Sjoerg   ScratchAlloc SA(*this);
5527330f729Sjoerg   getEntityInfo(D, DInfo.EntInfo, SA);
5537330f729Sjoerg   if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
5547330f729Sjoerg       || Loc.isInvalid())
5557330f729Sjoerg     return false;
5567330f729Sjoerg 
5577330f729Sjoerg   if (!LexicalDC)
5587330f729Sjoerg     LexicalDC = D->getLexicalDeclContext();
5597330f729Sjoerg 
5607330f729Sjoerg   if (shouldSuppressRefs())
5617330f729Sjoerg     markEntityOccurrenceInFile(D, Loc);
5627330f729Sjoerg 
5637330f729Sjoerg   DInfo.entityInfo = &DInfo.EntInfo;
5647330f729Sjoerg   DInfo.cursor = Cursor;
5657330f729Sjoerg   DInfo.loc = getIndexLoc(Loc);
5667330f729Sjoerg   DInfo.isImplicit = D->isImplicit();
5677330f729Sjoerg 
5687330f729Sjoerg   DInfo.attributes = DInfo.EntInfo.attributes;
5697330f729Sjoerg   DInfo.numAttributes = DInfo.EntInfo.numAttributes;
5707330f729Sjoerg 
5717330f729Sjoerg   if (!SemaDC)
5727330f729Sjoerg     SemaDC = D->getDeclContext();
5737330f729Sjoerg   getContainerInfo(SemaDC, DInfo.SemanticContainer);
5747330f729Sjoerg   DInfo.semanticContainer = &DInfo.SemanticContainer;
5757330f729Sjoerg 
5767330f729Sjoerg   if (LexicalDC == SemaDC) {
5777330f729Sjoerg     DInfo.lexicalContainer = &DInfo.SemanticContainer;
5787330f729Sjoerg   } else if (isTemplateImplicitInstantiation(D)) {
5797330f729Sjoerg     // Implicit instantiations have the lexical context of where they were
5807330f729Sjoerg     // instantiated first. We choose instead the semantic context because:
5817330f729Sjoerg     // 1) at the time that we see the instantiation we have not seen the
5827330f729Sjoerg     //   function where it occurred yet.
5837330f729Sjoerg     // 2) the lexical context of the first instantiation is not useful
5847330f729Sjoerg     //   information anyway.
5857330f729Sjoerg     DInfo.lexicalContainer = &DInfo.SemanticContainer;
5867330f729Sjoerg   } else {
5877330f729Sjoerg     getContainerInfo(LexicalDC, DInfo.LexicalContainer);
5887330f729Sjoerg     DInfo.lexicalContainer = &DInfo.LexicalContainer;
5897330f729Sjoerg   }
5907330f729Sjoerg 
5917330f729Sjoerg   if (DInfo.isContainer) {
5927330f729Sjoerg     getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
5937330f729Sjoerg     DInfo.declAsContainer = &DInfo.DeclAsContainer;
5947330f729Sjoerg   }
5957330f729Sjoerg 
5967330f729Sjoerg   CB.indexDeclaration(ClientData, &DInfo);
5977330f729Sjoerg   return true;
5987330f729Sjoerg }
5997330f729Sjoerg 
handleObjCContainer(const ObjCContainerDecl * D,SourceLocation Loc,CXCursor Cursor,ObjCContainerDeclInfo & ContDInfo)6007330f729Sjoerg bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
6017330f729Sjoerg                                           SourceLocation Loc, CXCursor Cursor,
6027330f729Sjoerg                                           ObjCContainerDeclInfo &ContDInfo) {
6037330f729Sjoerg   ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
6047330f729Sjoerg   return handleDecl(D, Loc, Cursor, ContDInfo);
6057330f729Sjoerg }
6067330f729Sjoerg 
handleFunction(const FunctionDecl * D)6077330f729Sjoerg bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
6087330f729Sjoerg   bool isDef = D->isThisDeclarationADefinition();
6097330f729Sjoerg   bool isContainer = isDef;
6107330f729Sjoerg   bool isSkipped = false;
6117330f729Sjoerg   if (D->hasSkippedBody()) {
6127330f729Sjoerg     isSkipped = true;
6137330f729Sjoerg     isDef = true;
6147330f729Sjoerg     isContainer = false;
6157330f729Sjoerg   }
6167330f729Sjoerg 
6177330f729Sjoerg   DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer);
6187330f729Sjoerg   if (isSkipped)
6197330f729Sjoerg     DInfo.flags |= CXIdxDeclFlag_Skipped;
6207330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6217330f729Sjoerg }
6227330f729Sjoerg 
handleVar(const VarDecl * D)6237330f729Sjoerg bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
6247330f729Sjoerg   DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
6257330f729Sjoerg                  /*isContainer=*/false);
6267330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6277330f729Sjoerg }
6287330f729Sjoerg 
handleField(const FieldDecl * D)6297330f729Sjoerg bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
6307330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
6317330f729Sjoerg                  /*isContainer=*/false);
6327330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6337330f729Sjoerg }
6347330f729Sjoerg 
handleEnumerator(const EnumConstantDecl * D)6357330f729Sjoerg bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
6367330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
6377330f729Sjoerg                  /*isContainer=*/false);
6387330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6397330f729Sjoerg }
6407330f729Sjoerg 
handleTagDecl(const TagDecl * D)6417330f729Sjoerg bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
6427330f729Sjoerg   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
6437330f729Sjoerg     return handleCXXRecordDecl(CXXRD, D);
6447330f729Sjoerg 
6457330f729Sjoerg   DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
6467330f729Sjoerg                  D->isThisDeclarationADefinition());
6477330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6487330f729Sjoerg }
6497330f729Sjoerg 
handleTypedefName(const TypedefNameDecl * D)6507330f729Sjoerg bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
6517330f729Sjoerg   DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
6527330f729Sjoerg                  /*isContainer=*/false);
6537330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6547330f729Sjoerg }
6557330f729Sjoerg 
handleObjCInterface(const ObjCInterfaceDecl * D)6567330f729Sjoerg bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
6577330f729Sjoerg   // For @class forward declarations, suppress them the same way as references.
6587330f729Sjoerg   if (!D->isThisDeclarationADefinition()) {
6597330f729Sjoerg     if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
6607330f729Sjoerg       return false; // already occurred.
6617330f729Sjoerg 
6627330f729Sjoerg     // FIXME: This seems like the wrong definition for redeclaration.
6637330f729Sjoerg     bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
6647330f729Sjoerg     ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
6657330f729Sjoerg                                     /*isImplementation=*/false);
6667330f729Sjoerg     return handleObjCContainer(D, D->getLocation(),
6677330f729Sjoerg                                MakeCursorObjCClassRef(D, D->getLocation(),
6687330f729Sjoerg                                                       CXTU),
6697330f729Sjoerg                                ContDInfo);
6707330f729Sjoerg   }
6717330f729Sjoerg 
6727330f729Sjoerg   ScratchAlloc SA(*this);
6737330f729Sjoerg 
6747330f729Sjoerg   CXIdxBaseClassInfo BaseClass;
6757330f729Sjoerg   EntityInfo BaseEntity;
6767330f729Sjoerg   BaseClass.cursor = clang_getNullCursor();
6777330f729Sjoerg   if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
6787330f729Sjoerg     getEntityInfo(SuperD, BaseEntity, SA);
6797330f729Sjoerg     SourceLocation SuperLoc = D->getSuperClassLoc();
6807330f729Sjoerg     BaseClass.base = &BaseEntity;
6817330f729Sjoerg     BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU);
6827330f729Sjoerg     BaseClass.loc = getIndexLoc(SuperLoc);
6837330f729Sjoerg 
6847330f729Sjoerg     if (shouldSuppressRefs())
6857330f729Sjoerg       markEntityOccurrenceInFile(SuperD, SuperLoc);
6867330f729Sjoerg   }
6877330f729Sjoerg 
6887330f729Sjoerg   ObjCProtocolList EmptyProtoList;
6897330f729Sjoerg   ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()
6907330f729Sjoerg                                   ? D->getReferencedProtocols()
6917330f729Sjoerg                                   : EmptyProtoList,
6927330f729Sjoerg                                 *this, SA);
6937330f729Sjoerg 
6947330f729Sjoerg   ObjCInterfaceDeclInfo InterInfo(D);
6957330f729Sjoerg   InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
6967330f729Sjoerg   InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo;
6977330f729Sjoerg   InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass
6987330f729Sjoerg                                                              : nullptr;
6997330f729Sjoerg   InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
7007330f729Sjoerg 
7017330f729Sjoerg   return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
7027330f729Sjoerg }
7037330f729Sjoerg 
handleObjCImplementation(const ObjCImplementationDecl * D)7047330f729Sjoerg bool CXIndexDataConsumer::handleObjCImplementation(
7057330f729Sjoerg                                               const ObjCImplementationDecl *D) {
7067330f729Sjoerg   ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
7077330f729Sjoerg                       /*isRedeclaration=*/true,
7087330f729Sjoerg                       /*isImplementation=*/true);
7097330f729Sjoerg   return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
7107330f729Sjoerg }
7117330f729Sjoerg 
handleObjCProtocol(const ObjCProtocolDecl * D)7127330f729Sjoerg bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
7137330f729Sjoerg   if (!D->isThisDeclarationADefinition()) {
7147330f729Sjoerg     if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
7157330f729Sjoerg       return false; // already occurred.
7167330f729Sjoerg 
7177330f729Sjoerg     // FIXME: This seems like the wrong definition for redeclaration.
7187330f729Sjoerg     bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
7197330f729Sjoerg     ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
7207330f729Sjoerg                                     isRedeclaration,
7217330f729Sjoerg                                     /*isImplementation=*/false);
7227330f729Sjoerg     return handleObjCContainer(D, D->getLocation(),
7237330f729Sjoerg                                MakeCursorObjCProtocolRef(D, D->getLocation(),
7247330f729Sjoerg                                                          CXTU),
7257330f729Sjoerg                                ContDInfo);
7267330f729Sjoerg   }
7277330f729Sjoerg 
7287330f729Sjoerg   ScratchAlloc SA(*this);
7297330f729Sjoerg   ObjCProtocolList EmptyProtoList;
7307330f729Sjoerg   ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition()
7317330f729Sjoerg                                       ? D->getReferencedProtocols()
7327330f729Sjoerg                                       : EmptyProtoList,
7337330f729Sjoerg                                     *this, SA);
7347330f729Sjoerg 
7357330f729Sjoerg   ObjCProtocolDeclInfo ProtInfo(D);
7367330f729Sjoerg   ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
7377330f729Sjoerg 
7387330f729Sjoerg   return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
7397330f729Sjoerg }
7407330f729Sjoerg 
handleObjCCategory(const ObjCCategoryDecl * D)7417330f729Sjoerg bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
7427330f729Sjoerg   ScratchAlloc SA(*this);
7437330f729Sjoerg 
7447330f729Sjoerg   ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
7457330f729Sjoerg   EntityInfo ClassEntity;
7467330f729Sjoerg   const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
7477330f729Sjoerg   SourceLocation ClassLoc = D->getLocation();
7487330f729Sjoerg   SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
7497330f729Sjoerg                                                      : D->getCategoryNameLoc();
7507330f729Sjoerg   getEntityInfo(IFaceD, ClassEntity, SA);
7517330f729Sjoerg 
7527330f729Sjoerg   if (shouldSuppressRefs())
7537330f729Sjoerg     markEntityOccurrenceInFile(IFaceD, ClassLoc);
7547330f729Sjoerg 
7557330f729Sjoerg   ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
7567330f729Sjoerg 
7577330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
7587330f729Sjoerg   if (IFaceD) {
7597330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
7607330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.classCursor =
7617330f729Sjoerg         MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
7627330f729Sjoerg   } else {
7637330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
7647330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
7657330f729Sjoerg   }
7667330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
7677330f729Sjoerg   CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
7687330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo;
7697330f729Sjoerg 
7707330f729Sjoerg   return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
7717330f729Sjoerg }
7727330f729Sjoerg 
handleObjCCategoryImpl(const ObjCCategoryImplDecl * D)7737330f729Sjoerg bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
7747330f729Sjoerg   ScratchAlloc SA(*this);
7757330f729Sjoerg 
7767330f729Sjoerg   const ObjCCategoryDecl *CatD = D->getCategoryDecl();
7777330f729Sjoerg   ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
7787330f729Sjoerg   EntityInfo ClassEntity;
7797330f729Sjoerg   const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
7807330f729Sjoerg   SourceLocation ClassLoc = D->getLocation();
7817330f729Sjoerg   SourceLocation CategoryLoc = D->getCategoryNameLoc();
7827330f729Sjoerg   getEntityInfo(IFaceD, ClassEntity, SA);
7837330f729Sjoerg 
7847330f729Sjoerg   if (shouldSuppressRefs())
7857330f729Sjoerg     markEntityOccurrenceInFile(IFaceD, ClassLoc);
7867330f729Sjoerg 
7877330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
7887330f729Sjoerg   if (IFaceD) {
7897330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
7907330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.classCursor =
7917330f729Sjoerg         MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
7927330f729Sjoerg   } else {
7937330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
7947330f729Sjoerg     CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
7957330f729Sjoerg   }
7967330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
7977330f729Sjoerg   CatDInfo.ObjCCatDeclInfo.protocols = nullptr;
7987330f729Sjoerg 
7997330f729Sjoerg   return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
8007330f729Sjoerg }
8017330f729Sjoerg 
handleObjCMethod(const ObjCMethodDecl * D,SourceLocation Loc)8027330f729Sjoerg bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D,
8037330f729Sjoerg                                            SourceLocation Loc) {
8047330f729Sjoerg   bool isDef = D->isThisDeclarationADefinition();
8057330f729Sjoerg   bool isContainer = isDef;
8067330f729Sjoerg   bool isSkipped = false;
8077330f729Sjoerg   if (D->hasSkippedBody()) {
8087330f729Sjoerg     isSkipped = true;
8097330f729Sjoerg     isDef = true;
8107330f729Sjoerg     isContainer = false;
8117330f729Sjoerg   }
8127330f729Sjoerg 
8137330f729Sjoerg   DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer);
8147330f729Sjoerg   if (isSkipped)
8157330f729Sjoerg     DInfo.flags |= CXIdxDeclFlag_Skipped;
8167330f729Sjoerg   return handleDecl(D, Loc, getCursor(D), DInfo);
8177330f729Sjoerg }
8187330f729Sjoerg 
handleSynthesizedObjCProperty(const ObjCPropertyImplDecl * D)8197330f729Sjoerg bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
8207330f729Sjoerg                                                 const ObjCPropertyImplDecl *D) {
8217330f729Sjoerg   ObjCPropertyDecl *PD = D->getPropertyDecl();
8227330f729Sjoerg   auto *DC = D->getDeclContext();
8237330f729Sjoerg   return handleReference(PD, D->getLocation(), getCursor(D),
8247330f729Sjoerg                          dyn_cast<NamedDecl>(DC), DC);
8257330f729Sjoerg }
8267330f729Sjoerg 
handleSynthesizedObjCMethod(const ObjCMethodDecl * D,SourceLocation Loc,const DeclContext * LexicalDC)8277330f729Sjoerg bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
8287330f729Sjoerg                                                   SourceLocation Loc,
8297330f729Sjoerg                                                  const DeclContext *LexicalDC) {
8307330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
8317330f729Sjoerg                  /*isContainer=*/false);
8327330f729Sjoerg   return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, D->getDeclContext());
8337330f729Sjoerg }
8347330f729Sjoerg 
handleObjCProperty(const ObjCPropertyDecl * D)8357330f729Sjoerg bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
8367330f729Sjoerg   ScratchAlloc SA(*this);
8377330f729Sjoerg 
8387330f729Sjoerg   ObjCPropertyDeclInfo DInfo;
8397330f729Sjoerg   EntityInfo GetterEntity;
8407330f729Sjoerg   EntityInfo SetterEntity;
8417330f729Sjoerg 
8427330f729Sjoerg   DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
8437330f729Sjoerg 
8447330f729Sjoerg   if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) {
8457330f729Sjoerg     getEntityInfo(Getter, GetterEntity, SA);
8467330f729Sjoerg     DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
8477330f729Sjoerg   } else {
8487330f729Sjoerg     DInfo.ObjCPropDeclInfo.getter = nullptr;
8497330f729Sjoerg   }
8507330f729Sjoerg   if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
8517330f729Sjoerg     getEntityInfo(Setter, SetterEntity, SA);
8527330f729Sjoerg     DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
8537330f729Sjoerg   } else {
8547330f729Sjoerg     DInfo.ObjCPropDeclInfo.setter = nullptr;
8557330f729Sjoerg   }
8567330f729Sjoerg 
8577330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8587330f729Sjoerg }
8597330f729Sjoerg 
handleNamespace(const NamespaceDecl * D)8607330f729Sjoerg bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
8617330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
8627330f729Sjoerg                  /*isDefinition=*/true,
8637330f729Sjoerg                  /*isContainer=*/true);
8647330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8657330f729Sjoerg }
8667330f729Sjoerg 
handleClassTemplate(const ClassTemplateDecl * D)8677330f729Sjoerg bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
8687330f729Sjoerg   return handleCXXRecordDecl(D->getTemplatedDecl(), D);
8697330f729Sjoerg }
8707330f729Sjoerg 
handleFunctionTemplate(const FunctionTemplateDecl * D)8717330f729Sjoerg bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
8727330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
8737330f729Sjoerg                  /*isDefinition=*/D->isThisDeclarationADefinition(),
8747330f729Sjoerg                  /*isContainer=*/D->isThisDeclarationADefinition());
8757330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8767330f729Sjoerg }
8777330f729Sjoerg 
handleTypeAliasTemplate(const TypeAliasTemplateDecl * D)8787330f729Sjoerg bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
8797330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
8807330f729Sjoerg                  /*isDefinition=*/true, /*isContainer=*/false);
8817330f729Sjoerg   return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8827330f729Sjoerg }
8837330f729Sjoerg 
handleReference(const NamedDecl * D,SourceLocation Loc,CXCursor Cursor,const NamedDecl * Parent,const DeclContext * DC,const Expr * E,CXIdxEntityRefKind Kind,CXSymbolRole Role)8847330f729Sjoerg bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
8857330f729Sjoerg                                       CXCursor Cursor,
8867330f729Sjoerg                                       const NamedDecl *Parent,
8877330f729Sjoerg                                       const DeclContext *DC,
8887330f729Sjoerg                                       const Expr *E,
8897330f729Sjoerg                                       CXIdxEntityRefKind Kind,
8907330f729Sjoerg                                       CXSymbolRole Role) {
8917330f729Sjoerg   if (!CB.indexEntityReference)
8927330f729Sjoerg     return false;
8937330f729Sjoerg 
8947330f729Sjoerg   if (!D || !DC)
8957330f729Sjoerg     return false;
8967330f729Sjoerg   if (Loc.isInvalid())
8977330f729Sjoerg     return false;
8987330f729Sjoerg   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
8997330f729Sjoerg     return false;
9007330f729Sjoerg   if (isNotFromSourceFile(D->getLocation()))
9017330f729Sjoerg     return false;
9027330f729Sjoerg   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
9037330f729Sjoerg     return false;
9047330f729Sjoerg 
9057330f729Sjoerg   if (shouldSuppressRefs()) {
9067330f729Sjoerg     if (markEntityOccurrenceInFile(D, Loc))
9077330f729Sjoerg       return false; // already occurred.
9087330f729Sjoerg   }
9097330f729Sjoerg 
9107330f729Sjoerg   ScratchAlloc SA(*this);
9117330f729Sjoerg   EntityInfo RefEntity, ParentEntity;
9127330f729Sjoerg   getEntityInfo(D, RefEntity, SA);
9137330f729Sjoerg   if (!RefEntity.USR)
9147330f729Sjoerg     return false;
9157330f729Sjoerg 
9167330f729Sjoerg   getEntityInfo(Parent, ParentEntity, SA);
9177330f729Sjoerg 
9187330f729Sjoerg   ContainerInfo Container;
9197330f729Sjoerg   getContainerInfo(DC, Container);
9207330f729Sjoerg 
9217330f729Sjoerg   CXIdxEntityRefInfo Info = { Kind,
9227330f729Sjoerg                               Cursor,
9237330f729Sjoerg                               getIndexLoc(Loc),
9247330f729Sjoerg                               &RefEntity,
9257330f729Sjoerg                               Parent ? &ParentEntity : nullptr,
9267330f729Sjoerg                               &Container,
9277330f729Sjoerg                               Role };
9287330f729Sjoerg   CB.indexEntityReference(ClientData, &Info);
9297330f729Sjoerg   return true;
9307330f729Sjoerg }
9317330f729Sjoerg 
isNotFromSourceFile(SourceLocation Loc) const9327330f729Sjoerg bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
9337330f729Sjoerg   if (Loc.isInvalid())
9347330f729Sjoerg     return true;
9357330f729Sjoerg   SourceManager &SM = Ctx->getSourceManager();
9367330f729Sjoerg   SourceLocation FileLoc = SM.getFileLoc(Loc);
9377330f729Sjoerg   FileID FID = SM.getFileID(FileLoc);
9387330f729Sjoerg   return SM.getFileEntryForID(FID) == nullptr;
9397330f729Sjoerg }
9407330f729Sjoerg 
addContainerInMap(const DeclContext * DC,CXIdxClientContainer container)9417330f729Sjoerg void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
9427330f729Sjoerg                                         CXIdxClientContainer container) {
9437330f729Sjoerg   if (!DC)
9447330f729Sjoerg     return;
9457330f729Sjoerg 
9467330f729Sjoerg   ContainerMapTy::iterator I = ContainerMap.find(DC);
9477330f729Sjoerg   if (I == ContainerMap.end()) {
9487330f729Sjoerg     if (container)
9497330f729Sjoerg       ContainerMap[DC] = container;
9507330f729Sjoerg     return;
9517330f729Sjoerg   }
9527330f729Sjoerg   // Allow changing the container of a previously seen DeclContext so we
9537330f729Sjoerg   // can handle invalid user code, like a function re-definition.
9547330f729Sjoerg   if (container)
9557330f729Sjoerg     I->second = container;
9567330f729Sjoerg   else
9577330f729Sjoerg     ContainerMap.erase(I);
9587330f729Sjoerg }
9597330f729Sjoerg 
getClientEntity(const Decl * D) const9607330f729Sjoerg CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
9617330f729Sjoerg   if (!D)
9627330f729Sjoerg     return nullptr;
9637330f729Sjoerg   EntityMapTy::const_iterator I = EntityMap.find(D);
9647330f729Sjoerg   if (I == EntityMap.end())
9657330f729Sjoerg     return nullptr;
9667330f729Sjoerg   return I->second;
9677330f729Sjoerg }
9687330f729Sjoerg 
setClientEntity(const Decl * D,CXIdxClientEntity client)9697330f729Sjoerg void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
9707330f729Sjoerg   if (!D)
9717330f729Sjoerg     return;
9727330f729Sjoerg   EntityMap[D] = client;
9737330f729Sjoerg }
9747330f729Sjoerg 
handleCXXRecordDecl(const CXXRecordDecl * RD,const NamedDecl * OrigD)9757330f729Sjoerg bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
9767330f729Sjoerg                                           const NamedDecl *OrigD) {
9777330f729Sjoerg   if (RD->isThisDeclarationADefinition()) {
9787330f729Sjoerg     ScratchAlloc SA(*this);
9797330f729Sjoerg     CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
9807330f729Sjoerg                            /*isDefinition=*/RD->isThisDeclarationADefinition());
9817330f729Sjoerg     CXXBasesListInfo BaseList(RD, *this, SA);
9827330f729Sjoerg     CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
9837330f729Sjoerg     CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
9847330f729Sjoerg     CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
9857330f729Sjoerg 
9867330f729Sjoerg     if (shouldSuppressRefs()) {
9877330f729Sjoerg       // Go through bases and mark them as referenced.
9887330f729Sjoerg       for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
9897330f729Sjoerg         const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
9907330f729Sjoerg         if (baseInfo->base) {
9917330f729Sjoerg           const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
9927330f729Sjoerg           SourceLocation
9937330f729Sjoerg             Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
9947330f729Sjoerg           markEntityOccurrenceInFile(BaseD, Loc);
9957330f729Sjoerg         }
9967330f729Sjoerg       }
9977330f729Sjoerg     }
9987330f729Sjoerg 
9997330f729Sjoerg     return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
10007330f729Sjoerg   }
10017330f729Sjoerg 
10027330f729Sjoerg   DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
10037330f729Sjoerg                  /*isDefinition=*/RD->isThisDeclarationADefinition(),
10047330f729Sjoerg                  /*isContainer=*/RD->isThisDeclarationADefinition());
10057330f729Sjoerg   return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
10067330f729Sjoerg }
10077330f729Sjoerg 
markEntityOccurrenceInFile(const NamedDecl * D,SourceLocation Loc)10087330f729Sjoerg bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
10097330f729Sjoerg                                                  SourceLocation Loc) {
10107330f729Sjoerg   if (!D || Loc.isInvalid())
10117330f729Sjoerg     return true;
10127330f729Sjoerg 
10137330f729Sjoerg   SourceManager &SM = Ctx->getSourceManager();
10147330f729Sjoerg   D = getEntityDecl(D);
10157330f729Sjoerg 
10167330f729Sjoerg   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
10177330f729Sjoerg   FileID FID = LocInfo.first;
10187330f729Sjoerg   if (FID.isInvalid())
10197330f729Sjoerg     return true;
10207330f729Sjoerg 
10217330f729Sjoerg   const FileEntry *FE = SM.getFileEntryForID(FID);
10227330f729Sjoerg   if (!FE)
10237330f729Sjoerg     return true;
10247330f729Sjoerg   RefFileOccurrence RefOccur(FE, D);
10257330f729Sjoerg   std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
10267330f729Sjoerg   res = RefFileOccurrences.insert(RefOccur);
10277330f729Sjoerg   return !res.second; // already in map
10287330f729Sjoerg }
10297330f729Sjoerg 
getEntityDecl(const NamedDecl * D) const10307330f729Sjoerg const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
10317330f729Sjoerg   assert(D);
10327330f729Sjoerg   D = cast<NamedDecl>(D->getCanonicalDecl());
10337330f729Sjoerg 
10347330f729Sjoerg   if (const ObjCImplementationDecl *
10357330f729Sjoerg                ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
10367330f729Sjoerg     return getEntityDecl(ImplD->getClassInterface());
10377330f729Sjoerg 
10387330f729Sjoerg   } else if (const ObjCCategoryImplDecl *
10397330f729Sjoerg                CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
10407330f729Sjoerg     return getEntityDecl(CatImplD->getCategoryDecl());
10417330f729Sjoerg   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
10427330f729Sjoerg     if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
10437330f729Sjoerg       return getEntityDecl(TemplD);
10447330f729Sjoerg   } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
10457330f729Sjoerg     if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
10467330f729Sjoerg       return getEntityDecl(TemplD);
10477330f729Sjoerg   }
10487330f729Sjoerg 
10497330f729Sjoerg   return D;
10507330f729Sjoerg }
10517330f729Sjoerg 
10527330f729Sjoerg const DeclContext *
getEntityContainer(const Decl * D) const10537330f729Sjoerg CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
10547330f729Sjoerg   const DeclContext *DC = dyn_cast<DeclContext>(D);
10557330f729Sjoerg   if (DC)
10567330f729Sjoerg     return DC;
10577330f729Sjoerg 
10587330f729Sjoerg   if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
10597330f729Sjoerg     DC = ClassTempl->getTemplatedDecl();
10607330f729Sjoerg   } else if (const FunctionTemplateDecl *
10617330f729Sjoerg           FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
10627330f729Sjoerg     DC = FuncTempl->getTemplatedDecl();
10637330f729Sjoerg   }
10647330f729Sjoerg 
10657330f729Sjoerg   return DC;
10667330f729Sjoerg }
10677330f729Sjoerg 
10687330f729Sjoerg CXIdxClientContainer
getClientContainerForDC(const DeclContext * DC) const10697330f729Sjoerg CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
10707330f729Sjoerg   if (!DC)
10717330f729Sjoerg     return nullptr;
10727330f729Sjoerg 
10737330f729Sjoerg   ContainerMapTy::const_iterator I = ContainerMap.find(DC);
10747330f729Sjoerg   if (I == ContainerMap.end())
10757330f729Sjoerg     return nullptr;
10767330f729Sjoerg 
10777330f729Sjoerg   return I->second;
10787330f729Sjoerg }
10797330f729Sjoerg 
getIndexFile(const FileEntry * File)10807330f729Sjoerg CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
10817330f729Sjoerg   if (!File)
10827330f729Sjoerg     return nullptr;
10837330f729Sjoerg 
10847330f729Sjoerg   FileMapTy::iterator FI = FileMap.find(File);
10857330f729Sjoerg   if (FI != FileMap.end())
10867330f729Sjoerg     return FI->second;
10877330f729Sjoerg 
10887330f729Sjoerg   return nullptr;
10897330f729Sjoerg }
10907330f729Sjoerg 
getIndexLoc(SourceLocation Loc) const10917330f729Sjoerg CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
10927330f729Sjoerg   CXIdxLoc idxLoc =  { {nullptr, nullptr}, 0 };
10937330f729Sjoerg   if (Loc.isInvalid())
10947330f729Sjoerg     return idxLoc;
10957330f729Sjoerg 
10967330f729Sjoerg   idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
10977330f729Sjoerg   idxLoc.int_data = Loc.getRawEncoding();
10987330f729Sjoerg   return idxLoc;
10997330f729Sjoerg }
11007330f729Sjoerg 
translateLoc(SourceLocation Loc,CXIdxClientFile * indexFile,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)11017330f729Sjoerg void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
11027330f729Sjoerg                                    CXIdxClientFile *indexFile, CXFile *file,
11037330f729Sjoerg                                    unsigned *line, unsigned *column,
11047330f729Sjoerg                                    unsigned *offset) {
11057330f729Sjoerg   if (Loc.isInvalid())
11067330f729Sjoerg     return;
11077330f729Sjoerg 
11087330f729Sjoerg   SourceManager &SM = Ctx->getSourceManager();
11097330f729Sjoerg   Loc = SM.getFileLoc(Loc);
11107330f729Sjoerg 
11117330f729Sjoerg   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
11127330f729Sjoerg   FileID FID = LocInfo.first;
11137330f729Sjoerg   unsigned FileOffset = LocInfo.second;
11147330f729Sjoerg 
11157330f729Sjoerg   if (FID.isInvalid())
11167330f729Sjoerg     return;
11177330f729Sjoerg 
11187330f729Sjoerg   const FileEntry *FE = SM.getFileEntryForID(FID);
11197330f729Sjoerg   if (indexFile)
11207330f729Sjoerg     *indexFile = getIndexFile(FE);
11217330f729Sjoerg   if (file)
11227330f729Sjoerg     *file = const_cast<FileEntry *>(FE);
11237330f729Sjoerg   if (line)
11247330f729Sjoerg     *line = SM.getLineNumber(FID, FileOffset);
11257330f729Sjoerg   if (column)
11267330f729Sjoerg     *column = SM.getColumnNumber(FID, FileOffset);
11277330f729Sjoerg   if (offset)
11287330f729Sjoerg     *offset = FileOffset;
11297330f729Sjoerg }
11307330f729Sjoerg 
11317330f729Sjoerg static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
11327330f729Sjoerg static CXIdxEntityCXXTemplateKind
11337330f729Sjoerg getEntityKindFromSymbolProperties(SymbolPropertySet K);
11347330f729Sjoerg static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
11357330f729Sjoerg 
getEntityInfo(const NamedDecl * D,EntityInfo & EntityInfo,ScratchAlloc & SA)11367330f729Sjoerg void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
11377330f729Sjoerg                                     EntityInfo &EntityInfo,
11387330f729Sjoerg                                     ScratchAlloc &SA) {
11397330f729Sjoerg   if (!D)
11407330f729Sjoerg     return;
11417330f729Sjoerg 
11427330f729Sjoerg   D = getEntityDecl(D);
11437330f729Sjoerg   EntityInfo.cursor = getCursor(D);
11447330f729Sjoerg   EntityInfo.Dcl = D;
11457330f729Sjoerg   EntityInfo.IndexCtx = this;
11467330f729Sjoerg 
11477330f729Sjoerg   SymbolInfo SymInfo = getSymbolInfo(D);
11487330f729Sjoerg   EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang);
11497330f729Sjoerg   EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties);
11507330f729Sjoerg   EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
11517330f729Sjoerg 
11527330f729Sjoerg   if (D->hasAttrs()) {
11537330f729Sjoerg     EntityInfo.AttrList = AttrListInfo::create(D, *this);
11547330f729Sjoerg     EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
11557330f729Sjoerg     EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
11567330f729Sjoerg   }
11577330f729Sjoerg 
11587330f729Sjoerg   if (EntityInfo.kind == CXIdxEntity_Unexposed)
11597330f729Sjoerg     return;
11607330f729Sjoerg 
11617330f729Sjoerg   if (IdentifierInfo *II = D->getIdentifier()) {
11627330f729Sjoerg     EntityInfo.name = SA.toCStr(II->getName());
11637330f729Sjoerg 
11647330f729Sjoerg   } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
11657330f729Sjoerg     EntityInfo.name = nullptr; // anonymous tag/field/namespace.
11667330f729Sjoerg 
11677330f729Sjoerg   } else {
11687330f729Sjoerg     SmallString<256> StrBuf;
11697330f729Sjoerg     {
11707330f729Sjoerg       llvm::raw_svector_ostream OS(StrBuf);
11717330f729Sjoerg       D->printName(OS);
11727330f729Sjoerg     }
11737330f729Sjoerg     EntityInfo.name = SA.copyCStr(StrBuf.str());
11747330f729Sjoerg   }
11757330f729Sjoerg 
11767330f729Sjoerg   {
11777330f729Sjoerg     SmallString<512> StrBuf;
11787330f729Sjoerg     bool Ignore = getDeclCursorUSR(D, StrBuf);
11797330f729Sjoerg     if (Ignore) {
11807330f729Sjoerg       EntityInfo.USR = nullptr;
11817330f729Sjoerg     } else {
11827330f729Sjoerg       EntityInfo.USR = SA.copyCStr(StrBuf.str());
11837330f729Sjoerg     }
11847330f729Sjoerg   }
11857330f729Sjoerg }
11867330f729Sjoerg 
getContainerInfo(const DeclContext * DC,ContainerInfo & ContInfo)11877330f729Sjoerg void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
11887330f729Sjoerg                                        ContainerInfo &ContInfo) {
11897330f729Sjoerg   ContInfo.cursor = getCursor(cast<Decl>(DC));
11907330f729Sjoerg   ContInfo.DC = DC;
11917330f729Sjoerg   ContInfo.IndexCtx = this;
11927330f729Sjoerg }
11937330f729Sjoerg 
getRefCursor(const NamedDecl * D,SourceLocation Loc)11947330f729Sjoerg CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
11957330f729Sjoerg   if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
11967330f729Sjoerg     return MakeCursorTypeRef(TD, Loc, CXTU);
11977330f729Sjoerg   if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
11987330f729Sjoerg     return MakeCursorObjCClassRef(ID, Loc, CXTU);
11997330f729Sjoerg   if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
12007330f729Sjoerg     return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
12017330f729Sjoerg   if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
12027330f729Sjoerg     return MakeCursorTemplateRef(Template, Loc, CXTU);
12037330f729Sjoerg   if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
12047330f729Sjoerg     return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
12057330f729Sjoerg   if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
12067330f729Sjoerg     return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
12077330f729Sjoerg   if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
12087330f729Sjoerg     return MakeCursorMemberRef(Field, Loc, CXTU);
12097330f729Sjoerg   if (const VarDecl *Var = dyn_cast<VarDecl>(D))
12107330f729Sjoerg     return MakeCursorVariableRef(Var, Loc, CXTU);
12117330f729Sjoerg 
12127330f729Sjoerg   return clang_getNullCursor();
12137330f729Sjoerg }
12147330f729Sjoerg 
shouldIgnoreIfImplicit(const Decl * D)12157330f729Sjoerg bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
12167330f729Sjoerg   if (isa<ObjCInterfaceDecl>(D))
12177330f729Sjoerg     return false;
12187330f729Sjoerg   if (isa<ObjCCategoryDecl>(D))
12197330f729Sjoerg     return false;
12207330f729Sjoerg   if (isa<ObjCIvarDecl>(D))
12217330f729Sjoerg     return false;
12227330f729Sjoerg   if (isa<ObjCMethodDecl>(D))
12237330f729Sjoerg     return false;
12247330f729Sjoerg   if (isa<ImportDecl>(D))
12257330f729Sjoerg     return false;
12267330f729Sjoerg   return true;
12277330f729Sjoerg }
12287330f729Sjoerg 
isTemplateImplicitInstantiation(const Decl * D)12297330f729Sjoerg bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
12307330f729Sjoerg   if (const ClassTemplateSpecializationDecl *
12317330f729Sjoerg         SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
12327330f729Sjoerg     return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
12337330f729Sjoerg   }
12347330f729Sjoerg   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
12357330f729Sjoerg     return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
12367330f729Sjoerg   }
12377330f729Sjoerg   return false;
12387330f729Sjoerg }
12397330f729Sjoerg 
getEntityKindFromSymbolKind(SymbolKind K,SymbolLanguage Lang)12407330f729Sjoerg static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) {
12417330f729Sjoerg   switch (K) {
12427330f729Sjoerg   case SymbolKind::Unknown:
12437330f729Sjoerg   case SymbolKind::Module:
12447330f729Sjoerg   case SymbolKind::Macro:
12457330f729Sjoerg   case SymbolKind::ClassProperty:
12467330f729Sjoerg   case SymbolKind::Using:
1247*e038c9c4Sjoerg   case SymbolKind::TemplateTypeParm:
1248*e038c9c4Sjoerg   case SymbolKind::TemplateTemplateParm:
1249*e038c9c4Sjoerg   case SymbolKind::NonTypeTemplateParm:
12507330f729Sjoerg     return CXIdxEntity_Unexposed;
12517330f729Sjoerg 
12527330f729Sjoerg   case SymbolKind::Enum: return CXIdxEntity_Enum;
12537330f729Sjoerg   case SymbolKind::Struct: return CXIdxEntity_Struct;
12547330f729Sjoerg   case SymbolKind::Union: return CXIdxEntity_Union;
12557330f729Sjoerg   case SymbolKind::TypeAlias:
12567330f729Sjoerg     if (Lang == SymbolLanguage::CXX)
12577330f729Sjoerg       return CXIdxEntity_CXXTypeAlias;
12587330f729Sjoerg     return CXIdxEntity_Typedef;
12597330f729Sjoerg   case SymbolKind::Function: return CXIdxEntity_Function;
12607330f729Sjoerg   case SymbolKind::Variable: return CXIdxEntity_Variable;
12617330f729Sjoerg   case SymbolKind::Field:
12627330f729Sjoerg     if (Lang == SymbolLanguage::ObjC)
12637330f729Sjoerg       return CXIdxEntity_ObjCIvar;
12647330f729Sjoerg     return CXIdxEntity_Field;
12657330f729Sjoerg   case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
12667330f729Sjoerg   case SymbolKind::Class:
12677330f729Sjoerg     if (Lang == SymbolLanguage::ObjC)
12687330f729Sjoerg       return CXIdxEntity_ObjCClass;
12697330f729Sjoerg     return CXIdxEntity_CXXClass;
12707330f729Sjoerg   case SymbolKind::Protocol:
12717330f729Sjoerg     if (Lang == SymbolLanguage::ObjC)
12727330f729Sjoerg       return CXIdxEntity_ObjCProtocol;
12737330f729Sjoerg     return CXIdxEntity_CXXInterface;
12747330f729Sjoerg   case SymbolKind::Extension: return CXIdxEntity_ObjCCategory;
12757330f729Sjoerg   case SymbolKind::InstanceMethod:
12767330f729Sjoerg     if (Lang == SymbolLanguage::ObjC)
12777330f729Sjoerg       return CXIdxEntity_ObjCInstanceMethod;
12787330f729Sjoerg     return CXIdxEntity_CXXInstanceMethod;
12797330f729Sjoerg   case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod;
12807330f729Sjoerg   case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod;
12817330f729Sjoerg   case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty;
12827330f729Sjoerg   case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable;
12837330f729Sjoerg   case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace;
12847330f729Sjoerg   case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
12857330f729Sjoerg   case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
12867330f729Sjoerg   case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
12877330f729Sjoerg   case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
12887330f729Sjoerg   case SymbolKind::Parameter: return CXIdxEntity_Variable;
12897330f729Sjoerg   }
12907330f729Sjoerg   llvm_unreachable("invalid symbol kind");
12917330f729Sjoerg }
12927330f729Sjoerg 
12937330f729Sjoerg static CXIdxEntityCXXTemplateKind
getEntityKindFromSymbolProperties(SymbolPropertySet K)12947330f729Sjoerg getEntityKindFromSymbolProperties(SymbolPropertySet K) {
12957330f729Sjoerg   if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
12967330f729Sjoerg     return CXIdxEntity_TemplatePartialSpecialization;
12977330f729Sjoerg   if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
12987330f729Sjoerg     return CXIdxEntity_TemplateSpecialization;
12997330f729Sjoerg   if (K & (SymbolPropertySet)SymbolProperty::Generic)
13007330f729Sjoerg     return CXIdxEntity_Template;
13017330f729Sjoerg   return CXIdxEntity_NonTemplate;
13027330f729Sjoerg }
13037330f729Sjoerg 
getEntityLangFromSymbolLang(SymbolLanguage L)13047330f729Sjoerg static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
13057330f729Sjoerg   switch (L) {
13067330f729Sjoerg   case SymbolLanguage::C: return CXIdxEntityLang_C;
13077330f729Sjoerg   case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
13087330f729Sjoerg   case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
13097330f729Sjoerg   case SymbolLanguage::Swift: return CXIdxEntityLang_Swift;
13107330f729Sjoerg   }
13117330f729Sjoerg   llvm_unreachable("invalid symbol language");
13127330f729Sjoerg }
1313