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 86 SourceManager &SM = Ctx->getSourceManager(); 87 FileID FID = SM.getFileID(SM.getFileLoc(Loc)); 88 if (FID.isInvalid()) 89 return true; 90 91 bool Invalid = false; 92 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 93 if (Invalid || !SEntry.isFile()) 94 return true; 95 96 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 97 switch (IndexOpts.SystemSymbolFilter) { 98 case IndexingOptions::SystemSymbolFilterKind::None: 99 return true; 100 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 101 case IndexingOptions::SystemSymbolFilterKind::All: 102 break; 103 } 104 } 105 106 SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration; 107 if (ImportD->isImplicit()) 108 Roles |= (unsigned)SymbolRole::Implicit; 109 110 return DataConsumer.handleModuleOccurence(ImportD, Roles, Loc); 111 } 112 113 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { 114 TemplateSpecializationKind TKind = TSK_Undeclared; 115 if (const ClassTemplateSpecializationDecl * 116 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 117 TKind = SD->getSpecializationKind(); 118 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 119 TKind = FD->getTemplateSpecializationKind(); 120 } else if (auto *VD = dyn_cast<VarDecl>(D)) { 121 TKind = VD->getTemplateSpecializationKind(); 122 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { 123 if (RD->getInstantiatedFromMemberClass()) 124 TKind = RD->getTemplateSpecializationKind(); 125 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 126 if (ED->getInstantiatedFromMemberEnum()) 127 TKind = ED->getTemplateSpecializationKind(); 128 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) || 129 isa<EnumConstantDecl>(D)) { 130 if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext())) 131 return isTemplateImplicitInstantiation(Parent); 132 } 133 switch (TKind) { 134 case TSK_Undeclared: 135 case TSK_ExplicitSpecialization: 136 return false; 137 case TSK_ImplicitInstantiation: 138 case TSK_ExplicitInstantiationDeclaration: 139 case TSK_ExplicitInstantiationDefinition: 140 return true; 141 } 142 llvm_unreachable("invalid TemplateSpecializationKind"); 143 } 144 145 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { 146 if (isa<ObjCInterfaceDecl>(D)) 147 return false; 148 if (isa<ObjCCategoryDecl>(D)) 149 return false; 150 if (isa<ObjCIvarDecl>(D)) 151 return false; 152 if (isa<ObjCMethodDecl>(D)) 153 return false; 154 if (isa<ImportDecl>(D)) 155 return false; 156 return true; 157 } 158 159 static const CXXRecordDecl * 160 getDeclContextForTemplateInstationPattern(const Decl *D) { 161 if (const auto *CTSD = 162 dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) 163 return CTSD->getTemplateInstantiationPattern(); 164 else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) 165 return RD->getInstantiatedFromMemberClass(); 166 return nullptr; 167 } 168 169 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { 170 if (const ClassTemplateSpecializationDecl * 171 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 172 return SD->getTemplateInstantiationPattern(); 173 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 174 return FD->getTemplateInstantiationPattern(); 175 } else if (auto *VD = dyn_cast<VarDecl>(D)) { 176 return VD->getTemplateInstantiationPattern(); 177 } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { 178 return RD->getInstantiatedFromMemberClass(); 179 } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { 180 return ED->getInstantiatedFromMemberEnum(); 181 } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) { 182 const auto *ND = cast<NamedDecl>(D); 183 if (const CXXRecordDecl *Pattern = 184 getDeclContextForTemplateInstationPattern(ND)) { 185 for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) { 186 if (BaseND->isImplicit()) 187 continue; 188 if (BaseND->getKind() == ND->getKind()) 189 return BaseND; 190 } 191 } 192 } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { 193 if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { 194 if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { 195 for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) 196 return BaseECD; 197 } 198 } 199 } 200 return nullptr; 201 } 202 203 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { 204 if (auto VD = dyn_cast<VarDecl>(D)) 205 return VD->isThisDeclarationADefinition(Ctx); 206 207 if (auto FD = dyn_cast<FunctionDecl>(D)) 208 return FD->isThisDeclarationADefinition(); 209 210 if (auto TD = dyn_cast<TagDecl>(D)) 211 return TD->isThisDeclarationADefinition(); 212 213 if (auto MD = dyn_cast<ObjCMethodDecl>(D)) 214 return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC); 215 216 if (isa<TypedefNameDecl>(D) || 217 isa<EnumConstantDecl>(D) || 218 isa<FieldDecl>(D) || 219 isa<MSPropertyDecl>(D) || 220 isa<ObjCImplDecl>(D) || 221 isa<ObjCPropertyImplDecl>(D)) 222 return true; 223 224 return false; 225 } 226 227 /// Whether the given NamedDecl should be skipped because it has no name. 228 static bool shouldSkipNamelessDecl(const NamedDecl *ND) { 229 return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) && 230 !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND); 231 } 232 233 static const Decl *adjustParent(const Decl *Parent) { 234 if (!Parent) 235 return nullptr; 236 for (;; Parent = cast<Decl>(Parent->getDeclContext())) { 237 if (isa<TranslationUnitDecl>(Parent)) 238 return nullptr; 239 if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent)) 240 continue; 241 if (auto NS = dyn_cast<NamespaceDecl>(Parent)) { 242 if (NS->isAnonymousNamespace()) 243 continue; 244 } else if (auto RD = dyn_cast<RecordDecl>(Parent)) { 245 if (RD->isAnonymousStructOrUnion()) 246 continue; 247 } else if (auto ND = dyn_cast<NamedDecl>(Parent)) { 248 if (shouldSkipNamelessDecl(ND)) 249 continue; 250 } 251 return Parent; 252 } 253 } 254 255 static const Decl *getCanonicalDecl(const Decl *D) { 256 D = D->getCanonicalDecl(); 257 if (auto TD = dyn_cast<TemplateDecl>(D)) { 258 if (auto TTD = TD->getTemplatedDecl()) { 259 D = TTD; 260 assert(D->isCanonicalDecl()); 261 } 262 } 263 264 return D; 265 } 266 267 static bool shouldReportOccurrenceForSystemDeclOnlyMode( 268 bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { 269 if (!IsRef) 270 return true; 271 272 auto acceptForRelation = [](SymbolRoleSet roles) -> bool { 273 bool accept = false; 274 applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool { 275 switch (r) { 276 case SymbolRole::RelationChildOf: 277 case SymbolRole::RelationBaseOf: 278 case SymbolRole::RelationOverrideOf: 279 case SymbolRole::RelationExtendedBy: 280 case SymbolRole::RelationAccessorOf: 281 case SymbolRole::RelationIBTypeOf: 282 accept = true; 283 return false; 284 case SymbolRole::Declaration: 285 case SymbolRole::Definition: 286 case SymbolRole::Reference: 287 case SymbolRole::Read: 288 case SymbolRole::Write: 289 case SymbolRole::Call: 290 case SymbolRole::Dynamic: 291 case SymbolRole::AddressOf: 292 case SymbolRole::Implicit: 293 case SymbolRole::RelationReceivedBy: 294 case SymbolRole::RelationCalledBy: 295 case SymbolRole::RelationContainedBy: 296 case SymbolRole::RelationSpecializationOf: 297 return true; 298 } 299 llvm_unreachable("Unsupported SymbolRole value!"); 300 }); 301 return accept; 302 }; 303 304 for (auto &Rel : Relations) { 305 if (acceptForRelation(Rel.Roles)) 306 return true; 307 } 308 309 return false; 310 } 311 312 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, 313 bool IsRef, const Decl *Parent, 314 SymbolRoleSet Roles, 315 ArrayRef<SymbolRelation> Relations, 316 const Expr *OrigE, 317 const Decl *OrigD, 318 const DeclContext *ContainerDC) { 319 if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) 320 return true; 321 if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D))) 322 return true; 323 324 SourceManager &SM = Ctx->getSourceManager(); 325 FileID FID = SM.getFileID(SM.getFileLoc(Loc)); 326 if (FID.isInvalid()) 327 return true; 328 329 bool Invalid = false; 330 const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); 331 if (Invalid || !SEntry.isFile()) 332 return true; 333 334 if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { 335 switch (IndexOpts.SystemSymbolFilter) { 336 case IndexingOptions::SystemSymbolFilterKind::None: 337 return true; 338 case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: 339 if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) 340 return true; 341 break; 342 case IndexingOptions::SystemSymbolFilterKind::All: 343 break; 344 } 345 } 346 347 if (isTemplateImplicitInstantiation(D)) { 348 if (!IsRef) 349 return true; 350 D = adjustTemplateImplicitInstantiation(D); 351 if (!D) 352 return true; 353 assert(!isTemplateImplicitInstantiation(D)); 354 } 355 356 if (!OrigD) 357 OrigD = D; 358 359 if (IsRef) 360 Roles |= (unsigned)SymbolRole::Reference; 361 else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) 362 Roles |= (unsigned)SymbolRole::Definition; 363 else 364 Roles |= (unsigned)SymbolRole::Declaration; 365 366 D = getCanonicalDecl(D); 367 Parent = adjustParent(Parent); 368 if (Parent) 369 Parent = getCanonicalDecl(Parent); 370 371 SmallVector<SymbolRelation, 6> FinalRelations; 372 FinalRelations.reserve(Relations.size()+1); 373 374 auto addRelation = [&](SymbolRelation Rel) { 375 auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(), 376 [&](SymbolRelation Elem)->bool { 377 return Elem.RelatedSymbol == Rel.RelatedSymbol; 378 }); 379 if (It != FinalRelations.end()) { 380 It->Roles |= Rel.Roles; 381 } else { 382 FinalRelations.push_back(Rel); 383 } 384 Roles |= Rel.Roles; 385 }; 386 387 if (Parent) { 388 if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) { 389 addRelation(SymbolRelation{ 390 (unsigned)SymbolRole::RelationContainedBy, 391 Parent 392 }); 393 } else { 394 addRelation(SymbolRelation{ 395 (unsigned)SymbolRole::RelationChildOf, 396 Parent 397 }); 398 } 399 } 400 401 for (auto &Rel : Relations) { 402 addRelation(SymbolRelation(Rel.Roles, 403 Rel.RelatedSymbol->getCanonicalDecl())); 404 } 405 406 IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC}; 407 return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node); 408 } 409