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