17330f729Sjoerg //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines the ASTImporterLookupTable class which implements a
107330f729Sjoerg // lookup procedure for the import mechanism.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "clang/AST/ASTImporterLookupTable.h"
157330f729Sjoerg #include "clang/AST/Decl.h"
167330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
177330f729Sjoerg
187330f729Sjoerg namespace clang {
197330f729Sjoerg
207330f729Sjoerg namespace {
217330f729Sjoerg
227330f729Sjoerg struct Builder : RecursiveASTVisitor<Builder> {
237330f729Sjoerg ASTImporterLookupTable <
Builderclang::__anond11c4a580111::Builder247330f729Sjoerg Builder(ASTImporterLookupTable <) : LT(LT) {}
25*e038c9c4Sjoerg
VisitTypedefNameDeclclang::__anond11c4a580111::Builder26*e038c9c4Sjoerg bool VisitTypedefNameDecl(TypedefNameDecl *D) {
27*e038c9c4Sjoerg QualType Ty = D->getUnderlyingType();
28*e038c9c4Sjoerg Ty = Ty.getCanonicalType();
29*e038c9c4Sjoerg if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
30*e038c9c4Sjoerg LT.add(RTy->getAsRecordDecl());
31*e038c9c4Sjoerg // iterate over the field decls, adding them
32*e038c9c4Sjoerg for (auto *it : RTy->getAsRecordDecl()->fields()) {
33*e038c9c4Sjoerg LT.add(it);
34*e038c9c4Sjoerg }
35*e038c9c4Sjoerg }
36*e038c9c4Sjoerg return true;
37*e038c9c4Sjoerg }
38*e038c9c4Sjoerg
VisitNamedDeclclang::__anond11c4a580111::Builder397330f729Sjoerg bool VisitNamedDecl(NamedDecl *D) {
407330f729Sjoerg LT.add(D);
417330f729Sjoerg return true;
427330f729Sjoerg }
437330f729Sjoerg // In most cases the FriendDecl contains the declaration of the befriended
447330f729Sjoerg // class as a child node, so it is discovered during the recursive
457330f729Sjoerg // visitation. However, there are cases when the befriended class is not a
467330f729Sjoerg // child, thus it must be fetched explicitly from the FriendDecl, and only
477330f729Sjoerg // then can we add it to the lookup table.
VisitFriendDeclclang::__anond11c4a580111::Builder487330f729Sjoerg bool VisitFriendDecl(FriendDecl *D) {
497330f729Sjoerg if (D->getFriendType()) {
507330f729Sjoerg QualType Ty = D->getFriendType()->getType();
517330f729Sjoerg if (isa<ElaboratedType>(Ty))
527330f729Sjoerg Ty = cast<ElaboratedType>(Ty)->getNamedType();
537330f729Sjoerg // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
547330f729Sjoerg // always has that decl as child node.
557330f729Sjoerg // However, there are non-dependent cases which does not have the
567330f729Sjoerg // type as a child node. We have to dig up that type now.
577330f729Sjoerg if (!Ty->isDependentType()) {
587330f729Sjoerg if (const auto *RTy = dyn_cast<RecordType>(Ty))
597330f729Sjoerg LT.add(RTy->getAsCXXRecordDecl());
607330f729Sjoerg else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
617330f729Sjoerg LT.add(SpecTy->getAsCXXRecordDecl());
62*e038c9c4Sjoerg else if (const auto *SubstTy =
63*e038c9c4Sjoerg dyn_cast<SubstTemplateTypeParmType>(Ty)) {
64*e038c9c4Sjoerg if (SubstTy->getAsCXXRecordDecl())
65*e038c9c4Sjoerg LT.add(SubstTy->getAsCXXRecordDecl());
66*e038c9c4Sjoerg } else if (isa<TypedefType>(Ty)) {
677330f729Sjoerg // We do not put friend typedefs to the lookup table because
687330f729Sjoerg // ASTImporter does not organize typedefs into redecl chains.
697330f729Sjoerg } else {
707330f729Sjoerg llvm_unreachable("Unhandled type of friend class");
717330f729Sjoerg }
727330f729Sjoerg }
737330f729Sjoerg }
747330f729Sjoerg return true;
757330f729Sjoerg }
767330f729Sjoerg
777330f729Sjoerg // Override default settings of base.
shouldVisitTemplateInstantiationsclang::__anond11c4a580111::Builder787330f729Sjoerg bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCodeclang::__anond11c4a580111::Builder797330f729Sjoerg bool shouldVisitImplicitCode() const { return true; }
807330f729Sjoerg };
817330f729Sjoerg
827330f729Sjoerg } // anonymous namespace
837330f729Sjoerg
ASTImporterLookupTable(TranslationUnitDecl & TU)847330f729Sjoerg ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
857330f729Sjoerg Builder B(*this);
867330f729Sjoerg B.TraverseDecl(&TU);
877330f729Sjoerg }
887330f729Sjoerg
add(DeclContext * DC,NamedDecl * ND)897330f729Sjoerg void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
907330f729Sjoerg DeclList &Decls = LookupTable[DC][ND->getDeclName()];
917330f729Sjoerg // Inserts if and only if there is no element in the container equal to it.
927330f729Sjoerg Decls.insert(ND);
937330f729Sjoerg }
947330f729Sjoerg
remove(DeclContext * DC,NamedDecl * ND)957330f729Sjoerg void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
967330f729Sjoerg DeclList &Decls = LookupTable[DC][ND->getDeclName()];
977330f729Sjoerg bool EraseResult = Decls.remove(ND);
987330f729Sjoerg (void)EraseResult;
997330f729Sjoerg assert(EraseResult == true && "Trying to remove not contained Decl");
1007330f729Sjoerg }
1017330f729Sjoerg
add(NamedDecl * ND)1027330f729Sjoerg void ASTImporterLookupTable::add(NamedDecl *ND) {
1037330f729Sjoerg assert(ND);
1047330f729Sjoerg DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
1057330f729Sjoerg add(DC, ND);
1067330f729Sjoerg DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
1077330f729Sjoerg if (DC != ReDC)
1087330f729Sjoerg add(ReDC, ND);
1097330f729Sjoerg }
1107330f729Sjoerg
remove(NamedDecl * ND)1117330f729Sjoerg void ASTImporterLookupTable::remove(NamedDecl *ND) {
1127330f729Sjoerg assert(ND);
1137330f729Sjoerg DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
1147330f729Sjoerg remove(DC, ND);
1157330f729Sjoerg DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
1167330f729Sjoerg if (DC != ReDC)
1177330f729Sjoerg remove(ReDC, ND);
1187330f729Sjoerg }
1197330f729Sjoerg
1207330f729Sjoerg ASTImporterLookupTable::LookupResult
lookup(DeclContext * DC,DeclarationName Name) const1217330f729Sjoerg ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
1227330f729Sjoerg auto DCI = LookupTable.find(DC->getPrimaryContext());
1237330f729Sjoerg if (DCI == LookupTable.end())
1247330f729Sjoerg return {};
1257330f729Sjoerg
1267330f729Sjoerg const auto &FoundNameMap = DCI->second;
1277330f729Sjoerg auto NamesI = FoundNameMap.find(Name);
1287330f729Sjoerg if (NamesI == FoundNameMap.end())
1297330f729Sjoerg return {};
1307330f729Sjoerg
1317330f729Sjoerg return NamesI->second;
1327330f729Sjoerg }
1337330f729Sjoerg
dump(DeclContext * DC) const1347330f729Sjoerg void ASTImporterLookupTable::dump(DeclContext *DC) const {
1357330f729Sjoerg auto DCI = LookupTable.find(DC->getPrimaryContext());
1367330f729Sjoerg if (DCI == LookupTable.end())
1377330f729Sjoerg llvm::errs() << "empty\n";
1387330f729Sjoerg const auto &FoundNameMap = DCI->second;
1397330f729Sjoerg for (const auto &Entry : FoundNameMap) {
1407330f729Sjoerg DeclarationName Name = Entry.first;
1417330f729Sjoerg llvm::errs() << "==== Name: ";
1427330f729Sjoerg Name.dump();
1437330f729Sjoerg const DeclList& List = Entry.second;
1447330f729Sjoerg for (NamedDecl *ND : List) {
1457330f729Sjoerg ND->dump();
1467330f729Sjoerg }
1477330f729Sjoerg }
1487330f729Sjoerg }
1497330f729Sjoerg
dump() const1507330f729Sjoerg void ASTImporterLookupTable::dump() const {
1517330f729Sjoerg for (const auto &Entry : LookupTable) {
1527330f729Sjoerg DeclContext *DC = Entry.first;
1537330f729Sjoerg StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
1547330f729Sjoerg llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
1557330f729Sjoerg dump(DC);
1567330f729Sjoerg }
1577330f729Sjoerg }
1587330f729Sjoerg
1597330f729Sjoerg } // namespace clang
160