1 //===- IndexingContext.cpp - Indexing context data ------------------------===// 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/Index/IndexDataConsumer.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/DeclTemplate.h" 14 #include "clang/AST/DeclObjC.h" 15 #include "clang/Basic/SourceManager.h" 16 17 using namespace clang; 18 using namespace index; 19 20 static bool isGeneratedDecl(const Decl *D) { 21 if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) { 22 return attr->getGeneratedDeclaration(); 23 } 24 return false; 25 } 26 27 bool IndexingContext::shouldIndex(const Decl *D) { 28 return !isGeneratedDecl(D); 29 } 30 31 const LangOptions &IndexingContext::getLangOpts() const { 32 return Ctx->getLangOpts(); 33 } 34 35 bool IndexingContext::shouldIndexFunctionLocalSymbols() const { 36 return IndexOpts.IndexFunctionLocals; 37 } 38 39 bool IndexingContext::handleDecl(const Decl *D, 40 SymbolRoleSet Roles, 41 ArrayRef<SymbolRelation> Relations) { 42 return handleDecl(D, D->getLocation(), Roles, Relations); 43 } 44 45 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, 46 SymbolRoleSet Roles, 47 ArrayRef<SymbolRelation> Relations, 48 const DeclContext *DC) { 49 if (!DC) 50 DC = D->getDeclContext(); 51 52 const Decl *OrigD = D; 53 if (isa<ObjCPropertyImplDecl>(D)) { 54 D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl(); 55 } 56 return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC), 57 Roles, Relations, 58 nullptr, OrigD, DC); 59 } 60 61 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, 62 const NamedDecl *Parent, 63 const DeclContext *DC, 64 SymbolRoleSet Roles, 65 ArrayRef<SymbolRelation> Relations, 66 const Expr *RefE, 67 const Decl *RefD) { 68 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) 69 return true; 70 71 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D)) 72 return true; 73 74 return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations, 75 RefE, RefD, DC); 76 } 77 78 bool IndexingContext::importedModule(const ImportDecl *ImportD) { 79 SourceLocation Loc; 80 auto IdLocs = ImportD->getIdentifierLocs(); 81 if (!IdLocs.empty()) 82 Loc = IdLocs.front(); 83 else 84 Loc = ImportD->getLocation(); 85 SourceManager &SM = Ctx->getSourceManager(); 86 Loc = SM.getFileLoc(Loc); 87 if (Loc.isInvalid()) 88 return true; 89 90 FileID FID; 91 unsigned Offset; 92 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); 93 if (FID.isInvalid()) 94 return true; 95 96 bool Invalid = false; 97 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 98 if (Invalid || !SEntry.isFile()) 99 return true; 100 101 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 102 switch (IndexOpts.SystemSymbolFilter) { 103 case IndexingOptions::SystemSymbolFilterKind::None: 104 return true; 105 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 106 case IndexingOptions::SystemSymbolFilterKind::All: 107 break; 108 } 109 } 110 111 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration; 112 if (ImportD->isImplicit()) 113 Roles |= (unsigned)SymbolRole::Implicit; 114 115 return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); 116 } 117 118 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { 119 TemplateSpecializationKind TKind = TSK_Undeclared; 120 if (const ClassTemplateSpecializationDecl * 121 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 122 TKind = SD->getSpecializationKind(); 123 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 124 TKind = FD->getTemplateSpecializationKind(); 125 } else if (auto *VD = dyn_cast<VarDecl>(D)) { 126 TKind = VD->getTemplateSpecializationKind(); 127 } 128 switch (TKind) { 129 case TSK_Undeclared: 130 case TSK_ExplicitSpecialization: 131 return false; 132 case TSK_ImplicitInstantiation: 133 case TSK_ExplicitInstantiationDeclaration: 134 case TSK_ExplicitInstantiationDefinition: 135 return true; 136 } 137 llvm_unreachable("invalid TemplateSpecializationKind"); 138 } 139 140 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { 141 if (isa<ObjCInterfaceDecl>(D)) 142 return false; 143 if (isa<ObjCCategoryDecl>(D)) 144 return false; 145 if (isa<ObjCIvarDecl>(D)) 146 return false; 147 if (isa<ObjCMethodDecl>(D)) 148 return false; 149 if (isa<ImportDecl>(D)) 150 return false; 151 return true; 152 } 153 154 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { 155 if (const ClassTemplateSpecializationDecl * 156 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 157 return SD->getTemplateInstantiationPattern(); 158 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 159 return FD->getTemplateInstantiationPattern(); 160 } else if (auto *VD = dyn_cast<VarDecl>(D)) { 161 return VD->getTemplateInstantiationPattern(); 162 } 163 return nullptr; 164 } 165 166 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { 167 if (auto VD = dyn_cast<VarDecl>(D)) 168 return VD->isThisDeclarationADefinition(Ctx); 169 170 if (auto FD = dyn_cast<FunctionDecl>(D)) 171 return FD->isThisDeclarationADefinition(); 172 173 if (auto TD = dyn_cast<TagDecl>(D)) 174 return TD->isThisDeclarationADefinition(); 175 176 if (auto MD = dyn_cast<ObjCMethodDecl>(D)) 177 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC); 178 179 if (isa<TypedefNameDecl>(D) || 180 isa<EnumConstantDecl>(D) || 181 isa<FieldDecl>(D) || 182 isa<MSPropertyDecl>(D) || 183 isa<ObjCImplDecl>(D) || 184 isa<ObjCPropertyImplDecl>(D)) 185 return true; 186 187 return false; 188 } 189 190 static const Decl *adjustParent(const Decl *Parent) { 191 if (!Parent) 192 return nullptr; 193 for (;; Parent = cast<Decl>(Parent->getDeclContext())) { 194 if (isa<TranslationUnitDecl>(Parent)) 195 return nullptr; 196 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent)) 197 continue; 198 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) { 199 if (NS->isAnonymousNamespace()) 200 continue; 201 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) { 202 if (RD->isAnonymousStructOrUnion()) 203 continue; 204 } else if (auto FD = dyn_cast<FieldDecl>(Parent)) { 205 if (FD->getDeclName().isEmpty()) 206 continue; 207 } 208 return Parent; 209 } 210 } 211 212 static const Decl *getCanonicalDecl(const Decl *D) { 213 D = D->getCanonicalDecl(); 214 if (auto TD = dyn_cast<TemplateDecl>(D)) { 215 D = TD->getTemplatedDecl(); 216 assert(D->isCanonicalDecl()); 217 } 218 219 return D; 220 } 221 222 static bool shouldReportOccurrenceForSystemDeclOnlyMode( 223 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { 224 if (!IsRef) 225 return true; 226 227 auto acceptForRelation = [](SymbolRoleSet roles) -> bool { 228 bool accept = false; 229 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool { 230 switch (r) { 231 case SymbolRole::RelationChildOf: 232 case SymbolRole::RelationBaseOf: 233 case SymbolRole::RelationOverrideOf: 234 case SymbolRole::RelationExtendedBy: 235 case SymbolRole::RelationAccessorOf: 236 case SymbolRole::RelationIBTypeOf: 237 accept = true; 238 return false; 239 case SymbolRole::Declaration: 240 case SymbolRole::Definition: 241 case SymbolRole::Reference: 242 case SymbolRole::Read: 243 case SymbolRole::Write: 244 case SymbolRole::Call: 245 case SymbolRole::Dynamic: 246 case SymbolRole::AddressOf: 247 case SymbolRole::Implicit: 248 case SymbolRole::RelationReceivedBy: 249 case SymbolRole::RelationCalledBy: 250 case SymbolRole::RelationContainedBy: 251 case SymbolRole::RelationSpecializationOf: 252 return true; 253 } 254 llvm_unreachable("Unsupported SymbolRole value!"); 255 }); 256 return accept; 257 }; 258 259 for (auto &Rel : Relations) { 260 if (acceptForRelation(Rel.Roles)) 261 return true; 262 } 263 264 return false; 265 } 266 267 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, 268 bool IsRef, const Decl *Parent, 269 SymbolRoleSet Roles, 270 ArrayRef<SymbolRelation> Relations, 271 const Expr *OrigE, 272 const Decl *OrigD, 273 const DeclContext *ContainerDC) { 274 if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) 275 return true; 276 if (!isa<NamedDecl>(D) || 277 (cast<NamedDecl>(D)->getDeclName().isEmpty() && 278 !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D))) 279 return true; 280 281 SourceManager &SM = Ctx->getSourceManager(); 282 Loc = SM.getFileLoc(Loc); 283 if (Loc.isInvalid()) 284 return true; 285 286 FileID FID; 287 unsigned Offset; 288 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); 289 if (FID.isInvalid()) 290 return true; 291 292 bool Invalid = false; 293 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 294 if (Invalid || !SEntry.isFile()) 295 return true; 296 297 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 298 switch (IndexOpts.SystemSymbolFilter) { 299 case IndexingOptions::SystemSymbolFilterKind::None: 300 return true; 301 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 302 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) 303 return true; 304 break; 305 case IndexingOptions::SystemSymbolFilterKind::All: 306 break; 307 } 308 } 309 310 if (isTemplateImplicitInstantiation(D)) { 311 if (!IsRef) 312 return true; 313 D = adjustTemplateImplicitInstantiation(D); 314 if (!D) 315 return true; 316 assert(!isTemplateImplicitInstantiation(D)); 317 } 318 319 if (!OrigD) 320 OrigD = D; 321 322 if (IsRef) 323 Roles |= (unsigned)SymbolRole::Reference; 324 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) 325 Roles |= (unsigned)SymbolRole::Definition; 326 else 327 Roles |= (unsigned)SymbolRole::Declaration; 328 329 D = getCanonicalDecl(D); 330 Parent = adjustParent(Parent); 331 if (Parent) 332 Parent = getCanonicalDecl(Parent); 333 334 SmallVector<SymbolRelation, 6> FinalRelations; 335 FinalRelations.reserve(Relations.size()+1); 336 337 auto addRelation = [&](SymbolRelation Rel) { 338 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(), 339 [&](SymbolRelation Elem)->bool { 340 return Elem.RelatedSymbol == Rel.RelatedSymbol; 341 }); 342 if (It != FinalRelations.end()) { 343 It->Roles |= Rel.Roles; 344 } else { 345 FinalRelations.push_back(Rel); 346 } 347 Roles |= Rel.Roles; 348 }; 349 350 if (Parent) { 351 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) { 352 addRelation(SymbolRelation{ 353 (unsigned)SymbolRole::RelationContainedBy, 354 Parent 355 }); 356 } else { 357 addRelation(SymbolRelation{ 358 (unsigned)SymbolRole::RelationChildOf, 359 Parent 360 }); 361 } 362 } 363 364 for (auto &Rel : Relations) { 365 addRelation(SymbolRelation(Rel.Roles, 366 Rel.RelatedSymbol->getCanonicalDecl())); 367 } 368 369 IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC }; 370 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset, 371 Node); 372 } 373