14e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
24e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//
34e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
44e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//
54e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
64e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
74e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//
84e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
94e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
104e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis#include "IndexingContext.h"
114e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
12dec35a9848b3580855ea53eaeeafd3e17a5fb934Argyrios Kyrtzidis#include "RecursiveASTVisitor.h"
134e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
144e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisusing namespace clang;
154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisusing namespace cxindex;
164e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
174e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisnamespace {
184e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1998180d49bdbb9a41e9cacf12a3a8be30a60ba707Argyrios Kyrtzidisclass TypeIndexer : public cxindex::RecursiveASTVisitor<TypeIndexer> {
204e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  IndexingContext &IndexCtx;
214e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const NamedDecl *Parent;
224e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  const DeclContext *ParentDC;
234e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
244e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidispublic:
254e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
264e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis              const DeclContext *DC)
274e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
284e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
294e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
304e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
314e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
324e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
334e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                             Parent, ParentDC);
344e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return true;
354e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
364e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
37e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
38e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
39e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    return true;
40e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  }
41e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
424e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  bool VisitTagTypeLoc(TagTypeLoc TL) {
434e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    TagDecl *D = TL.getDecl();
44d6c8209fd1567db9c2721f441b50cb23cdf8d835Argyrios Kyrtzidis    if (D->getParentFunctionOrMethod())
45d6c8209fd1567db9c2721f441b50cb23cdf8d835Argyrios Kyrtzidis      return true;
464e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
474e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    if (TL.isDefinition()) {
484e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      IndexCtx.indexTagDecl(D);
494e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      return true;
504e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    }
514e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
524e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    if (D->getLocation() == TL.getNameLoc())
534e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      IndexCtx.handleTagDecl(D);
544e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    else
554e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      IndexCtx.handleReference(D, TL.getNameLoc(),
564e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                               Parent, ParentDC);
574e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return true;
584e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
594e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
604e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
614e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
624e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                             Parent, ParentDC);
634e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return true;
644e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
654e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
664e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
674e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
684e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis      IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
694e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                               Parent, ParentDC);
704e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    }
714e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return true;
724e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
73145f7b2093a0050621141acd089e09edf6118a09Argyrios Kyrtzidis
74145f7b2093a0050621141acd089e09edf6118a09Argyrios Kyrtzidis  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
756d968363877388f0a0268711d59367907b465ae1Argyrios Kyrtzidis    if (const TemplateSpecializationType *T = TL.getTypePtr()) {
7658d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis      if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
7758d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis        if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
7858d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis          IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
7958d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis                                   Parent, ParentDC);
8058d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis      } else {
8158d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis        if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
8258d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis          IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
8358d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis                                   Parent, ParentDC);
8458d2dbea680a75de266c5eff77cc15c323cfd48aArgyrios Kyrtzidis      }
856d968363877388f0a0268711d59367907b465ae1Argyrios Kyrtzidis    }
86145f7b2093a0050621141acd089e09edf6118a09Argyrios Kyrtzidis    return true;
87145f7b2093a0050621141acd089e09edf6118a09Argyrios Kyrtzidis  }
88f8490eeb966103516da4e3ecb05e1a36b3e6e3ecArgyrios Kyrtzidis
89f8490eeb966103516da4e3ecb05e1a36b3e6e3ecArgyrios Kyrtzidis  bool TraverseStmt(Stmt *S) {
90f8490eeb966103516da4e3ecb05e1a36b3e6e3ecArgyrios Kyrtzidis    IndexCtx.indexBody(S, Parent, ParentDC);
91f8490eeb966103516da4e3ecb05e1a36b3e6e3ecArgyrios Kyrtzidis    return true;
92f8490eeb966103516da4e3ecb05e1a36b3e6e3ecArgyrios Kyrtzidis  }
934e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis};
944e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
954e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis} // anonymous namespace
964e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
974e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisvoid IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
984e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                                          const NamedDecl *Parent,
994e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                                          const DeclContext *DC) {
1004e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  if (!TInfo || TInfo->getTypeLoc().isNull())
1014e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    return;
1024e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1034e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
1044e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
1054e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
1064e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisvoid IndexingContext::indexTypeLoc(TypeLoc TL,
1074e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                                   const NamedDecl *Parent,
1084e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis                                   const DeclContext *DC) {
109e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  if (TL.isNull())
110e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    return;
111e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
112e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  if (DC == 0)
113e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    DC = Parent->getLexicalDeclContext();
1144e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
1154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
1164e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
117e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidisvoid IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
118e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis                                                  const NamedDecl *Parent,
119e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis                                                  const DeclContext *DC) {
120e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  if (!NNS)
121e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    return;
122e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
123e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
124e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    indexNestedNameSpecifierLoc(Prefix, Parent, DC);
125e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
126e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  if (DC == 0)
127e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    DC = Parent->getLexicalDeclContext();
128e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  SourceLocation Loc = NNS.getSourceRange().getBegin();
129e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
130e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  switch (NNS.getNestedNameSpecifier()->getKind()) {
131e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::Identifier:
132e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::Global:
133e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    break;
134e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
135e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::Namespace:
136e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
137e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis                    Loc, Parent, DC);
138e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    break;
139e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::NamespaceAlias:
140e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
141e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis                    Loc, Parent, DC);
142e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    break;
143e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
144e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::TypeSpec:
145e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  case NestedNameSpecifier::TypeSpecWithTemplate:
146e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
147e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis    break;
148e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis  }
149e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis}
150e422e45a6a89d450b8eca10f671b49874e87617aArgyrios Kyrtzidis
1514e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidisvoid IndexingContext::indexTagDecl(const TagDecl *D) {
152b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  if (handleTagDecl(D)) {
153b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis    if (D->isThisDeclarationADefinition())
154b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis      indexDeclContext(D);
1554e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis  }
1564e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis}
157