[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / lib / AST / ASTImporterLookupTable.cpp
bloba193e97bbf5a06395c5dfdf0ffc63f80bf5d1ff4
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.
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTImporterLookupTable.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/RecursiveASTVisitor.h"
17 #include "llvm/Support/FormatVariadic.h"
19 namespace clang {
21 namespace {
23 struct Builder : RecursiveASTVisitor<Builder> {
24 ASTImporterLookupTable &LT;
25 Builder(ASTImporterLookupTable &LT) : LT(LT) {}
27 bool VisitTypedefNameDecl(TypedefNameDecl *D) {
28 QualType Ty = D->getUnderlyingType();
29 Ty = Ty.getCanonicalType();
30 if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
31 LT.add(RTy->getAsRecordDecl());
32 // iterate over the field decls, adding them
33 for (auto *it : RTy->getAsRecordDecl()->fields()) {
34 LT.add(it);
37 return true;
40 bool VisitNamedDecl(NamedDecl *D) {
41 LT.add(D);
42 return true;
44 // In most cases the FriendDecl contains the declaration of the befriended
45 // class as a child node, so it is discovered during the recursive
46 // visitation. However, there are cases when the befriended class is not a
47 // child, thus it must be fetched explicitly from the FriendDecl, and only
48 // then can we add it to the lookup table.
49 bool VisitFriendDecl(FriendDecl *D) {
50 if (D->getFriendType()) {
51 QualType Ty = D->getFriendType()->getType();
52 if (isa<ElaboratedType>(Ty))
53 Ty = cast<ElaboratedType>(Ty)->getNamedType();
54 // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
55 // always has that decl as child node.
56 // However, there are non-dependent cases which does not have the
57 // type as a child node. We have to dig up that type now.
58 if (!Ty->isDependentType()) {
59 if (const auto *RTy = dyn_cast<RecordType>(Ty))
60 LT.add(RTy->getAsCXXRecordDecl());
61 else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
62 LT.add(SpecTy->getAsCXXRecordDecl());
63 else if (const auto *SubstTy =
64 dyn_cast<SubstTemplateTypeParmType>(Ty)) {
65 if (SubstTy->getAsCXXRecordDecl())
66 LT.add(SubstTy->getAsCXXRecordDecl());
67 } else if (isa<TypedefType>(Ty)) {
68 // We do not put friend typedefs to the lookup table because
69 // ASTImporter does not organize typedefs into redecl chains.
70 } else if (isa<UsingType>(Ty)) {
71 // Similar to TypedefType, not putting into lookup table.
72 } else {
73 llvm_unreachable("Unhandled type of friend class");
77 return true;
80 // Override default settings of base.
81 bool shouldVisitTemplateInstantiations() const { return true; }
82 bool shouldVisitImplicitCode() const { return true; }
85 } // anonymous namespace
87 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
88 Builder B(*this);
89 B.TraverseDecl(&TU);
92 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
93 DeclList &Decls = LookupTable[DC][ND->getDeclName()];
94 // Inserts if and only if there is no element in the container equal to it.
95 Decls.insert(ND);
98 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
99 const DeclarationName Name = ND->getDeclName();
100 DeclList &Decls = LookupTable[DC][Name];
101 bool EraseResult = Decls.remove(ND);
102 (void)EraseResult;
103 #ifndef NDEBUG
104 if (!EraseResult) {
105 std::string Message =
106 llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
107 Name.getAsString(), DC->getDeclKindName())
108 .str();
109 llvm_unreachable(Message.c_str());
111 #endif
114 void ASTImporterLookupTable::add(NamedDecl *ND) {
115 assert(ND);
116 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
117 add(DC, ND);
118 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
119 if (DC != ReDC)
120 add(ReDC, ND);
123 void ASTImporterLookupTable::remove(NamedDecl *ND) {
124 assert(ND);
125 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
126 remove(DC, ND);
127 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
128 if (DC != ReDC)
129 remove(ReDC, ND);
132 void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {
133 assert(OldDC != ND->getDeclContext() &&
134 "DeclContext should be changed before update");
135 if (contains(ND->getDeclContext(), ND)) {
136 assert(!contains(OldDC, ND) &&
137 "Decl should not be found in the old context if already in the new");
138 return;
141 remove(OldDC, ND);
142 add(ND);
145 void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) {
146 LookupTable[OldDC][ND->getDeclName()].remove(ND);
147 add(ND);
150 ASTImporterLookupTable::LookupResult
151 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
152 auto DCI = LookupTable.find(DC->getPrimaryContext());
153 if (DCI == LookupTable.end())
154 return {};
156 const auto &FoundNameMap = DCI->second;
157 auto NamesI = FoundNameMap.find(Name);
158 if (NamesI == FoundNameMap.end())
159 return {};
161 return NamesI->second;
164 bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
165 return lookup(DC, ND->getDeclName()).contains(ND);
168 void ASTImporterLookupTable::dump(DeclContext *DC) const {
169 auto DCI = LookupTable.find(DC->getPrimaryContext());
170 if (DCI == LookupTable.end())
171 llvm::errs() << "empty\n";
172 const auto &FoundNameMap = DCI->second;
173 for (const auto &Entry : FoundNameMap) {
174 DeclarationName Name = Entry.first;
175 llvm::errs() << "==== Name: ";
176 Name.dump();
177 const DeclList& List = Entry.second;
178 for (NamedDecl *ND : List) {
179 ND->dump();
184 void ASTImporterLookupTable::dump() const {
185 for (const auto &Entry : LookupTable) {
186 DeclContext *DC = Entry.first;
187 StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
188 llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
189 dump(DC);
193 } // namespace clang