]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp
Merge ^/head r314420 through r314481.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexTypeSourceInfo.cpp
1 //===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
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/RecursiveASTVisitor.h"
12
13 using namespace clang;
14 using namespace index;
15
16 namespace {
17
18 class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
19   IndexingContext &IndexCtx;
20   const NamedDecl *Parent;
21   const DeclContext *ParentDC;
22   bool IsBase;
23   SmallVector<SymbolRelation, 3> Relations;
24
25   typedef RecursiveASTVisitor<TypeIndexer> base;
26
27 public:
28   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
29               const DeclContext *DC, bool isBase, bool isIBType)
30     : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
31     if (IsBase) {
32       assert(Parent);
33       Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
34     }
35     if (isIBType) {
36       assert(Parent);
37       Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
38     }
39   }
40   
41   bool shouldWalkTypesOfTypeLocs() const { return false; }
42
43   bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
44     return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
45                                     Parent, ParentDC, SymbolRoleSet(),
46                                     Relations);
47   }
48
49 #define TRY_TO(CALL_EXPR)                                                      \
50   do {                                                                         \
51     if (!CALL_EXPR)                                                            \
52       return false;                                                            \
53   } while (0)
54
55   bool traverseParamVarHelper(ParmVarDecl *D) {
56     TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
57     if (D->getTypeSourceInfo())
58       TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
59     return true;
60   }
61
62   bool TraverseParmVarDecl(ParmVarDecl *D) {
63     // Avoid visiting default arguments from the definition that were already
64     // visited in the declaration.
65     // FIXME: A free function definition can have default arguments.
66     // Avoiding double visitaiton of default arguments should be handled by the
67     // visitor probably with a bit in the AST to indicate if the attached
68     // default argument was 'inherited' or written in source.
69     if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
70       if (FD->isThisDeclarationADefinition()) {
71         return traverseParamVarHelper(D);
72       }
73     }
74
75     return base::TraverseParmVarDecl(D);
76   }
77
78   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
79     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
80     return true;
81   }
82
83   bool VisitTagTypeLoc(TagTypeLoc TL) {
84     TagDecl *D = TL.getDecl();
85     if (D->getParentFunctionOrMethod())
86       return true;
87
88     if (TL.isDefinition()) {
89       IndexCtx.indexTagDecl(D);
90       return true;
91     }
92
93     return IndexCtx.handleReference(D, TL.getNameLoc(),
94                                     Parent, ParentDC, SymbolRoleSet(),
95                                     Relations);
96   }
97
98   bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
99     return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
100                                     Parent, ParentDC, SymbolRoleSet(), Relations);
101   }
102
103   bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
104     for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
105       IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
106                                Parent, ParentDC, SymbolRoleSet(), Relations);
107     }
108     return true;
109   }
110
111   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
112     if (const TemplateSpecializationType *T = TL.getTypePtr()) {
113       if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
114         if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
115           IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
116                                    Parent, ParentDC, SymbolRoleSet(), Relations);
117       } else {
118         if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
119           IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
120                                    Parent, ParentDC, SymbolRoleSet(), Relations);
121       }
122     }
123     return true;
124   }
125
126   bool TraverseStmt(Stmt *S) {
127     IndexCtx.indexBody(S, Parent, ParentDC);
128     return true;
129   }
130 };
131
132 } // anonymous namespace
133
134 void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
135                                           const NamedDecl *Parent,
136                                           const DeclContext *DC,
137                                           bool isBase,
138                                           bool isIBType) {
139   if (!TInfo || TInfo->getTypeLoc().isNull())
140     return;
141   
142   indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
143 }
144
145 void IndexingContext::indexTypeLoc(TypeLoc TL,
146                                    const NamedDecl *Parent,
147                                    const DeclContext *DC,
148                                    bool isBase,
149                                    bool isIBType) {
150   if (TL.isNull())
151     return;
152
153   if (!DC)
154     DC = Parent->getLexicalDeclContext();
155   TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
156 }
157
158 void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
159                                                   const NamedDecl *Parent,
160                                                   const DeclContext *DC) {
161   if (!NNS)
162     return;
163
164   if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
165     indexNestedNameSpecifierLoc(Prefix, Parent, DC);
166
167   if (!DC)
168     DC = Parent->getLexicalDeclContext();
169   SourceLocation Loc = NNS.getSourceRange().getBegin();
170
171   switch (NNS.getNestedNameSpecifier()->getKind()) {
172   case NestedNameSpecifier::Identifier:
173   case NestedNameSpecifier::Global:
174   case NestedNameSpecifier::Super:
175     break;
176
177   case NestedNameSpecifier::Namespace:
178     handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
179                     Loc, Parent, DC, SymbolRoleSet());
180     break;
181   case NestedNameSpecifier::NamespaceAlias:
182     handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
183                     Loc, Parent, DC, SymbolRoleSet());
184     break;
185
186   case NestedNameSpecifier::TypeSpec:
187   case NestedNameSpecifier::TypeSpecWithTemplate:
188     indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
189     break;
190   }
191 }
192
193 void IndexingContext::indexTagDecl(const TagDecl *D) {
194   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
195     return;
196
197   if (handleDecl(D)) {
198     if (D->isThisDeclarationADefinition()) {
199       indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
200       if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
201         for (const auto &I : CXXRD->bases()) {
202           indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
203         }
204       }
205       indexDeclContext(D);
206     }
207   }
208 }