brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · 3c1e038 Raw
292 lines · cpp
1//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "IndexingContext.h"10#include "clang/AST/ASTConcept.h"11#include "clang/AST/PrettyPrinter.h"12#include "clang/AST/RecursiveASTVisitor.h"13#include "clang/AST/TypeLoc.h"14#include "clang/Sema/HeuristicResolver.h"15#include "llvm/ADT/ScopeExit.h"16 17using namespace clang;18using namespace index;19 20namespace {21 22class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {23  IndexingContext &IndexCtx;24  const NamedDecl *Parent;25  const DeclContext *ParentDC;26  bool IsBase;27  SmallVector<SymbolRelation, 3> Relations;28 29  typedef RecursiveASTVisitor<TypeIndexer> base;30 31public:32  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,33              const DeclContext *DC, bool isBase, bool isIBType)34    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {35    if (IsBase) {36      assert(Parent);37      Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);38    }39    if (isIBType) {40      assert(Parent);41      Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);42    }43  }44 45  bool shouldWalkTypesOfTypeLocs() const { return false; }46 47#define TRY_TO(CALL_EXPR)                                                      \48  do {                                                                         \49    if (!CALL_EXPR)                                                            \50      return false;                                                            \51  } while (0)52 53  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {54    SourceLocation Loc = TTPL.getNameLoc();55    TemplateTypeParmDecl *TTPD = TTPL.getDecl();56    return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,57                                    SymbolRoleSet());58  }59 60  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {61    SourceLocation Loc = TL.getNameLoc();62    TypedefNameDecl *ND = TL.getDecl();63    if (ND->isTransparentTag()) {64      auto *Underlying = ND->getUnderlyingType()->castAsTagDecl();65      return IndexCtx.handleReference(Underlying, Loc, Parent,66                                      ParentDC, SymbolRoleSet(), Relations);67    }68    if (IsBase) {69      TRY_TO(IndexCtx.handleReference(ND, Loc,70                                      Parent, ParentDC, SymbolRoleSet()));71      if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {72        TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,73                                        (unsigned)SymbolRole::Implicit,74                                        Relations));75      }76    } else {77      TRY_TO(IndexCtx.handleReference(ND, Loc,78                                      Parent, ParentDC, SymbolRoleSet(),79                                      Relations));80    }81    return true;82  }83 84  bool VisitAutoTypeLoc(AutoTypeLoc TL) {85    if (auto *C = TL.getNamedConcept())86      return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent,87                                      ParentDC);88    return true;89  }90 91  bool traverseParamVarHelper(ParmVarDecl *D) {92    TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));93    if (D->getTypeSourceInfo())94      TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));95    return true;96  }97 98  bool TraverseParmVarDecl(ParmVarDecl *D) {99    // Avoid visiting default arguments from the definition that were already100    // visited in the declaration.101    // FIXME: A free function definition can have default arguments.102    // Avoiding double visitaiton of default arguments should be handled by the103    // visitor probably with a bit in the AST to indicate if the attached104    // default argument was 'inherited' or written in source.105    if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {106      if (FD->isThisDeclarationADefinition()) {107        return traverseParamVarHelper(D);108      }109    }110 111    return base::TraverseParmVarDecl(D);112  }113 114  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {115    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);116    return true;117  }118 119  bool VisitTagTypeLoc(TagTypeLoc TL) {120    TagDecl *D = TL.getDecl();121    if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&122        D->getParentFunctionOrMethod())123      return true;124 125    if (TL.isDefinition()) {126      IndexCtx.indexTagDecl(D);127      return true;128    }129 130    return IndexCtx.handleReference(D, TL.getNameLoc(),131                                    Parent, ParentDC, SymbolRoleSet(),132                                    Relations);133  }134 135  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {136    return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),137                                    Parent, ParentDC, SymbolRoleSet(), Relations);138  }139 140  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {141    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {142      IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),143                               Parent, ParentDC, SymbolRoleSet(), Relations);144    }145    return true;146  }147 148  void HandleTemplateSpecializationTypeLoc(TemplateName TemplName,149                                           SourceLocation TemplNameLoc,150                                           CXXRecordDecl *ResolvedClass,151                                           bool IsTypeAlias) {152    // In presence of type aliases, the resolved class was never written in153    // the code so don't report it.154    if (!IsTypeAlias && ResolvedClass &&155        (!ResolvedClass->isImplicit() ||156         IndexCtx.shouldIndexImplicitInstantiation())) {157      IndexCtx.handleReference(ResolvedClass, TemplNameLoc, Parent, ParentDC,158                               SymbolRoleSet(), Relations);159    } else if (const TemplateDecl *D = TemplName.getAsTemplateDecl()) {160      IndexCtx.handleReference(D, TemplNameLoc, Parent, ParentDC,161                               SymbolRoleSet(), Relations);162    }163  }164 165  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {166    auto *T = TL.getTypePtr();167    if (!T)168      return true;169    HandleTemplateSpecializationTypeLoc(170        T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),171        T->isTypeAlias());172    return true;173  }174 175  bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL,176                                             bool TraverseQualifier) {177    if (!WalkUpFromTemplateSpecializationTypeLoc(TL))178      return false;179    if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName()))180      return false;181 182    // The relations we have to `Parent` do not apply to our template arguments,183    // so clear them while visiting the args.184    SmallVector<SymbolRelation, 3> SavedRelations = Relations;185    Relations.clear();186    auto ResetSavedRelations =187        llvm::make_scope_exit([&] { this->Relations = SavedRelations; });188    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {189      if (!TraverseTemplateArgumentLoc(TL.getArgLoc(I)))190        return false;191    }192 193    return true;194  }195 196  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {197    auto *T = TL.getTypePtr();198    if (!T)199      return true;200    HandleTemplateSpecializationTypeLoc(201        T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),202        /*IsTypeAlias=*/false);203    return true;204  }205 206  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {207    std::vector<const NamedDecl *> Symbols =208        IndexCtx.getResolver()->resolveDependentNameType(TL.getTypePtr());209    if (Symbols.size() != 1)210      return true;211    return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,212                                    ParentDC, SymbolRoleSet(), Relations);213  }214 215  bool TraverseStmt(Stmt *S) {216    IndexCtx.indexBody(S, Parent, ParentDC);217    return true;218  }219};220 221} // anonymous namespace222 223void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,224                                          const NamedDecl *Parent,225                                          const DeclContext *DC,226                                          bool isBase,227                                          bool isIBType) {228  if (!TInfo || TInfo->getTypeLoc().isNull())229    return;230 231  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);232}233 234void IndexingContext::indexTypeLoc(TypeLoc TL,235                                   const NamedDecl *Parent,236                                   const DeclContext *DC,237                                   bool isBase,238                                   bool isIBType) {239  if (TL.isNull())240    return;241 242  if (!DC)243    DC = Parent->getLexicalDeclContext();244  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);245}246 247void IndexingContext::indexNestedNameSpecifierLoc(248    NestedNameSpecifierLoc QualifierLoc, const NamedDecl *Parent,249    const DeclContext *DC) {250  if (!DC)251    DC = Parent->getLexicalDeclContext();252  switch (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();253          Qualifier.getKind()) {254  case NestedNameSpecifier::Kind::Null:255  case NestedNameSpecifier::Kind::Global:256  case NestedNameSpecifier::Kind::MicrosoftSuper:257    break;258 259  case NestedNameSpecifier::Kind::Namespace: {260    auto [Namespace, Prefix] = QualifierLoc.castAsNamespaceAndPrefix();261    indexNestedNameSpecifierLoc(Prefix, Parent, DC);262    handleReference(Namespace, QualifierLoc.getLocalBeginLoc(), Parent, DC,263                    SymbolRoleSet());264    break;265  }266 267  case NestedNameSpecifier::Kind::Type:268    indexTypeLoc(QualifierLoc.castAsTypeLoc(), Parent, DC);269    break;270  }271}272 273void IndexingContext::indexTagDecl(const TagDecl *D,274                                   ArrayRef<SymbolRelation> Relations) {275  if (!shouldIndex(D))276    return;277  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))278    return;279 280  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {281    if (D->isThisDeclarationADefinition()) {282      indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);283      if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {284        for (const auto &I : CXXRD->bases()) {285          indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);286        }287      }288      indexDeclContext(D);289    }290  }291}292