IndexTypeSourceInfo.cpp revision ef8225444452a1486bd721f3285301fe84643b00
1//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IndexingContext.h"
11#include "clang/AST/DataRecursiveASTVisitor.h"
12
13using namespace clang;
14using namespace cxindex;
15
16namespace {
17
18class TypeIndexer : public DataRecursiveASTVisitor<TypeIndexer> {
19  IndexingContext &IndexCtx;
20  const NamedDecl *Parent;
21  const DeclContext *ParentDC;
22
23public:
24  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
25              const DeclContext *DC)
26    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
27
28  bool shouldWalkTypesOfTypeLocs() const { return false; }
29
30  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
31    IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
32                             Parent, ParentDC);
33    return true;
34  }
35
36  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
37    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
38    return true;
39  }
40
41  bool VisitTagTypeLoc(TagTypeLoc TL) {
42    TagDecl *D = TL.getDecl();
43    if (D->getParentFunctionOrMethod())
44      return true;
45
46    if (TL.isDefinition()) {
47      IndexCtx.indexTagDecl(D);
48      return true;
49    }
50
51    if (D->getLocation() == TL.getNameLoc())
52      IndexCtx.handleTagDecl(D);
53    else
54      IndexCtx.handleReference(D, TL.getNameLoc(),
55                               Parent, ParentDC);
56    return true;
57  }
58
59  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
60    IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
61                             Parent, ParentDC);
62    return true;
63  }
64
65  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
66    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
67      IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
68                               Parent, ParentDC);
69    }
70    return true;
71  }
72
73  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
74    if (const TemplateSpecializationType *T = TL.getTypePtr()) {
75      if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
76        if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
77          IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
78                                   Parent, ParentDC);
79      } else {
80        if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
81          IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
82                                   Parent, ParentDC);
83      }
84    }
85    return true;
86  }
87
88  bool TraverseStmt(Stmt *S) {
89    IndexCtx.indexBody(S, Parent, ParentDC);
90    return true;
91  }
92};
93
94} // anonymous namespace
95
96void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
97                                          const NamedDecl *Parent,
98                                          const DeclContext *DC) {
99  if (!TInfo || TInfo->getTypeLoc().isNull())
100    return;
101
102  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
103}
104
105void IndexingContext::indexTypeLoc(TypeLoc TL,
106                                   const NamedDecl *Parent,
107                                   const DeclContext *DC) {
108  if (TL.isNull())
109    return;
110
111  if (!DC)
112    DC = Parent->getLexicalDeclContext();
113  TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
114}
115
116void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
117                                                  const NamedDecl *Parent,
118                                                  const DeclContext *DC) {
119  if (!NNS)
120    return;
121
122  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
123    indexNestedNameSpecifierLoc(Prefix, Parent, DC);
124
125  if (!DC)
126    DC = Parent->getLexicalDeclContext();
127  SourceLocation Loc = NNS.getSourceRange().getBegin();
128
129  switch (NNS.getNestedNameSpecifier()->getKind()) {
130  case NestedNameSpecifier::Identifier:
131  case NestedNameSpecifier::Global:
132    break;
133
134  case NestedNameSpecifier::Namespace:
135    handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
136                    Loc, Parent, DC);
137    break;
138  case NestedNameSpecifier::NamespaceAlias:
139    handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
140                    Loc, Parent, DC);
141    break;
142
143  case NestedNameSpecifier::TypeSpec:
144  case NestedNameSpecifier::TypeSpecWithTemplate:
145    indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
146    break;
147  }
148}
149
150void IndexingContext::indexTagDecl(const TagDecl *D) {
151  if (handleTagDecl(D)) {
152    if (D->isThisDeclarationADefinition())
153      indexDeclContext(D);
154  }
155}
156