160 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| //  This file defines the ASTImporterLookupTable class which implements a
 | |
| //  lookup procedure for the import mechanism.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "clang/AST/ASTImporterLookupTable.h"
 | |
| #include "clang/AST/Decl.h"
 | |
| #include "clang/AST/RecursiveASTVisitor.h"
 | |
| 
 | |
| namespace clang {
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| struct Builder : RecursiveASTVisitor<Builder> {
 | |
|   ASTImporterLookupTable <
 | |
|   Builder(ASTImporterLookupTable <) : LT(LT) {}
 | |
| 
 | |
|   bool VisitTypedefNameDecl(TypedefNameDecl *D) {
 | |
|     QualType Ty = D->getUnderlyingType();
 | |
|     Ty = Ty.getCanonicalType();
 | |
|     if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
 | |
|       LT.add(RTy->getAsRecordDecl());
 | |
|       // iterate over the field decls, adding them
 | |
|       for (auto *it : RTy->getAsRecordDecl()->fields()) {
 | |
|         LT.add(it);
 | |
|       }
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool VisitNamedDecl(NamedDecl *D) {
 | |
|     LT.add(D);
 | |
|     return true;
 | |
|   }
 | |
|   // In most cases the FriendDecl contains the declaration of the befriended
 | |
|   // class as a child node, so it is discovered during the recursive
 | |
|   // visitation. However, there are cases when the befriended class is not a
 | |
|   // child, thus it must be fetched explicitly from the FriendDecl, and only
 | |
|   // then can we add it to the lookup table.
 | |
|   bool VisitFriendDecl(FriendDecl *D) {
 | |
|     if (D->getFriendType()) {
 | |
|       QualType Ty = D->getFriendType()->getType();
 | |
|       if (isa<ElaboratedType>(Ty))
 | |
|         Ty = cast<ElaboratedType>(Ty)->getNamedType();
 | |
|       // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
 | |
|       // always has that decl as child node.
 | |
|       // However, there are non-dependent cases which does not have the
 | |
|       // type as a child node. We have to dig up that type now.
 | |
|       if (!Ty->isDependentType()) {
 | |
|         if (const auto *RTy = dyn_cast<RecordType>(Ty))
 | |
|           LT.add(RTy->getAsCXXRecordDecl());
 | |
|         else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
 | |
|           LT.add(SpecTy->getAsCXXRecordDecl());
 | |
|         else if (const auto *SubstTy =
 | |
|                      dyn_cast<SubstTemplateTypeParmType>(Ty)) {
 | |
|           if (SubstTy->getAsCXXRecordDecl())
 | |
|             LT.add(SubstTy->getAsCXXRecordDecl());
 | |
|         } else if (isa<TypedefType>(Ty)) {
 | |
|           // We do not put friend typedefs to the lookup table because
 | |
|           // ASTImporter does not organize typedefs into redecl chains.
 | |
|         } else {
 | |
|           llvm_unreachable("Unhandled type of friend class");
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // Override default settings of base.
 | |
|   bool shouldVisitTemplateInstantiations() const { return true; }
 | |
|   bool shouldVisitImplicitCode() const { return true; }
 | |
| };
 | |
| 
 | |
| } // anonymous namespace
 | |
| 
 | |
| ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
 | |
|   Builder B(*this);
 | |
|   B.TraverseDecl(&TU);
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
 | |
|   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
 | |
|   // Inserts if and only if there is no element in the container equal to it.
 | |
|   Decls.insert(ND);
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
 | |
|   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
 | |
|   bool EraseResult = Decls.remove(ND);
 | |
|   (void)EraseResult;
 | |
|   assert(EraseResult == true && "Trying to remove not contained Decl");
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::add(NamedDecl *ND) {
 | |
|   assert(ND);
 | |
|   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
 | |
|   add(DC, ND);
 | |
|   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
 | |
|   if (DC != ReDC)
 | |
|     add(ReDC, ND);
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::remove(NamedDecl *ND) {
 | |
|   assert(ND);
 | |
|   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
 | |
|   remove(DC, ND);
 | |
|   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
 | |
|   if (DC != ReDC)
 | |
|     remove(ReDC, ND);
 | |
| }
 | |
| 
 | |
| ASTImporterLookupTable::LookupResult
 | |
| ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
 | |
|   auto DCI = LookupTable.find(DC->getPrimaryContext());
 | |
|   if (DCI == LookupTable.end())
 | |
|     return {};
 | |
| 
 | |
|   const auto &FoundNameMap = DCI->second;
 | |
|   auto NamesI = FoundNameMap.find(Name);
 | |
|   if (NamesI == FoundNameMap.end())
 | |
|     return {};
 | |
| 
 | |
|   return NamesI->second;
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::dump(DeclContext *DC) const {
 | |
|   auto DCI = LookupTable.find(DC->getPrimaryContext());
 | |
|   if (DCI == LookupTable.end())
 | |
|     llvm::errs() << "empty\n";
 | |
|   const auto &FoundNameMap = DCI->second;
 | |
|   for (const auto &Entry : FoundNameMap) {
 | |
|     DeclarationName Name = Entry.first;
 | |
|     llvm::errs() << "==== Name: ";
 | |
|     Name.dump();
 | |
|     const DeclList& List = Entry.second;
 | |
|     for (NamedDecl *ND : List) {
 | |
|       ND->dump();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void ASTImporterLookupTable::dump() const {
 | |
|   for (const auto &Entry : LookupTable) {
 | |
|     DeclContext *DC = Entry.first;
 | |
|     StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
 | |
|     llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
 | |
|     dump(DC);
 | |
|   }
 | |
| }
 | |
| 
 | |
| } // namespace clang
 |