1//===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- C++ -*---===// 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#ifndef LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H 15#define LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H 16 17#include "clang/AST/DeclBase.h" // lookup_result 18#include "clang/AST/DeclarationName.h" 19#include "llvm/ADT/DenseMap.h" 20#include "llvm/ADT/SetVector.h" 21 22namespace clang { 23 24class NamedDecl; 25class DeclContext; 26 27// There are certain cases when normal C/C++ lookup (localUncachedLookup) 28// does not find AST nodes. E.g.: 29// Example 1: 30// template <class T> 31// struct X { 32// friend void foo(); // this is never found in the DC of the TU. 33// }; 34// Example 2: 35// // The fwd decl to Foo is not found in the lookupPtr of the DC of the 36// // translation unit decl. 37// // Here we could find the node by doing a traverse throught the list of 38// // the Decls in the DC, but that would not scale. 39// struct A { struct Foo *p; }; 40// This is a severe problem because the importer decides if it has to create a 41// new Decl or not based on the lookup results. 42// To overcome these cases we need an importer specific lookup table which 43// holds every node and we are not interested in any C/C++ specific visibility 44// considerations. Simply, we must know if there is an existing Decl in a 45// given DC. Once we found it then we can handle any visibility related tasks. 46class ASTImporterLookupTable { 47 48 // We store a list of declarations for each name. 49 // And we collect these lists for each DeclContext. 50 // We could have a flat map with (DeclContext, Name) tuple as key, but a two 51 // level map seems easier to handle. 52 using DeclList = llvm::SmallSetVector<NamedDecl *, 2>; 53 using NameMap = llvm::SmallDenseMap<DeclarationName, DeclList, 4>; 54 using DCMap = llvm::DenseMap<DeclContext *, NameMap>; 55 56 void add(DeclContext *DC, NamedDecl *ND); 57 void remove(DeclContext *DC, NamedDecl *ND); 58 59 DCMap LookupTable; 60 61public: 62 ASTImporterLookupTable(TranslationUnitDecl &TU); 63 void add(NamedDecl *ND); 64 void remove(NamedDecl *ND); 65 // Sometimes a declaration is created first with a temporarily value of decl 66 // context (often the translation unit) and later moved to the final context. 67 // This happens for declarations that are created before the final declaration 68 // context. In such cases the lookup table needs to be updated. 69 // (The declaration is in these cases not added to the temporary decl context, 70 // only its parent is set.) 71 // FIXME: It would be better to not add the declaration to the temporary 72 // context at all in the lookup table, but this requires big change in 73 // ASTImporter. 74 // The function should be called when the old context is definitely different 75 // from the new. 76 void update(NamedDecl *ND, DeclContext *OldDC); 77 // Same as 'update' but allow if 'ND' is not in the table or the old context 78 // is the same as the new. 79 // FIXME: The old redeclaration context is not handled. 80 void updateForced(NamedDecl *ND, DeclContext *OldDC); 81 using LookupResult = DeclList; 82 LookupResult lookup(DeclContext *DC, DeclarationName Name) const; 83 // Check if the `ND` is within the lookup table (with its current name) in 84 // context `DC`. This is intended for debug purposes when the DeclContext of a 85 // NamedDecl is changed. 86 bool contains(DeclContext *DC, NamedDecl *ND) const; 87 void dump(DeclContext *DC) const; 88 void dump() const; 89}; 90 91} // namespace clang 92 93#endif // LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H 94