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/Basic/SourceLocation.h" 12 #include "clang/Index/IndexDataConsumer.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/DeclTemplate.h" 15 #include "clang/AST/DeclObjC.h" 16 #include "clang/Basic/SourceManager.h" 17 18 using namespace clang; 19 using namespace index; 20 21 static bool isGeneratedDecl(const Decl *D) { 22 if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) { 23 return attr->getGeneratedDeclaration(); 24 } 25 return false; 26 } 27 28 bool IndexingContext::shouldIndex(const Decl *D) { 29 return !isGeneratedDecl(D); 30 } 31 32 const LangOptions &IndexingContext::getLangOpts() const { 33 return Ctx->getLangOpts(); 34 } 35 36 bool IndexingContext::shouldIndexFunctionLocalSymbols() const { 37 return IndexOpts.IndexFunctionLocals; 38 } 39 40 bool IndexingContext::shouldIndexImplicitInstantiation() const { 41 return IndexOpts.IndexImplicitInstantiation; 42 } 43 44 bool IndexingContext::handleDecl(const Decl *D, 45 SymbolRoleSet Roles, 46 ArrayRef<SymbolRelation> Relations) { 47 return handleDecl(D, D->getLocation(), Roles, Relations); 48 } 49 50 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, 51 SymbolRoleSet Roles, 52 ArrayRef<SymbolRelation> Relations, 53 const DeclContext *DC) { 54 if (!DC) 55 DC = D->getDeclContext(); 56 57 const Decl *OrigD = D; 58 if (isa<ObjCPropertyImplDecl>(D)) { 59 D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl(); 60 } 61 return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC), 62 Roles, Relations, 63 nullptr, OrigD, DC); 64 } 65 66 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, 67 const NamedDecl *Parent, 68 const DeclContext *DC, 69 SymbolRoleSet Roles, 70 ArrayRef<SymbolRelation> Relations, 71 const Expr *RefE, 72 const Decl *RefD) { 73 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) 74 return true; 75 76 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D)) 77 return true; 78 79 return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations, 80 RefE, RefD, DC); 81 } 82 83 bool IndexingContext::importedModule(const ImportDecl *ImportD) { 84 SourceLocation Loc; 85 auto IdLocs = ImportD->getIdentifierLocs(); 86 if (!IdLocs.empty()) 87 Loc = IdLocs.front(); 88 else 89 Loc = ImportD->getLocation(); 90 91 SourceManager &SM = Ctx->getSourceManager(); 92 FileID FID = SM.getFileID(SM.getFileLoc(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, Loc); 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 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { 128 if (RD->getInstantiatedFromMemberClass()) 129 TKind = RD->getTemplateSpecializationKind(); 130 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 131 if (ED->getInstantiatedFromMemberEnum()) 132 TKind = ED->getTemplateSpecializationKind(); 133 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) || 134 isa<EnumConstantDecl>(D)) { 135 if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext())) 136 return isTemplateImplicitInstantiation(Parent); 137 } 138 switch (TKind) { 139 case TSK_Undeclared: 140 case TSK_ExplicitSpecialization: 141 return false; 142 case TSK_ImplicitInstantiation: 143 case TSK_ExplicitInstantiationDeclaration: 144 case TSK_ExplicitInstantiationDefinition: 145 return true; 146 } 147 llvm_unreachable("invalid TemplateSpecializationKind"); 148 } 149 150 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { 151 if (isa<ObjCInterfaceDecl>(D)) 152 return false; 153 if (isa<ObjCCategoryDecl>(D)) 154 return false; 155 if (isa<ObjCIvarDecl>(D)) 156 return false; 157 if (isa<ObjCMethodDecl>(D)) 158 return false; 159 if (isa<ImportDecl>(D)) 160 return false; 161 return true; 162 } 163 164 static const CXXRecordDecl * 165 getDeclContextForTemplateInstationPattern(const Decl *D) { 166 if (const auto *CTSD = 167 dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) 168 return CTSD->getTemplateInstantiationPattern(); 169 else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) 170 return RD->getInstantiatedFromMemberClass(); 171 return nullptr; 172 } 173 174 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { 175 if (const ClassTemplateSpecializationDecl * 176 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 177 return SD->getTemplateInstantiationPattern(); 178 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 179 return FD->getTemplateInstantiationPattern(); 180 } else if (auto *VD = dyn_cast<VarDecl>(D)) { 181 return VD->getTemplateInstantiationPattern(); 182 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { 183 return RD->getInstantiatedFromMemberClass(); 184 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 185 return ED->getInstantiatedFromMemberEnum(); 186 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) { 187 const auto *ND = cast<NamedDecl>(D); 188 if (const CXXRecordDecl *Pattern = 189 getDeclContextForTemplateInstationPattern(ND)) { 190 for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) { 191 if (BaseND->isImplicit()) 192 continue; 193 if (BaseND->getKind() == ND->getKind()) 194 return BaseND; 195 } 196 } 197 } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { 198 if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { 199 if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { 200 for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) 201 return BaseECD; 202 } 203 } 204 } 205 return nullptr; 206 } 207 208 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { 209 if (auto VD = dyn_cast<VarDecl>(D)) 210 return VD->isThisDeclarationADefinition(Ctx); 211 212 if (auto FD = dyn_cast<FunctionDecl>(D)) 213 return FD->isThisDeclarationADefinition(); 214 215 if (auto TD = dyn_cast<TagDecl>(D)) 216 return TD->isThisDeclarationADefinition(); 217 218 if (auto MD = dyn_cast<ObjCMethodDecl>(D)) 219 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC); 220 221 if (isa<TypedefNameDecl>(D) || 222 isa<EnumConstantDecl>(D) || 223 isa<FieldDecl>(D) || 224 isa<MSPropertyDecl>(D) || 225 isa<ObjCImplDecl>(D) || 226 isa<ObjCPropertyImplDecl>(D)) 227 return true; 228 229 return false; 230 } 231 232 /// Whether the given NamedDecl should be skipped because it has no name. 233 static bool shouldSkipNamelessDecl(const NamedDecl *ND) { 234 return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) && 235 !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND); 236 } 237 238 static const Decl *adjustParent(const Decl *Parent) { 239 if (!Parent) 240 return nullptr; 241 for (;; Parent = cast<Decl>(Parent->getDeclContext())) { 242 if (isa<TranslationUnitDecl>(Parent)) 243 return nullptr; 244 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent)) 245 continue; 246 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) { 247 if (NS->isAnonymousNamespace()) 248 continue; 249 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) { 250 if (RD->isAnonymousStructOrUnion()) 251 continue; 252 } else if (auto ND = dyn_cast<NamedDecl>(Parent)) { 253 if (shouldSkipNamelessDecl(ND)) 254 continue; 255 } 256 return Parent; 257 } 258 } 259 260 static const Decl *getCanonicalDecl(const Decl *D) { 261 D = D->getCanonicalDecl(); 262 if (auto TD = dyn_cast<TemplateDecl>(D)) { 263 if (auto TTD = TD->getTemplatedDecl()) { 264 D = TTD; 265 assert(D->isCanonicalDecl()); 266 } 267 } 268 269 return D; 270 } 271 272 static bool shouldReportOccurrenceForSystemDeclOnlyMode( 273 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { 274 if (!IsRef) 275 return true; 276 277 auto acceptForRelation = [](SymbolRoleSet roles) -> bool { 278 bool accept = false; 279 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool { 280 switch (r) { 281 case SymbolRole::RelationChildOf: 282 case SymbolRole::RelationBaseOf: 283 case SymbolRole::RelationOverrideOf: 284 case SymbolRole::RelationExtendedBy: 285 case SymbolRole::RelationAccessorOf: 286 case SymbolRole::RelationIBTypeOf: 287 accept = true; 288 return false; 289 case SymbolRole::Declaration: 290 case SymbolRole::Definition: 291 case SymbolRole::Reference: 292 case SymbolRole::Read: 293 case SymbolRole::Write: 294 case SymbolRole::Call: 295 case SymbolRole::Dynamic: 296 case SymbolRole::AddressOf: 297 case SymbolRole::Implicit: 298 case SymbolRole::Undefinition: 299 case SymbolRole::RelationReceivedBy: 300 case SymbolRole::RelationCalledBy: 301 case SymbolRole::RelationContainedBy: 302 case SymbolRole::RelationSpecializationOf: 303 return true; 304 } 305 llvm_unreachable("Unsupported SymbolRole value!"); 306 }); 307 return accept; 308 }; 309 310 for (auto &Rel : Relations) { 311 if (acceptForRelation(Rel.Roles)) 312 return true; 313 } 314 315 return false; 316 } 317 318 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, 319 bool IsRef, const Decl *Parent, 320 SymbolRoleSet Roles, 321 ArrayRef<SymbolRelation> Relations, 322 const Expr *OrigE, 323 const Decl *OrigD, 324 const DeclContext *ContainerDC) { 325 if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) 326 return true; 327 if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D))) 328 return true; 329 330 SourceManager &SM = Ctx->getSourceManager(); 331 FileID FID = SM.getFileID(SM.getFileLoc(Loc)); 332 if (FID.isInvalid()) 333 return true; 334 335 bool Invalid = false; 336 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 337 if (Invalid || !SEntry.isFile()) 338 return true; 339 340 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 341 switch (IndexOpts.SystemSymbolFilter) { 342 case IndexingOptions::SystemSymbolFilterKind::None: 343 return true; 344 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 345 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) 346 return true; 347 break; 348 case IndexingOptions::SystemSymbolFilterKind::All: 349 break; 350 } 351 } 352 353 if (!OrigD) 354 OrigD = D; 355 356 if (isTemplateImplicitInstantiation(D)) { 357 if (!IsRef) 358 return true; 359 D = adjustTemplateImplicitInstantiation(D); 360 if (!D) 361 return true; 362 assert(!isTemplateImplicitInstantiation(D)); 363 } 364 365 if (IsRef) 366 Roles |= (unsigned)SymbolRole::Reference; 367 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) 368 Roles |= (unsigned)SymbolRole::Definition; 369 else 370 Roles |= (unsigned)SymbolRole::Declaration; 371 372 D = getCanonicalDecl(D); 373 Parent = adjustParent(Parent); 374 if (Parent) 375 Parent = getCanonicalDecl(Parent); 376 377 SmallVector<SymbolRelation, 6> FinalRelations; 378 FinalRelations.reserve(Relations.size()+1); 379 380 auto addRelation = [&](SymbolRelation Rel) { 381 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(), 382 [&](SymbolRelation Elem)->bool { 383 return Elem.RelatedSymbol == Rel.RelatedSymbol; 384 }); 385 if (It != FinalRelations.end()) { 386 It->Roles |= Rel.Roles; 387 } else { 388 FinalRelations.push_back(Rel); 389 } 390 Roles |= Rel.Roles; 391 }; 392 393 if (Parent) { 394 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) { 395 addRelation(SymbolRelation{ 396 (unsigned)SymbolRole::RelationContainedBy, 397 Parent 398 }); 399 } else { 400 addRelation(SymbolRelation{ 401 (unsigned)SymbolRole::RelationChildOf, 402 Parent 403 }); 404 } 405 } 406 407 for (auto &Rel : Relations) { 408 addRelation(SymbolRelation(Rel.Roles, 409 Rel.RelatedSymbol->getCanonicalDecl())); 410 } 411 412 IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC}; 413 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node); 414 } 415 416 void IndexingContext::handleMacroDefined(const IdentifierInfo &Name, 417 SourceLocation Loc, 418 const MacroInfo &MI) { 419 SymbolRoleSet Roles = (unsigned)SymbolRole::Definition; 420 DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); 421 } 422 423 void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name, 424 SourceLocation Loc, 425 const MacroInfo &MI) { 426 SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition; 427 DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); 428 } 429 430 void IndexingContext::handleMacroReference(const IdentifierInfo &Name, 431 SourceLocation Loc, 432 const MacroInfo &MI) { 433 SymbolRoleSet Roles = (unsigned)SymbolRole::Reference; 434 DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); 435 } 436