brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 29c3af1 Raw
206 lines · cpp
1//===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//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//  This file defines the ASTImporterLookupTable class which implements a10//  lookup procedure for the import mechanism.11//12//===----------------------------------------------------------------------===//13 14#include "clang/AST/ASTImporterLookupTable.h"15#include "clang/AST/Decl.h"16#include "clang/AST/RecursiveASTVisitor.h"17#include "llvm/Support/FormatVariadic.h"18 19namespace clang {20 21namespace {22 23struct Builder : RecursiveASTVisitor<Builder> {24  ASTImporterLookupTable &LT;25  Builder(ASTImporterLookupTable &LT) : LT(LT) {}26 27  bool VisitTypedefNameDecl(TypedefNameDecl *D) {28    QualType Ty = D->getUnderlyingType();29    Ty = Ty.getCanonicalType();30    if (const auto *RTy = dyn_cast<RecordType>(Ty)) {31      LT.add(RTy->getAsRecordDecl());32      // iterate over the field decls, adding them33      for (auto *it : RTy->getAsRecordDecl()->fields()) {34        LT.add(it);35      }36    }37    return true;38  }39 40  bool VisitNamedDecl(NamedDecl *D) {41    LT.add(D);42    return true;43  }44  // In most cases the FriendDecl contains the declaration of the befriended45  // class as a child node, so it is discovered during the recursive46  // visitation. However, there are cases when the befriended class is not a47  // child, thus it must be fetched explicitly from the FriendDecl, and only48  // then can we add it to the lookup table.49  bool VisitFriendDecl(FriendDecl *D) {50    if (D->getFriendType()) {51      QualType Ty = D->getFriendType()->getType();52      // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)53      // always has that decl as child node.54      // However, there are non-dependent cases which does not have the55      // type as a child node. We have to dig up that type now.56      if (!Ty->isDependentType()) {57        if (const auto *RTy = dyn_cast<RecordType>(Ty))58          LT.add(RTy->getAsCXXRecordDecl());59        else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))60          LT.add(SpecTy->getAsCXXRecordDecl());61        else if (const auto *SubstTy =62                     dyn_cast<SubstTemplateTypeParmType>(Ty)) {63          if (SubstTy->getAsCXXRecordDecl())64            LT.add(SubstTy->getAsCXXRecordDecl());65        } else {66          if (isa<TypedefType>(Ty)) {67            // We do not put friend typedefs to the lookup table because68            // ASTImporter does not organize typedefs into redecl chains.69          } else if (isa<UsingType>(Ty)) {70            // Similar to TypedefType, not putting into lookup table.71          } else {72            llvm_unreachable("Unhandled type of friend class");73          }74        }75      }76    }77    return true;78  }79 80  // Override default settings of base.81  bool shouldVisitTemplateInstantiations() const { return true; }82  bool shouldVisitImplicitCode() const { return true; }83};84 85} // anonymous namespace86 87ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {88  Builder B(*this);89  B.TraverseDecl(&TU);90  // The VaList declaration may be created on demand only or not traversed.91  // To ensure it is present and found during import, add it to the table now.92  if (auto *D =93          dyn_cast_or_null<NamedDecl>(TU.getASTContext().getVaListTagDecl())) {94    // On some platforms (AArch64) the VaList declaration can be inside a 'std'95    // namespace. This is handled specially and not visible by AST traversal.96    // ASTImporter must be able to find this namespace to import the VaList97    // declaration (and the namespace) correctly.98    if (auto *Ns = dyn_cast<NamespaceDecl>(D->getDeclContext()))99      add(&TU, Ns);100    add(D->getDeclContext(), D);101  }102}103 104void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {105  DeclList &Decls = LookupTable[DC][ND->getDeclName()];106  // Inserts if and only if there is no element in the container equal to it.107  Decls.insert(ND);108}109 110void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {111  const DeclarationName Name = ND->getDeclName();112  DeclList &Decls = LookupTable[DC][Name];113  bool EraseResult = Decls.remove(ND);114  (void)EraseResult;115#ifndef NDEBUG116  if (!EraseResult) {117    std::string Message =118        llvm::formatv(119            "Trying to remove not contained Decl '{0}' of type {1} from a {2}",120            Name.getAsString(), ND->getDeclKindName(), DC->getDeclKindName())121            .str();122    llvm_unreachable(Message.c_str());123  }124#endif125}126 127void ASTImporterLookupTable::add(NamedDecl *ND) {128  assert(ND);129  DeclContext *DC = ND->getDeclContext();130  add(DC, ND);131  DeclContext *ReDC = DC->getRedeclContext();132  if (DC != ReDC)133    add(ReDC, ND);134}135 136void ASTImporterLookupTable::remove(NamedDecl *ND) {137  assert(ND);138  DeclContext *DC = ND->getDeclContext();139  remove(DC, ND);140  DeclContext *ReDC = DC->getRedeclContext();141  if (DC != ReDC)142    remove(ReDC, ND);143}144 145void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {146  assert(OldDC != ND->getDeclContext() &&147         "DeclContext should be changed before update");148  if (contains(ND->getDeclContext(), ND)) {149    assert(!contains(OldDC, ND) &&150           "Decl should not be found in the old context if already in the new");151    return;152  }153 154  remove(OldDC, ND);155  add(ND);156}157 158void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) {159  LookupTable[OldDC][ND->getDeclName()].remove(ND);160  add(ND);161}162 163ASTImporterLookupTable::LookupResult164ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {165  auto DCI = LookupTable.find(DC);166  if (DCI == LookupTable.end())167    return {};168 169  const auto &FoundNameMap = DCI->second;170  auto NamesI = FoundNameMap.find(Name);171  if (NamesI == FoundNameMap.end())172    return {};173 174  return NamesI->second;175}176 177bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {178  return lookup(DC, ND->getDeclName()).contains(ND);179}180 181void ASTImporterLookupTable::dump(DeclContext *DC) const {182  auto DCI = LookupTable.find(DC);183  if (DCI == LookupTable.end())184    llvm::errs() << "empty\n";185  const auto &FoundNameMap = DCI->second;186  for (const auto &Entry : FoundNameMap) {187    DeclarationName Name = Entry.first;188    llvm::errs() << "==== Name: ";189    Name.dump();190    const DeclList& List = Entry.second;191    for (NamedDecl *ND : List) {192      ND->dump();193    }194  }195}196 197void ASTImporterLookupTable::dump() const {198  for (const auto &Entry : LookupTable) {199    DeclContext *DC = Entry.first;200    llvm::errs() << "== DC:" << cast<Decl>(DC) << "\n";201    dump(DC);202  }203}204 205} // namespace clang206