Home | History | Annotate | Line # | Download | only in AST
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 //  This file defines the ASTImporterLookupTable class which implements a
     10 //  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 
     18 namespace clang {
     19 
     20 namespace {
     21 
     22 struct Builder : RecursiveASTVisitor<Builder> {
     23   ASTImporterLookupTable &LT;
     24   Builder(ASTImporterLookupTable &LT) : LT(LT) {}
     25 
     26   bool VisitTypedefNameDecl(TypedefNameDecl *D) {
     27     QualType Ty = D->getUnderlyingType();
     28     Ty = Ty.getCanonicalType();
     29     if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
     30       LT.add(RTy->getAsRecordDecl());
     31       // iterate over the field decls, adding them
     32       for (auto *it : RTy->getAsRecordDecl()->fields()) {
     33         LT.add(it);
     34       }
     35     }
     36     return true;
     37   }
     38 
     39   bool VisitNamedDecl(NamedDecl *D) {
     40     LT.add(D);
     41     return true;
     42   }
     43   // In most cases the FriendDecl contains the declaration of the befriended
     44   // class as a child node, so it is discovered during the recursive
     45   // visitation. However, there are cases when the befriended class is not a
     46   // child, thus it must be fetched explicitly from the FriendDecl, and only
     47   // then can we add it to the lookup table.
     48   bool VisitFriendDecl(FriendDecl *D) {
     49     if (D->getFriendType()) {
     50       QualType Ty = D->getFriendType()->getType();
     51       if (isa<ElaboratedType>(Ty))
     52         Ty = cast<ElaboratedType>(Ty)->getNamedType();
     53       // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
     54       // always has that decl as child node.
     55       // However, there are non-dependent cases which does not have the
     56       // type as a child node. We have to dig up that type now.
     57       if (!Ty->isDependentType()) {
     58         if (const auto *RTy = dyn_cast<RecordType>(Ty))
     59           LT.add(RTy->getAsCXXRecordDecl());
     60         else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
     61           LT.add(SpecTy->getAsCXXRecordDecl());
     62         else if (const auto *SubstTy =
     63                      dyn_cast<SubstTemplateTypeParmType>(Ty)) {
     64           if (SubstTy->getAsCXXRecordDecl())
     65             LT.add(SubstTy->getAsCXXRecordDecl());
     66         } else if (isa<TypedefType>(Ty)) {
     67           // We do not put friend typedefs to the lookup table because
     68           // ASTImporter does not organize typedefs into redecl chains.
     69         } else {
     70           llvm_unreachable("Unhandled type of friend class");
     71         }
     72       }
     73     }
     74     return true;
     75   }
     76 
     77   // Override default settings of base.
     78   bool shouldVisitTemplateInstantiations() const { return true; }
     79   bool shouldVisitImplicitCode() const { return true; }
     80 };
     81 
     82 } // anonymous namespace
     83 
     84 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
     85   Builder B(*this);
     86   B.TraverseDecl(&TU);
     87 }
     88 
     89 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
     90   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
     91   // Inserts if and only if there is no element in the container equal to it.
     92   Decls.insert(ND);
     93 }
     94 
     95 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
     96   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
     97   bool EraseResult = Decls.remove(ND);
     98   (void)EraseResult;
     99   assert(EraseResult == true && "Trying to remove not contained Decl");
    100 }
    101 
    102 void ASTImporterLookupTable::add(NamedDecl *ND) {
    103   assert(ND);
    104   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
    105   add(DC, ND);
    106   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
    107   if (DC != ReDC)
    108     add(ReDC, ND);
    109 }
    110 
    111 void ASTImporterLookupTable::remove(NamedDecl *ND) {
    112   assert(ND);
    113   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
    114   remove(DC, ND);
    115   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
    116   if (DC != ReDC)
    117     remove(ReDC, ND);
    118 }
    119 
    120 ASTImporterLookupTable::LookupResult
    121 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
    122   auto DCI = LookupTable.find(DC->getPrimaryContext());
    123   if (DCI == LookupTable.end())
    124     return {};
    125 
    126   const auto &FoundNameMap = DCI->second;
    127   auto NamesI = FoundNameMap.find(Name);
    128   if (NamesI == FoundNameMap.end())
    129     return {};
    130 
    131   return NamesI->second;
    132 }
    133 
    134 void ASTImporterLookupTable::dump(DeclContext *DC) const {
    135   auto DCI = LookupTable.find(DC->getPrimaryContext());
    136   if (DCI == LookupTable.end())
    137     llvm::errs() << "empty\n";
    138   const auto &FoundNameMap = DCI->second;
    139   for (const auto &Entry : FoundNameMap) {
    140     DeclarationName Name = Entry.first;
    141     llvm::errs() << "==== Name: ";
    142     Name.dump();
    143     const DeclList& List = Entry.second;
    144     for (NamedDecl *ND : List) {
    145       ND->dump();
    146     }
    147   }
    148 }
    149 
    150 void ASTImporterLookupTable::dump() const {
    151   for (const auto &Entry : LookupTable) {
    152     DeclContext *DC = Entry.first;
    153     StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
    154     llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
    155     dump(DC);
    156   }
    157 }
    158 
    159 } // namespace clang
    160