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 } 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::RelationReceivedBy: 299 case SymbolRole::RelationCalledBy: 300 case SymbolRole::RelationContainedBy: 301 case SymbolRole::RelationSpecializationOf: 302 return true; 303 } 304 llvm_unreachable("Unsupported SymbolRole value!"); 305 }); 306 return accept; 307 }; 308 309 for (auto &Rel : Relations) { 310 if (acceptForRelation(Rel.Roles)) 311 return true; 312 } 313 314 return false; 315 } 316 317 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, 318 bool IsRef, const Decl *Parent, 319 SymbolRoleSet Roles, 320 ArrayRef<SymbolRelation> Relations, 321 const Expr *OrigE, 322 const Decl *OrigD, 323 const DeclContext *ContainerDC) { 324 if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) 325 return true; 326 if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D))) 327 return true; 328 329 SourceManager &SM = Ctx->getSourceManager(); 330 Loc = SM.getFileLoc(Loc); 331 if (Loc.isInvalid()) 332 return true; 333 334 FileID FID; 335 unsigned Offset; 336 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); 337 if (FID.isInvalid()) 338 return true; 339 340 bool Invalid = false; 341 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 342 if (Invalid || !SEntry.isFile()) 343 return true; 344 345 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 346 switch (IndexOpts.SystemSymbolFilter) { 347 case IndexingOptions::SystemSymbolFilterKind::None: 348 return true; 349 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 350 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) 351 return true; 352 break; 353 case IndexingOptions::SystemSymbolFilterKind::All: 354 break; 355 } 356 } 357 358 if (isTemplateImplicitInstantiation(D)) { 359 if (!IsRef) 360 return true; 361 D = adjustTemplateImplicitInstantiation(D); 362 if (!D) 363 return true; 364 assert(!isTemplateImplicitInstantiation(D)); 365 } 366 367 if (!OrigD) 368 OrigD = D; 369 370 if (IsRef) 371 Roles |= (unsigned)SymbolRole::Reference; 372 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) 373 Roles |= (unsigned)SymbolRole::Definition; 374 else 375 Roles |= (unsigned)SymbolRole::Declaration; 376 377 D = getCanonicalDecl(D); 378 Parent = adjustParent(Parent); 379 if (Parent) 380 Parent = getCanonicalDecl(Parent); 381 382 SmallVector<SymbolRelation, 6> FinalRelations; 383 FinalRelations.reserve(Relations.size()+1); 384 385 auto addRelation = [&](SymbolRelation Rel) { 386 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(), 387 [&](SymbolRelation Elem)->bool { 388 return Elem.RelatedSymbol == Rel.RelatedSymbol; 389 }); 390 if (It != FinalRelations.end()) { 391 It->Roles |= Rel.Roles; 392 } else { 393 FinalRelations.push_back(Rel); 394 } 395 Roles |= Rel.Roles; 396 }; 397 398 if (Parent) { 399 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) { 400 addRelation(SymbolRelation{ 401 (unsigned)SymbolRole::RelationContainedBy, 402 Parent 403 }); 404 } else { 405 addRelation(SymbolRelation{ 406 (unsigned)SymbolRole::RelationChildOf, 407 Parent 408 }); 409 } 410 } 411 412 for (auto &Rel : Relations) { 413 addRelation(SymbolRelation(Rel.Roles, 414 Rel.RelatedSymbol->getCanonicalDecl())); 415 } 416 417 IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC }; 418 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset, 419 Node); 420 } 421