1e5dd7070Spatrick //===- DeclBase.cpp - Declaration AST Node Implementation -----------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the Decl and DeclContext classes.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/AST/DeclBase.h"
14e5dd7070Spatrick #include "clang/AST/ASTContext.h"
15e5dd7070Spatrick #include "clang/AST/ASTLambda.h"
16e5dd7070Spatrick #include "clang/AST/ASTMutationListener.h"
17e5dd7070Spatrick #include "clang/AST/Attr.h"
18e5dd7070Spatrick #include "clang/AST/AttrIterator.h"
19e5dd7070Spatrick #include "clang/AST/Decl.h"
20e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
21e5dd7070Spatrick #include "clang/AST/DeclContextInternals.h"
22e5dd7070Spatrick #include "clang/AST/DeclFriend.h"
23e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
24e5dd7070Spatrick #include "clang/AST/DeclOpenMP.h"
25e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
26e5dd7070Spatrick #include "clang/AST/DependentDiagnostic.h"
27e5dd7070Spatrick #include "clang/AST/ExternalASTSource.h"
28e5dd7070Spatrick #include "clang/AST/Stmt.h"
29e5dd7070Spatrick #include "clang/AST/Type.h"
30e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
31e5dd7070Spatrick #include "clang/Basic/LLVM.h"
32e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
33e5dd7070Spatrick #include "clang/Basic/ObjCRuntime.h"
34e5dd7070Spatrick #include "clang/Basic/PartialDiagnostic.h"
35e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
36e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
37e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h"
38e5dd7070Spatrick #include "llvm/ADT/PointerIntPair.h"
39e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
40e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
41e5dd7070Spatrick #include "llvm/Support/Casting.h"
42e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
43e5dd7070Spatrick #include "llvm/Support/MathExtras.h"
44e5dd7070Spatrick #include "llvm/Support/VersionTuple.h"
45e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
46e5dd7070Spatrick #include <algorithm>
47e5dd7070Spatrick #include <cassert>
48e5dd7070Spatrick #include <cstddef>
49e5dd7070Spatrick #include <string>
50e5dd7070Spatrick #include <tuple>
51e5dd7070Spatrick #include <utility>
52e5dd7070Spatrick
53e5dd7070Spatrick using namespace clang;
54e5dd7070Spatrick
55e5dd7070Spatrick //===----------------------------------------------------------------------===//
56e5dd7070Spatrick // Statistics
57e5dd7070Spatrick //===----------------------------------------------------------------------===//
58e5dd7070Spatrick
59e5dd7070Spatrick #define DECL(DERIVED, BASE) static int n##DERIVED##s = 0;
60e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
61e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
62e5dd7070Spatrick
updateOutOfDate(IdentifierInfo & II) const63e5dd7070Spatrick void Decl::updateOutOfDate(IdentifierInfo &II) const {
64e5dd7070Spatrick getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
65e5dd7070Spatrick }
66e5dd7070Spatrick
67e5dd7070Spatrick #define DECL(DERIVED, BASE) \
68e5dd7070Spatrick static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \
69e5dd7070Spatrick "Alignment sufficient after objects prepended to " #DERIVED);
70e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
71e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
72e5dd7070Spatrick
operator new(std::size_t Size,const ASTContext & Context,unsigned ID,std::size_t Extra)73e5dd7070Spatrick void *Decl::operator new(std::size_t Size, const ASTContext &Context,
74e5dd7070Spatrick unsigned ID, std::size_t Extra) {
75e5dd7070Spatrick // Allocate an extra 8 bytes worth of storage, which ensures that the
76e5dd7070Spatrick // resulting pointer will still be 8-byte aligned.
77e5dd7070Spatrick static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
78e5dd7070Spatrick "Decl won't be misaligned");
79e5dd7070Spatrick void *Start = Context.Allocate(Size + Extra + 8);
80e5dd7070Spatrick void *Result = (char*)Start + 8;
81e5dd7070Spatrick
82e5dd7070Spatrick unsigned *PrefixPtr = (unsigned *)Result - 2;
83e5dd7070Spatrick
84e5dd7070Spatrick // Zero out the first 4 bytes; this is used to store the owning module ID.
85e5dd7070Spatrick PrefixPtr[0] = 0;
86e5dd7070Spatrick
87e5dd7070Spatrick // Store the global declaration ID in the second 4 bytes.
88e5dd7070Spatrick PrefixPtr[1] = ID;
89e5dd7070Spatrick
90e5dd7070Spatrick return Result;
91e5dd7070Spatrick }
92e5dd7070Spatrick
operator new(std::size_t Size,const ASTContext & Ctx,DeclContext * Parent,std::size_t Extra)93e5dd7070Spatrick void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
94e5dd7070Spatrick DeclContext *Parent, std::size_t Extra) {
95e5dd7070Spatrick assert(!Parent || &Parent->getParentASTContext() == &Ctx);
96e5dd7070Spatrick // With local visibility enabled, we track the owning module even for local
97e5dd7070Spatrick // declarations. We create the TU decl early and may not yet know what the
98e5dd7070Spatrick // LangOpts are, so conservatively allocate the storage.
99e5dd7070Spatrick if (Ctx.getLangOpts().trackLocalOwningModule() || !Parent) {
100e5dd7070Spatrick // Ensure required alignment of the resulting object by adding extra
101e5dd7070Spatrick // padding at the start if required.
102e5dd7070Spatrick size_t ExtraAlign =
103e5dd7070Spatrick llvm::offsetToAlignment(sizeof(Module *), llvm::Align(alignof(Decl)));
104e5dd7070Spatrick auto *Buffer = reinterpret_cast<char *>(
105e5dd7070Spatrick ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
106e5dd7070Spatrick Buffer += ExtraAlign;
107e5dd7070Spatrick auto *ParentModule =
108e5dd7070Spatrick Parent ? cast<Decl>(Parent)->getOwningModule() : nullptr;
109e5dd7070Spatrick return new (Buffer) Module*(ParentModule) + 1;
110e5dd7070Spatrick }
111e5dd7070Spatrick return ::operator new(Size + Extra, Ctx);
112e5dd7070Spatrick }
113e5dd7070Spatrick
getOwningModuleSlow() const114e5dd7070Spatrick Module *Decl::getOwningModuleSlow() const {
115e5dd7070Spatrick assert(isFromASTFile() && "Not from AST file?");
116e5dd7070Spatrick return getASTContext().getExternalSource()->getModule(getOwningModuleID());
117e5dd7070Spatrick }
118e5dd7070Spatrick
hasLocalOwningModuleStorage() const119e5dd7070Spatrick bool Decl::hasLocalOwningModuleStorage() const {
120e5dd7070Spatrick return getASTContext().getLangOpts().trackLocalOwningModule();
121e5dd7070Spatrick }
122e5dd7070Spatrick
getDeclKindName() const123e5dd7070Spatrick const char *Decl::getDeclKindName() const {
124e5dd7070Spatrick switch (DeclKind) {
125e5dd7070Spatrick default: llvm_unreachable("Declaration not in DeclNodes.inc!");
126e5dd7070Spatrick #define DECL(DERIVED, BASE) case DERIVED: return #DERIVED;
127e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
128e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
129e5dd7070Spatrick }
130e5dd7070Spatrick }
131e5dd7070Spatrick
setInvalidDecl(bool Invalid)132e5dd7070Spatrick void Decl::setInvalidDecl(bool Invalid) {
133e5dd7070Spatrick InvalidDecl = Invalid;
134e5dd7070Spatrick assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition());
135e5dd7070Spatrick if (!Invalid) {
136e5dd7070Spatrick return;
137e5dd7070Spatrick }
138e5dd7070Spatrick
139e5dd7070Spatrick if (!isa<ParmVarDecl>(this)) {
140e5dd7070Spatrick // Defensive maneuver for ill-formed code: we're likely not to make it to
141e5dd7070Spatrick // a point where we set the access specifier, so default it to "public"
142e5dd7070Spatrick // to avoid triggering asserts elsewhere in the front end.
143e5dd7070Spatrick setAccess(AS_public);
144e5dd7070Spatrick }
145e5dd7070Spatrick
146e5dd7070Spatrick // Marking a DecompositionDecl as invalid implies all the child BindingDecl's
147e5dd7070Spatrick // are invalid too.
148e5dd7070Spatrick if (auto *DD = dyn_cast<DecompositionDecl>(this)) {
149e5dd7070Spatrick for (auto *Binding : DD->bindings()) {
150e5dd7070Spatrick Binding->setInvalidDecl();
151e5dd7070Spatrick }
152e5dd7070Spatrick }
153e5dd7070Spatrick }
154e5dd7070Spatrick
hasValidDeclKind() const155*12c85518Srobert bool DeclContext::hasValidDeclKind() const {
156*12c85518Srobert switch (getDeclKind()) {
157*12c85518Srobert #define DECL(DERIVED, BASE) case Decl::DERIVED: return true;
158*12c85518Srobert #define ABSTRACT_DECL(DECL)
159*12c85518Srobert #include "clang/AST/DeclNodes.inc"
160*12c85518Srobert }
161*12c85518Srobert return false;
162*12c85518Srobert }
163*12c85518Srobert
getDeclKindName() const164e5dd7070Spatrick const char *DeclContext::getDeclKindName() const {
165e5dd7070Spatrick switch (getDeclKind()) {
166e5dd7070Spatrick #define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
167e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
168e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
169e5dd7070Spatrick }
170e5dd7070Spatrick llvm_unreachable("Declaration context not in DeclNodes.inc!");
171e5dd7070Spatrick }
172e5dd7070Spatrick
173e5dd7070Spatrick bool Decl::StatisticsEnabled = false;
EnableStatistics()174e5dd7070Spatrick void Decl::EnableStatistics() {
175e5dd7070Spatrick StatisticsEnabled = true;
176e5dd7070Spatrick }
177e5dd7070Spatrick
PrintStats()178e5dd7070Spatrick void Decl::PrintStats() {
179e5dd7070Spatrick llvm::errs() << "\n*** Decl Stats:\n";
180e5dd7070Spatrick
181e5dd7070Spatrick int totalDecls = 0;
182e5dd7070Spatrick #define DECL(DERIVED, BASE) totalDecls += n##DERIVED##s;
183e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
184e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
185e5dd7070Spatrick llvm::errs() << " " << totalDecls << " decls total.\n";
186e5dd7070Spatrick
187e5dd7070Spatrick int totalBytes = 0;
188e5dd7070Spatrick #define DECL(DERIVED, BASE) \
189e5dd7070Spatrick if (n##DERIVED##s > 0) { \
190e5dd7070Spatrick totalBytes += (int)(n##DERIVED##s * sizeof(DERIVED##Decl)); \
191e5dd7070Spatrick llvm::errs() << " " << n##DERIVED##s << " " #DERIVED " decls, " \
192e5dd7070Spatrick << sizeof(DERIVED##Decl) << " each (" \
193e5dd7070Spatrick << n##DERIVED##s * sizeof(DERIVED##Decl) \
194e5dd7070Spatrick << " bytes)\n"; \
195e5dd7070Spatrick }
196e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
197e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
198e5dd7070Spatrick
199e5dd7070Spatrick llvm::errs() << "Total bytes = " << totalBytes << "\n";
200e5dd7070Spatrick }
201e5dd7070Spatrick
add(Kind k)202e5dd7070Spatrick void Decl::add(Kind k) {
203e5dd7070Spatrick switch (k) {
204e5dd7070Spatrick #define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break;
205e5dd7070Spatrick #define ABSTRACT_DECL(DECL)
206e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
207e5dd7070Spatrick }
208e5dd7070Spatrick }
209e5dd7070Spatrick
isTemplateParameterPack() const210e5dd7070Spatrick bool Decl::isTemplateParameterPack() const {
211e5dd7070Spatrick if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(this))
212e5dd7070Spatrick return TTP->isParameterPack();
213e5dd7070Spatrick if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(this))
214e5dd7070Spatrick return NTTP->isParameterPack();
215e5dd7070Spatrick if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(this))
216e5dd7070Spatrick return TTP->isParameterPack();
217e5dd7070Spatrick return false;
218e5dd7070Spatrick }
219e5dd7070Spatrick
isParameterPack() const220e5dd7070Spatrick bool Decl::isParameterPack() const {
221e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(this))
222e5dd7070Spatrick return Var->isParameterPack();
223e5dd7070Spatrick
224e5dd7070Spatrick return isTemplateParameterPack();
225e5dd7070Spatrick }
226e5dd7070Spatrick
getAsFunction()227e5dd7070Spatrick FunctionDecl *Decl::getAsFunction() {
228e5dd7070Spatrick if (auto *FD = dyn_cast<FunctionDecl>(this))
229e5dd7070Spatrick return FD;
230e5dd7070Spatrick if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
231e5dd7070Spatrick return FTD->getTemplatedDecl();
232e5dd7070Spatrick return nullptr;
233e5dd7070Spatrick }
234e5dd7070Spatrick
isTemplateDecl() const235e5dd7070Spatrick bool Decl::isTemplateDecl() const {
236e5dd7070Spatrick return isa<TemplateDecl>(this);
237e5dd7070Spatrick }
238e5dd7070Spatrick
getDescribedTemplate() const239e5dd7070Spatrick TemplateDecl *Decl::getDescribedTemplate() const {
240e5dd7070Spatrick if (auto *FD = dyn_cast<FunctionDecl>(this))
241e5dd7070Spatrick return FD->getDescribedFunctionTemplate();
242a9ac8606Spatrick if (auto *RD = dyn_cast<CXXRecordDecl>(this))
243e5dd7070Spatrick return RD->getDescribedClassTemplate();
244a9ac8606Spatrick if (auto *VD = dyn_cast<VarDecl>(this))
245e5dd7070Spatrick return VD->getDescribedVarTemplate();
246a9ac8606Spatrick if (auto *AD = dyn_cast<TypeAliasDecl>(this))
247e5dd7070Spatrick return AD->getDescribedAliasTemplate();
248e5dd7070Spatrick
249e5dd7070Spatrick return nullptr;
250e5dd7070Spatrick }
251e5dd7070Spatrick
getDescribedTemplateParams() const252ec727ea7Spatrick const TemplateParameterList *Decl::getDescribedTemplateParams() const {
253ec727ea7Spatrick if (auto *TD = getDescribedTemplate())
254ec727ea7Spatrick return TD->getTemplateParameters();
255ec727ea7Spatrick if (auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this))
256ec727ea7Spatrick return CTPSD->getTemplateParameters();
257ec727ea7Spatrick if (auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(this))
258ec727ea7Spatrick return VTPSD->getTemplateParameters();
259ec727ea7Spatrick return nullptr;
260ec727ea7Spatrick }
261ec727ea7Spatrick
isTemplated() const262e5dd7070Spatrick bool Decl::isTemplated() const {
263ec727ea7Spatrick // A declaration is templated if it is a template or a template pattern, or
264*12c85518Srobert // is within (lexcially for a friend or local function declaration,
265*12c85518Srobert // semantically otherwise) a dependent context.
266e5dd7070Spatrick if (auto *AsDC = dyn_cast<DeclContext>(this))
267e5dd7070Spatrick return AsDC->isDependentContext();
268*12c85518Srobert auto *DC = getFriendObjectKind() || isLocalExternDecl()
269*12c85518Srobert ? getLexicalDeclContext() : getDeclContext();
270ec727ea7Spatrick return DC->isDependentContext() || isTemplateDecl() ||
271ec727ea7Spatrick getDescribedTemplateParams();
272ec727ea7Spatrick }
273ec727ea7Spatrick
getTemplateDepth() const274ec727ea7Spatrick unsigned Decl::getTemplateDepth() const {
275ec727ea7Spatrick if (auto *DC = dyn_cast<DeclContext>(this))
276ec727ea7Spatrick if (DC->isFileContext())
277ec727ea7Spatrick return 0;
278ec727ea7Spatrick
279ec727ea7Spatrick if (auto *TPL = getDescribedTemplateParams())
280ec727ea7Spatrick return TPL->getDepth() + 1;
281ec727ea7Spatrick
282ec727ea7Spatrick // If this is a dependent lambda, there might be an enclosing variable
283ec727ea7Spatrick // template. In this case, the next step is not the parent DeclContext (or
284ec727ea7Spatrick // even a DeclContext at all).
285ec727ea7Spatrick auto *RD = dyn_cast<CXXRecordDecl>(this);
286ec727ea7Spatrick if (RD && RD->isDependentLambda())
287ec727ea7Spatrick if (Decl *Context = RD->getLambdaContextDecl())
288ec727ea7Spatrick return Context->getTemplateDepth();
289ec727ea7Spatrick
290ec727ea7Spatrick const DeclContext *DC =
291ec727ea7Spatrick getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
292ec727ea7Spatrick return cast<Decl>(DC)->getTemplateDepth();
293e5dd7070Spatrick }
294e5dd7070Spatrick
getParentFunctionOrMethod(bool LexicalParent) const295*12c85518Srobert const DeclContext *Decl::getParentFunctionOrMethod(bool LexicalParent) const {
296*12c85518Srobert for (const DeclContext *DC = LexicalParent ? getLexicalDeclContext()
297*12c85518Srobert : getDeclContext();
298*12c85518Srobert DC && !DC->isFileContext(); DC = DC->getParent())
299e5dd7070Spatrick if (DC->isFunctionOrMethod())
300e5dd7070Spatrick return DC;
301e5dd7070Spatrick
302e5dd7070Spatrick return nullptr;
303e5dd7070Spatrick }
304e5dd7070Spatrick
305e5dd7070Spatrick //===----------------------------------------------------------------------===//
306e5dd7070Spatrick // PrettyStackTraceDecl Implementation
307e5dd7070Spatrick //===----------------------------------------------------------------------===//
308e5dd7070Spatrick
print(raw_ostream & OS) const309e5dd7070Spatrick void PrettyStackTraceDecl::print(raw_ostream &OS) const {
310e5dd7070Spatrick SourceLocation TheLoc = Loc;
311e5dd7070Spatrick if (TheLoc.isInvalid() && TheDecl)
312e5dd7070Spatrick TheLoc = TheDecl->getLocation();
313e5dd7070Spatrick
314e5dd7070Spatrick if (TheLoc.isValid()) {
315e5dd7070Spatrick TheLoc.print(OS, SM);
316e5dd7070Spatrick OS << ": ";
317e5dd7070Spatrick }
318e5dd7070Spatrick
319e5dd7070Spatrick OS << Message;
320e5dd7070Spatrick
321e5dd7070Spatrick if (const auto *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) {
322e5dd7070Spatrick OS << " '";
323e5dd7070Spatrick DN->printQualifiedName(OS);
324e5dd7070Spatrick OS << '\'';
325e5dd7070Spatrick }
326e5dd7070Spatrick OS << '\n';
327e5dd7070Spatrick }
328e5dd7070Spatrick
329e5dd7070Spatrick //===----------------------------------------------------------------------===//
330e5dd7070Spatrick // Decl Implementation
331e5dd7070Spatrick //===----------------------------------------------------------------------===//
332e5dd7070Spatrick
333e5dd7070Spatrick // Out-of-line virtual method providing a home for Decl.
334e5dd7070Spatrick Decl::~Decl() = default;
335e5dd7070Spatrick
setDeclContext(DeclContext * DC)336e5dd7070Spatrick void Decl::setDeclContext(DeclContext *DC) {
337e5dd7070Spatrick DeclCtx = DC;
338e5dd7070Spatrick }
339e5dd7070Spatrick
setLexicalDeclContext(DeclContext * DC)340e5dd7070Spatrick void Decl::setLexicalDeclContext(DeclContext *DC) {
341e5dd7070Spatrick if (DC == getLexicalDeclContext())
342e5dd7070Spatrick return;
343e5dd7070Spatrick
344e5dd7070Spatrick if (isInSemaDC()) {
345e5dd7070Spatrick setDeclContextsImpl(getDeclContext(), DC, getASTContext());
346e5dd7070Spatrick } else {
347e5dd7070Spatrick getMultipleDC()->LexicalDC = DC;
348e5dd7070Spatrick }
349e5dd7070Spatrick
350e5dd7070Spatrick // FIXME: We shouldn't be changing the lexical context of declarations
351e5dd7070Spatrick // imported from AST files.
352e5dd7070Spatrick if (!isFromASTFile()) {
353e5dd7070Spatrick setModuleOwnershipKind(getModuleOwnershipKindForChildOf(DC));
354e5dd7070Spatrick if (hasOwningModule())
355e5dd7070Spatrick setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
356e5dd7070Spatrick }
357e5dd7070Spatrick
358e5dd7070Spatrick assert(
359e5dd7070Spatrick (getModuleOwnershipKind() != ModuleOwnershipKind::VisibleWhenImported ||
360e5dd7070Spatrick getOwningModule()) &&
361e5dd7070Spatrick "hidden declaration has no owning module");
362e5dd7070Spatrick }
363e5dd7070Spatrick
setDeclContextsImpl(DeclContext * SemaDC,DeclContext * LexicalDC,ASTContext & Ctx)364e5dd7070Spatrick void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
365e5dd7070Spatrick ASTContext &Ctx) {
366e5dd7070Spatrick if (SemaDC == LexicalDC) {
367e5dd7070Spatrick DeclCtx = SemaDC;
368e5dd7070Spatrick } else {
369e5dd7070Spatrick auto *MDC = new (Ctx) Decl::MultipleDC();
370e5dd7070Spatrick MDC->SemanticDC = SemaDC;
371e5dd7070Spatrick MDC->LexicalDC = LexicalDC;
372e5dd7070Spatrick DeclCtx = MDC;
373e5dd7070Spatrick }
374e5dd7070Spatrick }
375e5dd7070Spatrick
isInLocalScopeForInstantiation() const376ec727ea7Spatrick bool Decl::isInLocalScopeForInstantiation() const {
377e5dd7070Spatrick const DeclContext *LDC = getLexicalDeclContext();
378ec727ea7Spatrick if (!LDC->isDependentContext())
379ec727ea7Spatrick return false;
380e5dd7070Spatrick while (true) {
381e5dd7070Spatrick if (LDC->isFunctionOrMethod())
382e5dd7070Spatrick return true;
383e5dd7070Spatrick if (!isa<TagDecl>(LDC))
384e5dd7070Spatrick return false;
385389bb291Spatrick if (const auto *CRD = dyn_cast<CXXRecordDecl>(LDC))
386389bb291Spatrick if (CRD->isLambda())
387389bb291Spatrick return true;
388e5dd7070Spatrick LDC = LDC->getLexicalParent();
389e5dd7070Spatrick }
390e5dd7070Spatrick return false;
391e5dd7070Spatrick }
392e5dd7070Spatrick
isInAnonymousNamespace() const393e5dd7070Spatrick bool Decl::isInAnonymousNamespace() const {
394e5dd7070Spatrick for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) {
395e5dd7070Spatrick if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
396e5dd7070Spatrick if (ND->isAnonymousNamespace())
397e5dd7070Spatrick return true;
398e5dd7070Spatrick }
399e5dd7070Spatrick
400e5dd7070Spatrick return false;
401e5dd7070Spatrick }
402e5dd7070Spatrick
isInStdNamespace() const403e5dd7070Spatrick bool Decl::isInStdNamespace() const {
404e5dd7070Spatrick const DeclContext *DC = getDeclContext();
405e5dd7070Spatrick return DC && DC->isStdNamespace();
406e5dd7070Spatrick }
407e5dd7070Spatrick
isFileContextDecl() const408*12c85518Srobert bool Decl::isFileContextDecl() const {
409*12c85518Srobert const auto *DC = dyn_cast<DeclContext>(this);
410*12c85518Srobert return DC && DC->isFileContext();
411*12c85518Srobert }
412*12c85518Srobert
getTranslationUnitDecl()413e5dd7070Spatrick TranslationUnitDecl *Decl::getTranslationUnitDecl() {
414e5dd7070Spatrick if (auto *TUD = dyn_cast<TranslationUnitDecl>(this))
415e5dd7070Spatrick return TUD;
416e5dd7070Spatrick
417e5dd7070Spatrick DeclContext *DC = getDeclContext();
418e5dd7070Spatrick assert(DC && "This decl is not contained in a translation unit!");
419e5dd7070Spatrick
420e5dd7070Spatrick while (!DC->isTranslationUnit()) {
421e5dd7070Spatrick DC = DC->getParent();
422e5dd7070Spatrick assert(DC && "This decl is not contained in a translation unit!");
423e5dd7070Spatrick }
424e5dd7070Spatrick
425e5dd7070Spatrick return cast<TranslationUnitDecl>(DC);
426e5dd7070Spatrick }
427e5dd7070Spatrick
getASTContext() const428e5dd7070Spatrick ASTContext &Decl::getASTContext() const {
429e5dd7070Spatrick return getTranslationUnitDecl()->getASTContext();
430e5dd7070Spatrick }
431e5dd7070Spatrick
432ec727ea7Spatrick /// Helper to get the language options from the ASTContext.
433ec727ea7Spatrick /// Defined out of line to avoid depending on ASTContext.h.
getLangOpts() const434ec727ea7Spatrick const LangOptions &Decl::getLangOpts() const {
435ec727ea7Spatrick return getASTContext().getLangOpts();
436ec727ea7Spatrick }
437ec727ea7Spatrick
getASTMutationListener() const438e5dd7070Spatrick ASTMutationListener *Decl::getASTMutationListener() const {
439e5dd7070Spatrick return getASTContext().getASTMutationListener();
440e5dd7070Spatrick }
441e5dd7070Spatrick
getMaxAlignment() const442e5dd7070Spatrick unsigned Decl::getMaxAlignment() const {
443e5dd7070Spatrick if (!hasAttrs())
444e5dd7070Spatrick return 0;
445e5dd7070Spatrick
446e5dd7070Spatrick unsigned Align = 0;
447e5dd7070Spatrick const AttrVec &V = getAttrs();
448e5dd7070Spatrick ASTContext &Ctx = getASTContext();
449e5dd7070Spatrick specific_attr_iterator<AlignedAttr> I(V.begin()), E(V.end());
450ec727ea7Spatrick for (; I != E; ++I) {
451ec727ea7Spatrick if (!I->isAlignmentErrorDependent())
452e5dd7070Spatrick Align = std::max(Align, I->getAlignment(Ctx));
453ec727ea7Spatrick }
454e5dd7070Spatrick return Align;
455e5dd7070Spatrick }
456e5dd7070Spatrick
isUsed(bool CheckUsedAttr) const457e5dd7070Spatrick bool Decl::isUsed(bool CheckUsedAttr) const {
458e5dd7070Spatrick const Decl *CanonD = getCanonicalDecl();
459e5dd7070Spatrick if (CanonD->Used)
460e5dd7070Spatrick return true;
461e5dd7070Spatrick
462e5dd7070Spatrick // Check for used attribute.
463e5dd7070Spatrick // Ask the most recent decl, since attributes accumulate in the redecl chain.
464e5dd7070Spatrick if (CheckUsedAttr && getMostRecentDecl()->hasAttr<UsedAttr>())
465e5dd7070Spatrick return true;
466e5dd7070Spatrick
467e5dd7070Spatrick // The information may have not been deserialized yet. Force deserialization
468e5dd7070Spatrick // to complete the needed information.
469e5dd7070Spatrick return getMostRecentDecl()->getCanonicalDecl()->Used;
470e5dd7070Spatrick }
471e5dd7070Spatrick
markUsed(ASTContext & C)472e5dd7070Spatrick void Decl::markUsed(ASTContext &C) {
473e5dd7070Spatrick if (isUsed(false))
474e5dd7070Spatrick return;
475e5dd7070Spatrick
476e5dd7070Spatrick if (C.getASTMutationListener())
477e5dd7070Spatrick C.getASTMutationListener()->DeclarationMarkedUsed(this);
478e5dd7070Spatrick
479e5dd7070Spatrick setIsUsed();
480e5dd7070Spatrick }
481e5dd7070Spatrick
isReferenced() const482e5dd7070Spatrick bool Decl::isReferenced() const {
483e5dd7070Spatrick if (Referenced)
484e5dd7070Spatrick return true;
485e5dd7070Spatrick
486e5dd7070Spatrick // Check redeclarations.
487e5dd7070Spatrick for (const auto *I : redecls())
488e5dd7070Spatrick if (I->Referenced)
489e5dd7070Spatrick return true;
490e5dd7070Spatrick
491e5dd7070Spatrick return false;
492e5dd7070Spatrick }
493e5dd7070Spatrick
getExternalSourceSymbolAttr() const494e5dd7070Spatrick ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const {
495e5dd7070Spatrick const Decl *Definition = nullptr;
496e5dd7070Spatrick if (auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) {
497e5dd7070Spatrick Definition = ID->getDefinition();
498e5dd7070Spatrick } else if (auto *PD = dyn_cast<ObjCProtocolDecl>(this)) {
499e5dd7070Spatrick Definition = PD->getDefinition();
500e5dd7070Spatrick } else if (auto *TD = dyn_cast<TagDecl>(this)) {
501e5dd7070Spatrick Definition = TD->getDefinition();
502e5dd7070Spatrick }
503e5dd7070Spatrick if (!Definition)
504e5dd7070Spatrick Definition = this;
505e5dd7070Spatrick
506e5dd7070Spatrick if (auto *attr = Definition->getAttr<ExternalSourceSymbolAttr>())
507e5dd7070Spatrick return attr;
508e5dd7070Spatrick if (auto *dcd = dyn_cast<Decl>(getDeclContext())) {
509e5dd7070Spatrick return dcd->getAttr<ExternalSourceSymbolAttr>();
510e5dd7070Spatrick }
511e5dd7070Spatrick
512e5dd7070Spatrick return nullptr;
513e5dd7070Spatrick }
514e5dd7070Spatrick
hasDefiningAttr() const515e5dd7070Spatrick bool Decl::hasDefiningAttr() const {
516ec727ea7Spatrick return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>() ||
517ec727ea7Spatrick hasAttr<LoaderUninitializedAttr>();
518e5dd7070Spatrick }
519e5dd7070Spatrick
getDefiningAttr() const520e5dd7070Spatrick const Attr *Decl::getDefiningAttr() const {
521e5dd7070Spatrick if (auto *AA = getAttr<AliasAttr>())
522e5dd7070Spatrick return AA;
523e5dd7070Spatrick if (auto *IFA = getAttr<IFuncAttr>())
524e5dd7070Spatrick return IFA;
525ec727ea7Spatrick if (auto *NZA = getAttr<LoaderUninitializedAttr>())
526ec727ea7Spatrick return NZA;
527e5dd7070Spatrick return nullptr;
528e5dd7070Spatrick }
529e5dd7070Spatrick
getRealizedPlatform(const AvailabilityAttr * A,const ASTContext & Context)530e5dd7070Spatrick static StringRef getRealizedPlatform(const AvailabilityAttr *A,
531e5dd7070Spatrick const ASTContext &Context) {
532e5dd7070Spatrick // Check if this is an App Extension "platform", and if so chop off
533e5dd7070Spatrick // the suffix for matching with the actual platform.
534e5dd7070Spatrick StringRef RealizedPlatform = A->getPlatform()->getName();
535e5dd7070Spatrick if (!Context.getLangOpts().AppExt)
536e5dd7070Spatrick return RealizedPlatform;
537e5dd7070Spatrick size_t suffix = RealizedPlatform.rfind("_app_extension");
538e5dd7070Spatrick if (suffix != StringRef::npos)
539e5dd7070Spatrick return RealizedPlatform.slice(0, suffix);
540e5dd7070Spatrick return RealizedPlatform;
541e5dd7070Spatrick }
542e5dd7070Spatrick
543e5dd7070Spatrick /// Determine the availability of the given declaration based on
544e5dd7070Spatrick /// the target platform.
545e5dd7070Spatrick ///
546e5dd7070Spatrick /// When it returns an availability result other than \c AR_Available,
547e5dd7070Spatrick /// if the \p Message parameter is non-NULL, it will be set to a
548e5dd7070Spatrick /// string describing why the entity is unavailable.
549e5dd7070Spatrick ///
550e5dd7070Spatrick /// FIXME: Make these strings localizable, since they end up in
551e5dd7070Spatrick /// diagnostics.
CheckAvailability(ASTContext & Context,const AvailabilityAttr * A,std::string * Message,VersionTuple EnclosingVersion)552e5dd7070Spatrick static AvailabilityResult CheckAvailability(ASTContext &Context,
553e5dd7070Spatrick const AvailabilityAttr *A,
554e5dd7070Spatrick std::string *Message,
555e5dd7070Spatrick VersionTuple EnclosingVersion) {
556e5dd7070Spatrick if (EnclosingVersion.empty())
557e5dd7070Spatrick EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion();
558e5dd7070Spatrick
559e5dd7070Spatrick if (EnclosingVersion.empty())
560e5dd7070Spatrick return AR_Available;
561e5dd7070Spatrick
562e5dd7070Spatrick StringRef ActualPlatform = A->getPlatform()->getName();
563e5dd7070Spatrick StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
564e5dd7070Spatrick
565e5dd7070Spatrick // Match the platform name.
566e5dd7070Spatrick if (getRealizedPlatform(A, Context) != TargetPlatform)
567e5dd7070Spatrick return AR_Available;
568e5dd7070Spatrick
569e5dd7070Spatrick StringRef PrettyPlatformName
570e5dd7070Spatrick = AvailabilityAttr::getPrettyPlatformName(ActualPlatform);
571e5dd7070Spatrick
572e5dd7070Spatrick if (PrettyPlatformName.empty())
573e5dd7070Spatrick PrettyPlatformName = ActualPlatform;
574e5dd7070Spatrick
575e5dd7070Spatrick std::string HintMessage;
576e5dd7070Spatrick if (!A->getMessage().empty()) {
577e5dd7070Spatrick HintMessage = " - ";
578e5dd7070Spatrick HintMessage += A->getMessage();
579e5dd7070Spatrick }
580e5dd7070Spatrick
581e5dd7070Spatrick // Make sure that this declaration has not been marked 'unavailable'.
582e5dd7070Spatrick if (A->getUnavailable()) {
583e5dd7070Spatrick if (Message) {
584e5dd7070Spatrick Message->clear();
585e5dd7070Spatrick llvm::raw_string_ostream Out(*Message);
586e5dd7070Spatrick Out << "not available on " << PrettyPlatformName
587e5dd7070Spatrick << HintMessage;
588e5dd7070Spatrick }
589e5dd7070Spatrick
590e5dd7070Spatrick return AR_Unavailable;
591e5dd7070Spatrick }
592e5dd7070Spatrick
593e5dd7070Spatrick // Make sure that this declaration has already been introduced.
594e5dd7070Spatrick if (!A->getIntroduced().empty() &&
595e5dd7070Spatrick EnclosingVersion < A->getIntroduced()) {
596e5dd7070Spatrick if (Message) {
597e5dd7070Spatrick Message->clear();
598e5dd7070Spatrick llvm::raw_string_ostream Out(*Message);
599e5dd7070Spatrick VersionTuple VTI(A->getIntroduced());
600e5dd7070Spatrick Out << "introduced in " << PrettyPlatformName << ' '
601e5dd7070Spatrick << VTI << HintMessage;
602e5dd7070Spatrick }
603e5dd7070Spatrick
604e5dd7070Spatrick return A->getStrict() ? AR_Unavailable : AR_NotYetIntroduced;
605e5dd7070Spatrick }
606e5dd7070Spatrick
607e5dd7070Spatrick // Make sure that this declaration hasn't been obsoleted.
608e5dd7070Spatrick if (!A->getObsoleted().empty() && EnclosingVersion >= A->getObsoleted()) {
609e5dd7070Spatrick if (Message) {
610e5dd7070Spatrick Message->clear();
611e5dd7070Spatrick llvm::raw_string_ostream Out(*Message);
612e5dd7070Spatrick VersionTuple VTO(A->getObsoleted());
613e5dd7070Spatrick Out << "obsoleted in " << PrettyPlatformName << ' '
614e5dd7070Spatrick << VTO << HintMessage;
615e5dd7070Spatrick }
616e5dd7070Spatrick
617e5dd7070Spatrick return AR_Unavailable;
618e5dd7070Spatrick }
619e5dd7070Spatrick
620e5dd7070Spatrick // Make sure that this declaration hasn't been deprecated.
621e5dd7070Spatrick if (!A->getDeprecated().empty() && EnclosingVersion >= A->getDeprecated()) {
622e5dd7070Spatrick if (Message) {
623e5dd7070Spatrick Message->clear();
624e5dd7070Spatrick llvm::raw_string_ostream Out(*Message);
625e5dd7070Spatrick VersionTuple VTD(A->getDeprecated());
626e5dd7070Spatrick Out << "first deprecated in " << PrettyPlatformName << ' '
627e5dd7070Spatrick << VTD << HintMessage;
628e5dd7070Spatrick }
629e5dd7070Spatrick
630e5dd7070Spatrick return AR_Deprecated;
631e5dd7070Spatrick }
632e5dd7070Spatrick
633e5dd7070Spatrick return AR_Available;
634e5dd7070Spatrick }
635e5dd7070Spatrick
getAvailability(std::string * Message,VersionTuple EnclosingVersion,StringRef * RealizedPlatform) const636e5dd7070Spatrick AvailabilityResult Decl::getAvailability(std::string *Message,
637e5dd7070Spatrick VersionTuple EnclosingVersion,
638e5dd7070Spatrick StringRef *RealizedPlatform) const {
639e5dd7070Spatrick if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
640e5dd7070Spatrick return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion,
641e5dd7070Spatrick RealizedPlatform);
642e5dd7070Spatrick
643e5dd7070Spatrick AvailabilityResult Result = AR_Available;
644e5dd7070Spatrick std::string ResultMessage;
645e5dd7070Spatrick
646e5dd7070Spatrick for (const auto *A : attrs()) {
647e5dd7070Spatrick if (const auto *Deprecated = dyn_cast<DeprecatedAttr>(A)) {
648e5dd7070Spatrick if (Result >= AR_Deprecated)
649e5dd7070Spatrick continue;
650e5dd7070Spatrick
651e5dd7070Spatrick if (Message)
652ec727ea7Spatrick ResultMessage = std::string(Deprecated->getMessage());
653e5dd7070Spatrick
654e5dd7070Spatrick Result = AR_Deprecated;
655e5dd7070Spatrick continue;
656e5dd7070Spatrick }
657e5dd7070Spatrick
658e5dd7070Spatrick if (const auto *Unavailable = dyn_cast<UnavailableAttr>(A)) {
659e5dd7070Spatrick if (Message)
660ec727ea7Spatrick *Message = std::string(Unavailable->getMessage());
661e5dd7070Spatrick return AR_Unavailable;
662e5dd7070Spatrick }
663e5dd7070Spatrick
664e5dd7070Spatrick if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
665e5dd7070Spatrick AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
666e5dd7070Spatrick Message, EnclosingVersion);
667e5dd7070Spatrick
668e5dd7070Spatrick if (AR == AR_Unavailable) {
669e5dd7070Spatrick if (RealizedPlatform)
670e5dd7070Spatrick *RealizedPlatform = Availability->getPlatform()->getName();
671e5dd7070Spatrick return AR_Unavailable;
672e5dd7070Spatrick }
673e5dd7070Spatrick
674e5dd7070Spatrick if (AR > Result) {
675e5dd7070Spatrick Result = AR;
676e5dd7070Spatrick if (Message)
677e5dd7070Spatrick ResultMessage.swap(*Message);
678e5dd7070Spatrick }
679e5dd7070Spatrick continue;
680e5dd7070Spatrick }
681e5dd7070Spatrick }
682e5dd7070Spatrick
683e5dd7070Spatrick if (Message)
684e5dd7070Spatrick Message->swap(ResultMessage);
685e5dd7070Spatrick return Result;
686e5dd7070Spatrick }
687e5dd7070Spatrick
getVersionIntroduced() const688e5dd7070Spatrick VersionTuple Decl::getVersionIntroduced() const {
689e5dd7070Spatrick const ASTContext &Context = getASTContext();
690e5dd7070Spatrick StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
691e5dd7070Spatrick for (const auto *A : attrs()) {
692e5dd7070Spatrick if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
693e5dd7070Spatrick if (getRealizedPlatform(Availability, Context) != TargetPlatform)
694e5dd7070Spatrick continue;
695e5dd7070Spatrick if (!Availability->getIntroduced().empty())
696e5dd7070Spatrick return Availability->getIntroduced();
697e5dd7070Spatrick }
698e5dd7070Spatrick }
699e5dd7070Spatrick return {};
700e5dd7070Spatrick }
701e5dd7070Spatrick
canBeWeakImported(bool & IsDefinition) const702e5dd7070Spatrick bool Decl::canBeWeakImported(bool &IsDefinition) const {
703e5dd7070Spatrick IsDefinition = false;
704e5dd7070Spatrick
705e5dd7070Spatrick // Variables, if they aren't definitions.
706e5dd7070Spatrick if (const auto *Var = dyn_cast<VarDecl>(this)) {
707e5dd7070Spatrick if (Var->isThisDeclarationADefinition()) {
708e5dd7070Spatrick IsDefinition = true;
709e5dd7070Spatrick return false;
710e5dd7070Spatrick }
711e5dd7070Spatrick return true;
712a9ac8606Spatrick }
713e5dd7070Spatrick // Functions, if they aren't definitions.
714a9ac8606Spatrick if (const auto *FD = dyn_cast<FunctionDecl>(this)) {
715e5dd7070Spatrick if (FD->hasBody()) {
716e5dd7070Spatrick IsDefinition = true;
717e5dd7070Spatrick return false;
718e5dd7070Spatrick }
719e5dd7070Spatrick return true;
720e5dd7070Spatrick
721a9ac8606Spatrick }
722e5dd7070Spatrick // Objective-C classes, if this is the non-fragile runtime.
723a9ac8606Spatrick if (isa<ObjCInterfaceDecl>(this) &&
724e5dd7070Spatrick getASTContext().getLangOpts().ObjCRuntime.hasWeakClassImport()) {
725e5dd7070Spatrick return true;
726e5dd7070Spatrick }
727a9ac8606Spatrick // Nothing else.
728a9ac8606Spatrick return false;
729e5dd7070Spatrick }
730e5dd7070Spatrick
isWeakImported() const731e5dd7070Spatrick bool Decl::isWeakImported() const {
732e5dd7070Spatrick bool IsDefinition;
733e5dd7070Spatrick if (!canBeWeakImported(IsDefinition))
734e5dd7070Spatrick return false;
735e5dd7070Spatrick
736a9ac8606Spatrick for (const auto *A : getMostRecentDecl()->attrs()) {
737e5dd7070Spatrick if (isa<WeakImportAttr>(A))
738e5dd7070Spatrick return true;
739e5dd7070Spatrick
740e5dd7070Spatrick if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
741e5dd7070Spatrick if (CheckAvailability(getASTContext(), Availability, nullptr,
742e5dd7070Spatrick VersionTuple()) == AR_NotYetIntroduced)
743e5dd7070Spatrick return true;
744e5dd7070Spatrick }
745e5dd7070Spatrick }
746e5dd7070Spatrick
747e5dd7070Spatrick return false;
748e5dd7070Spatrick }
749e5dd7070Spatrick
getIdentifierNamespaceForKind(Kind DeclKind)750e5dd7070Spatrick unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
751e5dd7070Spatrick switch (DeclKind) {
752e5dd7070Spatrick case Function:
753e5dd7070Spatrick case CXXDeductionGuide:
754e5dd7070Spatrick case CXXMethod:
755e5dd7070Spatrick case CXXConstructor:
756e5dd7070Spatrick case ConstructorUsingShadow:
757e5dd7070Spatrick case CXXDestructor:
758e5dd7070Spatrick case CXXConversion:
759e5dd7070Spatrick case EnumConstant:
760e5dd7070Spatrick case Var:
761e5dd7070Spatrick case ImplicitParam:
762e5dd7070Spatrick case ParmVar:
763e5dd7070Spatrick case ObjCMethod:
764e5dd7070Spatrick case ObjCProperty:
765e5dd7070Spatrick case MSProperty:
766*12c85518Srobert case HLSLBuffer:
767e5dd7070Spatrick return IDNS_Ordinary;
768e5dd7070Spatrick case Label:
769e5dd7070Spatrick return IDNS_Label;
770e5dd7070Spatrick case IndirectField:
771e5dd7070Spatrick return IDNS_Ordinary | IDNS_Member;
772e5dd7070Spatrick
773e5dd7070Spatrick case Binding:
774e5dd7070Spatrick case NonTypeTemplateParm:
775e5dd7070Spatrick case VarTemplate:
776e5dd7070Spatrick case Concept:
777e5dd7070Spatrick // These (C++-only) declarations are found by redeclaration lookup for
778e5dd7070Spatrick // tag types, so we include them in the tag namespace.
779e5dd7070Spatrick return IDNS_Ordinary | IDNS_Tag;
780e5dd7070Spatrick
781e5dd7070Spatrick case ObjCCompatibleAlias:
782e5dd7070Spatrick case ObjCInterface:
783e5dd7070Spatrick return IDNS_Ordinary | IDNS_Type;
784e5dd7070Spatrick
785e5dd7070Spatrick case Typedef:
786e5dd7070Spatrick case TypeAlias:
787e5dd7070Spatrick case TemplateTypeParm:
788e5dd7070Spatrick case ObjCTypeParam:
789e5dd7070Spatrick return IDNS_Ordinary | IDNS_Type;
790e5dd7070Spatrick
791e5dd7070Spatrick case UnresolvedUsingTypename:
792e5dd7070Spatrick return IDNS_Ordinary | IDNS_Type | IDNS_Using;
793e5dd7070Spatrick
794e5dd7070Spatrick case UsingShadow:
795e5dd7070Spatrick return 0; // we'll actually overwrite this later
796e5dd7070Spatrick
797e5dd7070Spatrick case UnresolvedUsingValue:
798e5dd7070Spatrick return IDNS_Ordinary | IDNS_Using;
799e5dd7070Spatrick
800e5dd7070Spatrick case Using:
801e5dd7070Spatrick case UsingPack:
802a9ac8606Spatrick case UsingEnum:
803e5dd7070Spatrick return IDNS_Using;
804e5dd7070Spatrick
805e5dd7070Spatrick case ObjCProtocol:
806e5dd7070Spatrick return IDNS_ObjCProtocol;
807e5dd7070Spatrick
808e5dd7070Spatrick case Field:
809e5dd7070Spatrick case ObjCAtDefsField:
810e5dd7070Spatrick case ObjCIvar:
811e5dd7070Spatrick return IDNS_Member;
812e5dd7070Spatrick
813e5dd7070Spatrick case Record:
814e5dd7070Spatrick case CXXRecord:
815e5dd7070Spatrick case Enum:
816e5dd7070Spatrick return IDNS_Tag | IDNS_Type;
817e5dd7070Spatrick
818e5dd7070Spatrick case Namespace:
819e5dd7070Spatrick case NamespaceAlias:
820e5dd7070Spatrick return IDNS_Namespace;
821e5dd7070Spatrick
822e5dd7070Spatrick case FunctionTemplate:
823e5dd7070Spatrick return IDNS_Ordinary;
824e5dd7070Spatrick
825e5dd7070Spatrick case ClassTemplate:
826e5dd7070Spatrick case TemplateTemplateParm:
827e5dd7070Spatrick case TypeAliasTemplate:
828e5dd7070Spatrick return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
829e5dd7070Spatrick
830a9ac8606Spatrick case UnresolvedUsingIfExists:
831a9ac8606Spatrick return IDNS_Type | IDNS_Ordinary;
832a9ac8606Spatrick
833e5dd7070Spatrick case OMPDeclareReduction:
834e5dd7070Spatrick return IDNS_OMPReduction;
835e5dd7070Spatrick
836e5dd7070Spatrick case OMPDeclareMapper:
837e5dd7070Spatrick return IDNS_OMPMapper;
838e5dd7070Spatrick
839e5dd7070Spatrick // Never have names.
840e5dd7070Spatrick case Friend:
841e5dd7070Spatrick case FriendTemplate:
842e5dd7070Spatrick case AccessSpec:
843e5dd7070Spatrick case LinkageSpec:
844e5dd7070Spatrick case Export:
845e5dd7070Spatrick case FileScopeAsm:
846*12c85518Srobert case TopLevelStmt:
847e5dd7070Spatrick case StaticAssert:
848e5dd7070Spatrick case ObjCPropertyImpl:
849e5dd7070Spatrick case PragmaComment:
850e5dd7070Spatrick case PragmaDetectMismatch:
851e5dd7070Spatrick case Block:
852e5dd7070Spatrick case Captured:
853e5dd7070Spatrick case TranslationUnit:
854e5dd7070Spatrick case ExternCContext:
855e5dd7070Spatrick case Decomposition:
856ec727ea7Spatrick case MSGuid:
857*12c85518Srobert case UnnamedGlobalConstant:
858a9ac8606Spatrick case TemplateParamObject:
859e5dd7070Spatrick
860e5dd7070Spatrick case UsingDirective:
861e5dd7070Spatrick case BuiltinTemplate:
862e5dd7070Spatrick case ClassTemplateSpecialization:
863e5dd7070Spatrick case ClassTemplatePartialSpecialization:
864e5dd7070Spatrick case ClassScopeFunctionSpecialization:
865e5dd7070Spatrick case VarTemplateSpecialization:
866e5dd7070Spatrick case VarTemplatePartialSpecialization:
867e5dd7070Spatrick case ObjCImplementation:
868e5dd7070Spatrick case ObjCCategory:
869e5dd7070Spatrick case ObjCCategoryImpl:
870e5dd7070Spatrick case Import:
871e5dd7070Spatrick case OMPThreadPrivate:
872e5dd7070Spatrick case OMPAllocate:
873e5dd7070Spatrick case OMPRequires:
874e5dd7070Spatrick case OMPCapturedExpr:
875e5dd7070Spatrick case Empty:
876e5dd7070Spatrick case LifetimeExtendedTemporary:
877e5dd7070Spatrick case RequiresExprBody:
878*12c85518Srobert case ImplicitConceptSpecialization:
879e5dd7070Spatrick // Never looked up by name.
880e5dd7070Spatrick return 0;
881e5dd7070Spatrick }
882e5dd7070Spatrick
883e5dd7070Spatrick llvm_unreachable("Invalid DeclKind!");
884e5dd7070Spatrick }
885e5dd7070Spatrick
setAttrsImpl(const AttrVec & attrs,ASTContext & Ctx)886e5dd7070Spatrick void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) {
887e5dd7070Spatrick assert(!HasAttrs && "Decl already contains attrs.");
888e5dd7070Spatrick
889e5dd7070Spatrick AttrVec &AttrBlank = Ctx.getDeclAttrs(this);
890e5dd7070Spatrick assert(AttrBlank.empty() && "HasAttrs was wrong?");
891e5dd7070Spatrick
892e5dd7070Spatrick AttrBlank = attrs;
893e5dd7070Spatrick HasAttrs = true;
894e5dd7070Spatrick }
895e5dd7070Spatrick
dropAttrs()896e5dd7070Spatrick void Decl::dropAttrs() {
897e5dd7070Spatrick if (!HasAttrs) return;
898e5dd7070Spatrick
899e5dd7070Spatrick HasAttrs = false;
900e5dd7070Spatrick getASTContext().eraseDeclAttrs(this);
901e5dd7070Spatrick }
902e5dd7070Spatrick
addAttr(Attr * A)903e5dd7070Spatrick void Decl::addAttr(Attr *A) {
904e5dd7070Spatrick if (!hasAttrs()) {
905e5dd7070Spatrick setAttrs(AttrVec(1, A));
906e5dd7070Spatrick return;
907e5dd7070Spatrick }
908e5dd7070Spatrick
909e5dd7070Spatrick AttrVec &Attrs = getAttrs();
910e5dd7070Spatrick if (!A->isInherited()) {
911e5dd7070Spatrick Attrs.push_back(A);
912e5dd7070Spatrick return;
913e5dd7070Spatrick }
914e5dd7070Spatrick
915e5dd7070Spatrick // Attribute inheritance is processed after attribute parsing. To keep the
916e5dd7070Spatrick // order as in the source code, add inherited attributes before non-inherited
917e5dd7070Spatrick // ones.
918e5dd7070Spatrick auto I = Attrs.begin(), E = Attrs.end();
919e5dd7070Spatrick for (; I != E; ++I) {
920e5dd7070Spatrick if (!(*I)->isInherited())
921e5dd7070Spatrick break;
922e5dd7070Spatrick }
923e5dd7070Spatrick Attrs.insert(I, A);
924e5dd7070Spatrick }
925e5dd7070Spatrick
getAttrs() const926e5dd7070Spatrick const AttrVec &Decl::getAttrs() const {
927e5dd7070Spatrick assert(HasAttrs && "No attrs to get!");
928e5dd7070Spatrick return getASTContext().getDeclAttrs(this);
929e5dd7070Spatrick }
930e5dd7070Spatrick
castFromDeclContext(const DeclContext * D)931e5dd7070Spatrick Decl *Decl::castFromDeclContext (const DeclContext *D) {
932e5dd7070Spatrick Decl::Kind DK = D->getDeclKind();
933e5dd7070Spatrick switch(DK) {
934e5dd7070Spatrick #define DECL(NAME, BASE)
935e5dd7070Spatrick #define DECL_CONTEXT(NAME) \
936e5dd7070Spatrick case Decl::NAME: \
937e5dd7070Spatrick return static_cast<NAME##Decl *>(const_cast<DeclContext *>(D));
938e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME)
939e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
940e5dd7070Spatrick default:
941e5dd7070Spatrick #define DECL(NAME, BASE)
942e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME) \
943e5dd7070Spatrick if (DK >= first##NAME && DK <= last##NAME) \
944e5dd7070Spatrick return static_cast<NAME##Decl *>(const_cast<DeclContext *>(D));
945e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
946e5dd7070Spatrick llvm_unreachable("a decl that inherits DeclContext isn't handled");
947e5dd7070Spatrick }
948e5dd7070Spatrick }
949e5dd7070Spatrick
castToDeclContext(const Decl * D)950e5dd7070Spatrick DeclContext *Decl::castToDeclContext(const Decl *D) {
951e5dd7070Spatrick Decl::Kind DK = D->getKind();
952e5dd7070Spatrick switch(DK) {
953e5dd7070Spatrick #define DECL(NAME, BASE)
954e5dd7070Spatrick #define DECL_CONTEXT(NAME) \
955e5dd7070Spatrick case Decl::NAME: \
956e5dd7070Spatrick return static_cast<NAME##Decl *>(const_cast<Decl *>(D));
957e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME)
958e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
959e5dd7070Spatrick default:
960e5dd7070Spatrick #define DECL(NAME, BASE)
961e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME) \
962e5dd7070Spatrick if (DK >= first##NAME && DK <= last##NAME) \
963e5dd7070Spatrick return static_cast<NAME##Decl *>(const_cast<Decl *>(D));
964e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
965e5dd7070Spatrick llvm_unreachable("a decl that inherits DeclContext isn't handled");
966e5dd7070Spatrick }
967e5dd7070Spatrick }
968e5dd7070Spatrick
getBodyRBrace() const969e5dd7070Spatrick SourceLocation Decl::getBodyRBrace() const {
970e5dd7070Spatrick // Special handling of FunctionDecl to avoid de-serializing the body from PCH.
971e5dd7070Spatrick // FunctionDecl stores EndRangeLoc for this purpose.
972e5dd7070Spatrick if (const auto *FD = dyn_cast<FunctionDecl>(this)) {
973e5dd7070Spatrick const FunctionDecl *Definition;
974e5dd7070Spatrick if (FD->hasBody(Definition))
975e5dd7070Spatrick return Definition->getSourceRange().getEnd();
976e5dd7070Spatrick return {};
977e5dd7070Spatrick }
978e5dd7070Spatrick
979e5dd7070Spatrick if (Stmt *Body = getBody())
980e5dd7070Spatrick return Body->getSourceRange().getEnd();
981e5dd7070Spatrick
982e5dd7070Spatrick return {};
983e5dd7070Spatrick }
984e5dd7070Spatrick
AccessDeclContextCheck() const985*12c85518Srobert bool Decl::AccessDeclContextCheck() const {
986e5dd7070Spatrick #ifndef NDEBUG
987e5dd7070Spatrick // Suppress this check if any of the following hold:
988e5dd7070Spatrick // 1. this is the translation unit (and thus has no parent)
989e5dd7070Spatrick // 2. this is a template parameter (and thus doesn't belong to its context)
990e5dd7070Spatrick // 3. this is a non-type template parameter
991e5dd7070Spatrick // 4. the context is not a record
992e5dd7070Spatrick // 5. it's invalid
993e5dd7070Spatrick // 6. it's a C++0x static_assert.
994e5dd7070Spatrick // 7. it's a block literal declaration
995a9ac8606Spatrick // 8. it's a temporary with lifetime extended due to being default value.
996a9ac8606Spatrick if (isa<TranslationUnitDecl>(this) || isa<TemplateTypeParmDecl>(this) ||
997a9ac8606Spatrick isa<NonTypeTemplateParmDecl>(this) || !getDeclContext() ||
998a9ac8606Spatrick !isa<CXXRecordDecl>(getDeclContext()) || isInvalidDecl() ||
999a9ac8606Spatrick isa<StaticAssertDecl>(this) || isa<BlockDecl>(this) ||
1000e5dd7070Spatrick // FIXME: a ParmVarDecl can have ClassTemplateSpecialization
1001e5dd7070Spatrick // as DeclContext (?).
1002e5dd7070Spatrick isa<ParmVarDecl>(this) ||
1003e5dd7070Spatrick // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
1004e5dd7070Spatrick // AS_none as access specifier.
1005e5dd7070Spatrick isa<CXXRecordDecl>(this) ||
1006a9ac8606Spatrick isa<ClassScopeFunctionSpecializationDecl>(this) ||
1007a9ac8606Spatrick isa<LifetimeExtendedTemporaryDecl>(this))
1008e5dd7070Spatrick return true;
1009e5dd7070Spatrick
1010e5dd7070Spatrick assert(Access != AS_none &&
1011e5dd7070Spatrick "Access specifier is AS_none inside a record decl");
1012e5dd7070Spatrick #endif
1013e5dd7070Spatrick return true;
1014e5dd7070Spatrick }
1015e5dd7070Spatrick
isInExportDeclContext() const1016*12c85518Srobert bool Decl::isInExportDeclContext() const {
1017*12c85518Srobert const DeclContext *DC = getLexicalDeclContext();
1018*12c85518Srobert
1019*12c85518Srobert while (DC && !isa<ExportDecl>(DC))
1020*12c85518Srobert DC = DC->getLexicalParent();
1021*12c85518Srobert
1022*12c85518Srobert return DC && isa<ExportDecl>(DC);
1023*12c85518Srobert }
1024*12c85518Srobert
getKind(const Decl * D)1025e5dd7070Spatrick static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
getKind(const DeclContext * DC)1026e5dd7070Spatrick static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }
1027e5dd7070Spatrick
getID() const1028e5dd7070Spatrick int64_t Decl::getID() const {
1029e5dd7070Spatrick return getASTContext().getAllocator().identifyKnownAlignedObject<Decl>(this);
1030e5dd7070Spatrick }
1031e5dd7070Spatrick
getFunctionType(bool BlocksToo) const1032e5dd7070Spatrick const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
1033e5dd7070Spatrick QualType Ty;
1034e5dd7070Spatrick if (const auto *D = dyn_cast<ValueDecl>(this))
1035e5dd7070Spatrick Ty = D->getType();
1036e5dd7070Spatrick else if (const auto *D = dyn_cast<TypedefNameDecl>(this))
1037e5dd7070Spatrick Ty = D->getUnderlyingType();
1038e5dd7070Spatrick else
1039e5dd7070Spatrick return nullptr;
1040e5dd7070Spatrick
1041e5dd7070Spatrick if (Ty->isFunctionPointerType())
1042e5dd7070Spatrick Ty = Ty->castAs<PointerType>()->getPointeeType();
1043e5dd7070Spatrick else if (Ty->isFunctionReferenceType())
1044e5dd7070Spatrick Ty = Ty->castAs<ReferenceType>()->getPointeeType();
1045e5dd7070Spatrick else if (BlocksToo && Ty->isBlockPointerType())
1046e5dd7070Spatrick Ty = Ty->castAs<BlockPointerType>()->getPointeeType();
1047e5dd7070Spatrick
1048e5dd7070Spatrick return Ty->getAs<FunctionType>();
1049e5dd7070Spatrick }
1050e5dd7070Spatrick
getNonTransparentDeclContext()1051*12c85518Srobert DeclContext *Decl::getNonTransparentDeclContext() {
1052*12c85518Srobert assert(getDeclContext());
1053*12c85518Srobert return getDeclContext()->getNonTransparentContext();
1054*12c85518Srobert }
1055*12c85518Srobert
1056e5dd7070Spatrick /// Starting at a given context (a Decl or DeclContext), look for a
1057e5dd7070Spatrick /// code context that is not a closure (a lambda, block, etc.).
getNonClosureContext(T * D)1058e5dd7070Spatrick template <class T> static Decl *getNonClosureContext(T *D) {
1059e5dd7070Spatrick if (getKind(D) == Decl::CXXMethod) {
1060e5dd7070Spatrick auto *MD = cast<CXXMethodDecl>(D);
1061e5dd7070Spatrick if (MD->getOverloadedOperator() == OO_Call &&
1062e5dd7070Spatrick MD->getParent()->isLambda())
1063e5dd7070Spatrick return getNonClosureContext(MD->getParent()->getParent());
1064e5dd7070Spatrick return MD;
1065a9ac8606Spatrick }
1066a9ac8606Spatrick if (auto *FD = dyn_cast<FunctionDecl>(D))
1067e5dd7070Spatrick return FD;
1068a9ac8606Spatrick if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
1069e5dd7070Spatrick return MD;
1070a9ac8606Spatrick if (auto *BD = dyn_cast<BlockDecl>(D))
1071e5dd7070Spatrick return getNonClosureContext(BD->getParent());
1072a9ac8606Spatrick if (auto *CD = dyn_cast<CapturedDecl>(D))
1073e5dd7070Spatrick return getNonClosureContext(CD->getParent());
1074e5dd7070Spatrick return nullptr;
1075e5dd7070Spatrick }
1076e5dd7070Spatrick
getNonClosureContext()1077e5dd7070Spatrick Decl *Decl::getNonClosureContext() {
1078e5dd7070Spatrick return ::getNonClosureContext(this);
1079e5dd7070Spatrick }
1080e5dd7070Spatrick
getNonClosureAncestor()1081e5dd7070Spatrick Decl *DeclContext::getNonClosureAncestor() {
1082e5dd7070Spatrick return ::getNonClosureContext(this);
1083e5dd7070Spatrick }
1084e5dd7070Spatrick
1085e5dd7070Spatrick //===----------------------------------------------------------------------===//
1086e5dd7070Spatrick // DeclContext Implementation
1087e5dd7070Spatrick //===----------------------------------------------------------------------===//
1088e5dd7070Spatrick
DeclContext(Decl::Kind K)1089e5dd7070Spatrick DeclContext::DeclContext(Decl::Kind K) {
1090e5dd7070Spatrick DeclContextBits.DeclKind = K;
1091e5dd7070Spatrick setHasExternalLexicalStorage(false);
1092e5dd7070Spatrick setHasExternalVisibleStorage(false);
1093e5dd7070Spatrick setNeedToReconcileExternalVisibleStorage(false);
1094e5dd7070Spatrick setHasLazyLocalLexicalLookups(false);
1095e5dd7070Spatrick setHasLazyExternalLexicalLookups(false);
1096e5dd7070Spatrick setUseQualifiedLookup(false);
1097e5dd7070Spatrick }
1098e5dd7070Spatrick
classof(const Decl * D)1099e5dd7070Spatrick bool DeclContext::classof(const Decl *D) {
1100e5dd7070Spatrick switch (D->getKind()) {
1101e5dd7070Spatrick #define DECL(NAME, BASE)
1102e5dd7070Spatrick #define DECL_CONTEXT(NAME) case Decl::NAME:
1103e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME)
1104e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
1105e5dd7070Spatrick return true;
1106e5dd7070Spatrick default:
1107e5dd7070Spatrick #define DECL(NAME, BASE)
1108e5dd7070Spatrick #define DECL_CONTEXT_BASE(NAME) \
1109e5dd7070Spatrick if (D->getKind() >= Decl::first##NAME && \
1110e5dd7070Spatrick D->getKind() <= Decl::last##NAME) \
1111e5dd7070Spatrick return true;
1112e5dd7070Spatrick #include "clang/AST/DeclNodes.inc"
1113e5dd7070Spatrick return false;
1114e5dd7070Spatrick }
1115e5dd7070Spatrick }
1116e5dd7070Spatrick
1117e5dd7070Spatrick DeclContext::~DeclContext() = default;
1118e5dd7070Spatrick
1119e5dd7070Spatrick /// Find the parent context of this context that will be
1120e5dd7070Spatrick /// used for unqualified name lookup.
1121e5dd7070Spatrick ///
1122e5dd7070Spatrick /// Generally, the parent lookup context is the semantic context. However, for
1123e5dd7070Spatrick /// a friend function the parent lookup context is the lexical context, which
1124e5dd7070Spatrick /// is the class in which the friend is declared.
getLookupParent()1125e5dd7070Spatrick DeclContext *DeclContext::getLookupParent() {
1126e5dd7070Spatrick // FIXME: Find a better way to identify friends.
1127e5dd7070Spatrick if (isa<FunctionDecl>(this))
1128e5dd7070Spatrick if (getParent()->getRedeclContext()->isFileContext() &&
1129e5dd7070Spatrick getLexicalParent()->getRedeclContext()->isRecord())
1130e5dd7070Spatrick return getLexicalParent();
1131e5dd7070Spatrick
1132e5dd7070Spatrick // A lookup within the call operator of a lambda never looks in the lambda
1133e5dd7070Spatrick // class; instead, skip to the context in which that closure type is
1134e5dd7070Spatrick // declared.
1135e5dd7070Spatrick if (isLambdaCallOperator(this))
1136e5dd7070Spatrick return getParent()->getParent();
1137e5dd7070Spatrick
1138e5dd7070Spatrick return getParent();
1139e5dd7070Spatrick }
1140e5dd7070Spatrick
getInnermostBlockDecl() const1141e5dd7070Spatrick const BlockDecl *DeclContext::getInnermostBlockDecl() const {
1142e5dd7070Spatrick const DeclContext *Ctx = this;
1143e5dd7070Spatrick
1144e5dd7070Spatrick do {
1145e5dd7070Spatrick if (Ctx->isClosure())
1146e5dd7070Spatrick return cast<BlockDecl>(Ctx);
1147e5dd7070Spatrick Ctx = Ctx->getParent();
1148e5dd7070Spatrick } while (Ctx);
1149e5dd7070Spatrick
1150e5dd7070Spatrick return nullptr;
1151e5dd7070Spatrick }
1152e5dd7070Spatrick
isInlineNamespace() const1153e5dd7070Spatrick bool DeclContext::isInlineNamespace() const {
1154e5dd7070Spatrick return isNamespace() &&
1155e5dd7070Spatrick cast<NamespaceDecl>(this)->isInline();
1156e5dd7070Spatrick }
1157e5dd7070Spatrick
isStdNamespace() const1158e5dd7070Spatrick bool DeclContext::isStdNamespace() const {
1159e5dd7070Spatrick if (!isNamespace())
1160e5dd7070Spatrick return false;
1161e5dd7070Spatrick
1162e5dd7070Spatrick const auto *ND = cast<NamespaceDecl>(this);
1163e5dd7070Spatrick if (ND->isInline()) {
1164e5dd7070Spatrick return ND->getParent()->isStdNamespace();
1165e5dd7070Spatrick }
1166e5dd7070Spatrick
1167e5dd7070Spatrick if (!getParent()->getRedeclContext()->isTranslationUnit())
1168e5dd7070Spatrick return false;
1169e5dd7070Spatrick
1170e5dd7070Spatrick const IdentifierInfo *II = ND->getIdentifier();
1171e5dd7070Spatrick return II && II->isStr("std");
1172e5dd7070Spatrick }
1173e5dd7070Spatrick
isDependentContext() const1174e5dd7070Spatrick bool DeclContext::isDependentContext() const {
1175e5dd7070Spatrick if (isFileContext())
1176e5dd7070Spatrick return false;
1177e5dd7070Spatrick
1178e5dd7070Spatrick if (isa<ClassTemplatePartialSpecializationDecl>(this))
1179e5dd7070Spatrick return true;
1180e5dd7070Spatrick
1181e5dd7070Spatrick if (const auto *Record = dyn_cast<CXXRecordDecl>(this)) {
1182e5dd7070Spatrick if (Record->getDescribedClassTemplate())
1183e5dd7070Spatrick return true;
1184e5dd7070Spatrick
1185e5dd7070Spatrick if (Record->isDependentLambda())
1186e5dd7070Spatrick return true;
1187*12c85518Srobert if (Record->isNeverDependentLambda())
1188*12c85518Srobert return false;
1189e5dd7070Spatrick }
1190e5dd7070Spatrick
1191e5dd7070Spatrick if (const auto *Function = dyn_cast<FunctionDecl>(this)) {
1192e5dd7070Spatrick if (Function->getDescribedFunctionTemplate())
1193e5dd7070Spatrick return true;
1194e5dd7070Spatrick
1195e5dd7070Spatrick // Friend function declarations are dependent if their *lexical*
1196e5dd7070Spatrick // context is dependent.
1197e5dd7070Spatrick if (cast<Decl>(this)->getFriendObjectKind())
1198e5dd7070Spatrick return getLexicalParent()->isDependentContext();
1199e5dd7070Spatrick }
1200e5dd7070Spatrick
1201e5dd7070Spatrick // FIXME: A variable template is a dependent context, but is not a
1202e5dd7070Spatrick // DeclContext. A context within it (such as a lambda-expression)
1203e5dd7070Spatrick // should be considered dependent.
1204e5dd7070Spatrick
1205e5dd7070Spatrick return getParent() && getParent()->isDependentContext();
1206e5dd7070Spatrick }
1207e5dd7070Spatrick
isTransparentContext() const1208e5dd7070Spatrick bool DeclContext::isTransparentContext() const {
1209e5dd7070Spatrick if (getDeclKind() == Decl::Enum)
1210e5dd7070Spatrick return !cast<EnumDecl>(this)->isScoped();
1211e5dd7070Spatrick
1212*12c85518Srobert return isa<LinkageSpecDecl, ExportDecl, HLSLBufferDecl>(this);
1213e5dd7070Spatrick }
1214e5dd7070Spatrick
isLinkageSpecContext(const DeclContext * DC,LinkageSpecDecl::LanguageIDs ID)1215e5dd7070Spatrick static bool isLinkageSpecContext(const DeclContext *DC,
1216e5dd7070Spatrick LinkageSpecDecl::LanguageIDs ID) {
1217e5dd7070Spatrick while (DC->getDeclKind() != Decl::TranslationUnit) {
1218e5dd7070Spatrick if (DC->getDeclKind() == Decl::LinkageSpec)
1219e5dd7070Spatrick return cast<LinkageSpecDecl>(DC)->getLanguage() == ID;
1220e5dd7070Spatrick DC = DC->getLexicalParent();
1221e5dd7070Spatrick }
1222e5dd7070Spatrick return false;
1223e5dd7070Spatrick }
1224e5dd7070Spatrick
isExternCContext() const1225e5dd7070Spatrick bool DeclContext::isExternCContext() const {
1226e5dd7070Spatrick return isLinkageSpecContext(this, LinkageSpecDecl::lang_c);
1227e5dd7070Spatrick }
1228e5dd7070Spatrick
getExternCContext() const1229e5dd7070Spatrick const LinkageSpecDecl *DeclContext::getExternCContext() const {
1230e5dd7070Spatrick const DeclContext *DC = this;
1231e5dd7070Spatrick while (DC->getDeclKind() != Decl::TranslationUnit) {
1232e5dd7070Spatrick if (DC->getDeclKind() == Decl::LinkageSpec &&
1233e5dd7070Spatrick cast<LinkageSpecDecl>(DC)->getLanguage() == LinkageSpecDecl::lang_c)
1234e5dd7070Spatrick return cast<LinkageSpecDecl>(DC);
1235e5dd7070Spatrick DC = DC->getLexicalParent();
1236e5dd7070Spatrick }
1237e5dd7070Spatrick return nullptr;
1238e5dd7070Spatrick }
1239e5dd7070Spatrick
isExternCXXContext() const1240e5dd7070Spatrick bool DeclContext::isExternCXXContext() const {
1241e5dd7070Spatrick return isLinkageSpecContext(this, LinkageSpecDecl::lang_cxx);
1242e5dd7070Spatrick }
1243e5dd7070Spatrick
Encloses(const DeclContext * DC) const1244e5dd7070Spatrick bool DeclContext::Encloses(const DeclContext *DC) const {
1245e5dd7070Spatrick if (getPrimaryContext() != this)
1246e5dd7070Spatrick return getPrimaryContext()->Encloses(DC);
1247e5dd7070Spatrick
1248e5dd7070Spatrick for (; DC; DC = DC->getParent())
1249*12c85518Srobert if (!isa<LinkageSpecDecl>(DC) && !isa<ExportDecl>(DC) &&
1250*12c85518Srobert DC->getPrimaryContext() == this)
1251e5dd7070Spatrick return true;
1252e5dd7070Spatrick return false;
1253e5dd7070Spatrick }
1254e5dd7070Spatrick
getNonTransparentContext()1255*12c85518Srobert DeclContext *DeclContext::getNonTransparentContext() {
1256*12c85518Srobert DeclContext *DC = this;
1257*12c85518Srobert while (DC->isTransparentContext()) {
1258*12c85518Srobert DC = DC->getParent();
1259*12c85518Srobert assert(DC && "All transparent contexts should have a parent!");
1260*12c85518Srobert }
1261*12c85518Srobert return DC;
1262*12c85518Srobert }
1263*12c85518Srobert
getPrimaryContext()1264e5dd7070Spatrick DeclContext *DeclContext::getPrimaryContext() {
1265e5dd7070Spatrick switch (getDeclKind()) {
1266e5dd7070Spatrick case Decl::ExternCContext:
1267e5dd7070Spatrick case Decl::LinkageSpec:
1268e5dd7070Spatrick case Decl::Export:
1269e5dd7070Spatrick case Decl::Block:
1270e5dd7070Spatrick case Decl::Captured:
1271e5dd7070Spatrick case Decl::OMPDeclareReduction:
1272e5dd7070Spatrick case Decl::OMPDeclareMapper:
1273e5dd7070Spatrick case Decl::RequiresExprBody:
1274e5dd7070Spatrick // There is only one DeclContext for these entities.
1275e5dd7070Spatrick return this;
1276e5dd7070Spatrick
1277*12c85518Srobert case Decl::HLSLBuffer:
1278*12c85518Srobert // Each buffer, even with the same name, is a distinct construct.
1279*12c85518Srobert // Multiple buffers with the same name are allowed for backward
1280*12c85518Srobert // compatibility.
1281*12c85518Srobert // As long as buffers have unique resource bindings the names don't matter.
1282*12c85518Srobert // The names get exposed via the CPU-side reflection API which
1283*12c85518Srobert // supports querying bindings, so we cannot remove them.
1284*12c85518Srobert return this;
1285*12c85518Srobert
1286a9ac8606Spatrick case Decl::TranslationUnit:
1287a9ac8606Spatrick return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
1288e5dd7070Spatrick case Decl::Namespace:
1289e5dd7070Spatrick // The original namespace is our primary context.
1290e5dd7070Spatrick return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
1291e5dd7070Spatrick
1292e5dd7070Spatrick case Decl::ObjCMethod:
1293e5dd7070Spatrick return this;
1294e5dd7070Spatrick
1295e5dd7070Spatrick case Decl::ObjCInterface:
1296e5dd7070Spatrick if (auto *OID = dyn_cast<ObjCInterfaceDecl>(this))
1297e5dd7070Spatrick if (auto *Def = OID->getDefinition())
1298e5dd7070Spatrick return Def;
1299e5dd7070Spatrick return this;
1300e5dd7070Spatrick
1301e5dd7070Spatrick case Decl::ObjCProtocol:
1302e5dd7070Spatrick if (auto *OPD = dyn_cast<ObjCProtocolDecl>(this))
1303e5dd7070Spatrick if (auto *Def = OPD->getDefinition())
1304e5dd7070Spatrick return Def;
1305e5dd7070Spatrick return this;
1306e5dd7070Spatrick
1307e5dd7070Spatrick case Decl::ObjCCategory:
1308e5dd7070Spatrick return this;
1309e5dd7070Spatrick
1310e5dd7070Spatrick case Decl::ObjCImplementation:
1311e5dd7070Spatrick case Decl::ObjCCategoryImpl:
1312e5dd7070Spatrick return this;
1313e5dd7070Spatrick
1314e5dd7070Spatrick default:
1315e5dd7070Spatrick if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) {
1316e5dd7070Spatrick // If this is a tag type that has a definition or is currently
1317e5dd7070Spatrick // being defined, that definition is our primary context.
1318e5dd7070Spatrick auto *Tag = cast<TagDecl>(this);
1319e5dd7070Spatrick
1320e5dd7070Spatrick if (TagDecl *Def = Tag->getDefinition())
1321e5dd7070Spatrick return Def;
1322e5dd7070Spatrick
1323e5dd7070Spatrick if (const auto *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) {
1324e5dd7070Spatrick // Note, TagType::getDecl returns the (partial) definition one exists.
1325e5dd7070Spatrick TagDecl *PossiblePartialDef = TagTy->getDecl();
1326e5dd7070Spatrick if (PossiblePartialDef->isBeingDefined())
1327e5dd7070Spatrick return PossiblePartialDef;
1328e5dd7070Spatrick } else {
1329e5dd7070Spatrick assert(isa<InjectedClassNameType>(Tag->getTypeForDecl()));
1330e5dd7070Spatrick }
1331e5dd7070Spatrick
1332e5dd7070Spatrick return Tag;
1333e5dd7070Spatrick }
1334e5dd7070Spatrick
1335e5dd7070Spatrick assert(getDeclKind() >= Decl::firstFunction &&
1336e5dd7070Spatrick getDeclKind() <= Decl::lastFunction &&
1337e5dd7070Spatrick "Unknown DeclContext kind");
1338e5dd7070Spatrick return this;
1339e5dd7070Spatrick }
1340e5dd7070Spatrick }
1341e5dd7070Spatrick
1342a9ac8606Spatrick template <typename T>
collectAllContextsImpl(T * Self,SmallVectorImpl<DeclContext * > & Contexts)1343a9ac8606Spatrick void collectAllContextsImpl(T *Self, SmallVectorImpl<DeclContext *> &Contexts) {
1344a9ac8606Spatrick for (T *D = Self->getMostRecentDecl(); D; D = D->getPreviousDecl())
1345a9ac8606Spatrick Contexts.push_back(D);
1346e5dd7070Spatrick
1347e5dd7070Spatrick std::reverse(Contexts.begin(), Contexts.end());
1348e5dd7070Spatrick }
1349e5dd7070Spatrick
collectAllContexts(SmallVectorImpl<DeclContext * > & Contexts)1350a9ac8606Spatrick void DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts) {
1351a9ac8606Spatrick Contexts.clear();
1352a9ac8606Spatrick
1353a9ac8606Spatrick Decl::Kind Kind = getDeclKind();
1354a9ac8606Spatrick
1355a9ac8606Spatrick if (Kind == Decl::TranslationUnit)
1356a9ac8606Spatrick collectAllContextsImpl(static_cast<TranslationUnitDecl *>(this), Contexts);
1357a9ac8606Spatrick else if (Kind == Decl::Namespace)
1358a9ac8606Spatrick collectAllContextsImpl(static_cast<NamespaceDecl *>(this), Contexts);
1359a9ac8606Spatrick else
1360a9ac8606Spatrick Contexts.push_back(this);
1361a9ac8606Spatrick }
1362a9ac8606Spatrick
1363e5dd7070Spatrick std::pair<Decl *, Decl *>
BuildDeclChain(ArrayRef<Decl * > Decls,bool FieldsAlreadyLoaded)1364e5dd7070Spatrick DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls,
1365e5dd7070Spatrick bool FieldsAlreadyLoaded) {
1366e5dd7070Spatrick // Build up a chain of declarations via the Decl::NextInContextAndBits field.
1367e5dd7070Spatrick Decl *FirstNewDecl = nullptr;
1368e5dd7070Spatrick Decl *PrevDecl = nullptr;
1369e5dd7070Spatrick for (auto *D : Decls) {
1370e5dd7070Spatrick if (FieldsAlreadyLoaded && isa<FieldDecl>(D))
1371e5dd7070Spatrick continue;
1372e5dd7070Spatrick
1373e5dd7070Spatrick if (PrevDecl)
1374e5dd7070Spatrick PrevDecl->NextInContextAndBits.setPointer(D);
1375e5dd7070Spatrick else
1376e5dd7070Spatrick FirstNewDecl = D;
1377e5dd7070Spatrick
1378e5dd7070Spatrick PrevDecl = D;
1379e5dd7070Spatrick }
1380e5dd7070Spatrick
1381e5dd7070Spatrick return std::make_pair(FirstNewDecl, PrevDecl);
1382e5dd7070Spatrick }
1383e5dd7070Spatrick
1384e5dd7070Spatrick /// We have just acquired external visible storage, and we already have
1385e5dd7070Spatrick /// built a lookup map. For every name in the map, pull in the new names from
1386e5dd7070Spatrick /// the external storage.
reconcileExternalVisibleStorage() const1387e5dd7070Spatrick void DeclContext::reconcileExternalVisibleStorage() const {
1388e5dd7070Spatrick assert(hasNeedToReconcileExternalVisibleStorage() && LookupPtr);
1389e5dd7070Spatrick setNeedToReconcileExternalVisibleStorage(false);
1390e5dd7070Spatrick
1391e5dd7070Spatrick for (auto &Lookup : *LookupPtr)
1392e5dd7070Spatrick Lookup.second.setHasExternalDecls();
1393e5dd7070Spatrick }
1394e5dd7070Spatrick
1395e5dd7070Spatrick /// Load the declarations within this lexical storage from an
1396e5dd7070Spatrick /// external source.
1397e5dd7070Spatrick /// \return \c true if any declarations were added.
1398e5dd7070Spatrick bool
LoadLexicalDeclsFromExternalStorage() const1399e5dd7070Spatrick DeclContext::LoadLexicalDeclsFromExternalStorage() const {
1400e5dd7070Spatrick ExternalASTSource *Source = getParentASTContext().getExternalSource();
1401e5dd7070Spatrick assert(hasExternalLexicalStorage() && Source && "No external storage?");
1402e5dd7070Spatrick
1403e5dd7070Spatrick // Notify that we have a DeclContext that is initializing.
1404e5dd7070Spatrick ExternalASTSource::Deserializing ADeclContext(Source);
1405e5dd7070Spatrick
1406e5dd7070Spatrick // Load the external declarations, if any.
1407e5dd7070Spatrick SmallVector<Decl*, 64> Decls;
1408e5dd7070Spatrick setHasExternalLexicalStorage(false);
1409e5dd7070Spatrick Source->FindExternalLexicalDecls(this, Decls);
1410e5dd7070Spatrick
1411e5dd7070Spatrick if (Decls.empty())
1412e5dd7070Spatrick return false;
1413e5dd7070Spatrick
1414e5dd7070Spatrick // We may have already loaded just the fields of this record, in which case
1415e5dd7070Spatrick // we need to ignore them.
1416e5dd7070Spatrick bool FieldsAlreadyLoaded = false;
1417e5dd7070Spatrick if (const auto *RD = dyn_cast<RecordDecl>(this))
1418e5dd7070Spatrick FieldsAlreadyLoaded = RD->hasLoadedFieldsFromExternalStorage();
1419e5dd7070Spatrick
1420e5dd7070Spatrick // Splice the newly-read declarations into the beginning of the list
1421e5dd7070Spatrick // of declarations.
1422e5dd7070Spatrick Decl *ExternalFirst, *ExternalLast;
1423e5dd7070Spatrick std::tie(ExternalFirst, ExternalLast) =
1424e5dd7070Spatrick BuildDeclChain(Decls, FieldsAlreadyLoaded);
1425e5dd7070Spatrick ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
1426e5dd7070Spatrick FirstDecl = ExternalFirst;
1427e5dd7070Spatrick if (!LastDecl)
1428e5dd7070Spatrick LastDecl = ExternalLast;
1429e5dd7070Spatrick return true;
1430e5dd7070Spatrick }
1431e5dd7070Spatrick
1432e5dd7070Spatrick DeclContext::lookup_result
SetNoExternalVisibleDeclsForName(const DeclContext * DC,DeclarationName Name)1433e5dd7070Spatrick ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
1434e5dd7070Spatrick DeclarationName Name) {
1435e5dd7070Spatrick ASTContext &Context = DC->getParentASTContext();
1436e5dd7070Spatrick StoredDeclsMap *Map;
1437e5dd7070Spatrick if (!(Map = DC->LookupPtr))
1438e5dd7070Spatrick Map = DC->CreateStoredDeclsMap(Context);
1439e5dd7070Spatrick if (DC->hasNeedToReconcileExternalVisibleStorage())
1440e5dd7070Spatrick DC->reconcileExternalVisibleStorage();
1441e5dd7070Spatrick
1442e5dd7070Spatrick (*Map)[Name].removeExternalDecls();
1443e5dd7070Spatrick
1444e5dd7070Spatrick return DeclContext::lookup_result();
1445e5dd7070Spatrick }
1446e5dd7070Spatrick
1447e5dd7070Spatrick DeclContext::lookup_result
SetExternalVisibleDeclsForName(const DeclContext * DC,DeclarationName Name,ArrayRef<NamedDecl * > Decls)1448e5dd7070Spatrick ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
1449e5dd7070Spatrick DeclarationName Name,
1450e5dd7070Spatrick ArrayRef<NamedDecl*> Decls) {
1451e5dd7070Spatrick ASTContext &Context = DC->getParentASTContext();
1452e5dd7070Spatrick StoredDeclsMap *Map;
1453e5dd7070Spatrick if (!(Map = DC->LookupPtr))
1454e5dd7070Spatrick Map = DC->CreateStoredDeclsMap(Context);
1455e5dd7070Spatrick if (DC->hasNeedToReconcileExternalVisibleStorage())
1456e5dd7070Spatrick DC->reconcileExternalVisibleStorage();
1457e5dd7070Spatrick
1458e5dd7070Spatrick StoredDeclsList &List = (*Map)[Name];
1459a9ac8606Spatrick List.replaceExternalDecls(Decls);
1460e5dd7070Spatrick return List.getLookupResult();
1461e5dd7070Spatrick }
1462e5dd7070Spatrick
decls_begin() const1463e5dd7070Spatrick DeclContext::decl_iterator DeclContext::decls_begin() const {
1464e5dd7070Spatrick if (hasExternalLexicalStorage())
1465e5dd7070Spatrick LoadLexicalDeclsFromExternalStorage();
1466e5dd7070Spatrick return decl_iterator(FirstDecl);
1467e5dd7070Spatrick }
1468e5dd7070Spatrick
decls_empty() const1469e5dd7070Spatrick bool DeclContext::decls_empty() const {
1470e5dd7070Spatrick if (hasExternalLexicalStorage())
1471e5dd7070Spatrick LoadLexicalDeclsFromExternalStorage();
1472e5dd7070Spatrick
1473e5dd7070Spatrick return !FirstDecl;
1474e5dd7070Spatrick }
1475e5dd7070Spatrick
containsDecl(Decl * D) const1476e5dd7070Spatrick bool DeclContext::containsDecl(Decl *D) const {
1477e5dd7070Spatrick return (D->getLexicalDeclContext() == this &&
1478e5dd7070Spatrick (D->NextInContextAndBits.getPointer() || D == LastDecl));
1479e5dd7070Spatrick }
1480e5dd7070Spatrick
containsDeclAndLoad(Decl * D) const1481e5dd7070Spatrick bool DeclContext::containsDeclAndLoad(Decl *D) const {
1482e5dd7070Spatrick if (hasExternalLexicalStorage())
1483e5dd7070Spatrick LoadLexicalDeclsFromExternalStorage();
1484e5dd7070Spatrick return containsDecl(D);
1485e5dd7070Spatrick }
1486e5dd7070Spatrick
1487e5dd7070Spatrick /// shouldBeHidden - Determine whether a declaration which was declared
1488e5dd7070Spatrick /// within its semantic context should be invisible to qualified name lookup.
shouldBeHidden(NamedDecl * D)1489e5dd7070Spatrick static bool shouldBeHidden(NamedDecl *D) {
1490e5dd7070Spatrick // Skip unnamed declarations.
1491e5dd7070Spatrick if (!D->getDeclName())
1492e5dd7070Spatrick return true;
1493e5dd7070Spatrick
1494e5dd7070Spatrick // Skip entities that can't be found by name lookup into a particular
1495e5dd7070Spatrick // context.
1496e5dd7070Spatrick if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
1497e5dd7070Spatrick D->isTemplateParameter())
1498e5dd7070Spatrick return true;
1499e5dd7070Spatrick
1500e5dd7070Spatrick // Skip friends and local extern declarations unless they're the first
1501e5dd7070Spatrick // declaration of the entity.
1502e5dd7070Spatrick if ((D->isLocalExternDecl() || D->getFriendObjectKind()) &&
1503e5dd7070Spatrick D != D->getCanonicalDecl())
1504e5dd7070Spatrick return true;
1505e5dd7070Spatrick
1506e5dd7070Spatrick // Skip template specializations.
1507e5dd7070Spatrick // FIXME: This feels like a hack. Should DeclarationName support
1508e5dd7070Spatrick // template-ids, or is there a better way to keep specializations
1509e5dd7070Spatrick // from being visible?
1510e5dd7070Spatrick if (isa<ClassTemplateSpecializationDecl>(D))
1511e5dd7070Spatrick return true;
1512e5dd7070Spatrick if (auto *FD = dyn_cast<FunctionDecl>(D))
1513e5dd7070Spatrick if (FD->isFunctionTemplateSpecialization())
1514e5dd7070Spatrick return true;
1515e5dd7070Spatrick
1516ec727ea7Spatrick // Hide destructors that are invalid. There should always be one destructor,
1517ec727ea7Spatrick // but if it is an invalid decl, another one is created. We need to hide the
1518ec727ea7Spatrick // invalid one from places that expect exactly one destructor, like the
1519ec727ea7Spatrick // serialization code.
1520ec727ea7Spatrick if (isa<CXXDestructorDecl>(D) && D->isInvalidDecl())
1521ec727ea7Spatrick return true;
1522ec727ea7Spatrick
1523e5dd7070Spatrick return false;
1524e5dd7070Spatrick }
1525e5dd7070Spatrick
removeDecl(Decl * D)1526e5dd7070Spatrick void DeclContext::removeDecl(Decl *D) {
1527e5dd7070Spatrick assert(D->getLexicalDeclContext() == this &&
1528e5dd7070Spatrick "decl being removed from non-lexical context");
1529e5dd7070Spatrick assert((D->NextInContextAndBits.getPointer() || D == LastDecl) &&
1530e5dd7070Spatrick "decl is not in decls list");
1531e5dd7070Spatrick
1532e5dd7070Spatrick // Remove D from the decl chain. This is O(n) but hopefully rare.
1533e5dd7070Spatrick if (D == FirstDecl) {
1534e5dd7070Spatrick if (D == LastDecl)
1535e5dd7070Spatrick FirstDecl = LastDecl = nullptr;
1536e5dd7070Spatrick else
1537e5dd7070Spatrick FirstDecl = D->NextInContextAndBits.getPointer();
1538e5dd7070Spatrick } else {
1539e5dd7070Spatrick for (Decl *I = FirstDecl; true; I = I->NextInContextAndBits.getPointer()) {
1540e5dd7070Spatrick assert(I && "decl not found in linked list");
1541e5dd7070Spatrick if (I->NextInContextAndBits.getPointer() == D) {
1542e5dd7070Spatrick I->NextInContextAndBits.setPointer(D->NextInContextAndBits.getPointer());
1543e5dd7070Spatrick if (D == LastDecl) LastDecl = I;
1544e5dd7070Spatrick break;
1545e5dd7070Spatrick }
1546e5dd7070Spatrick }
1547e5dd7070Spatrick }
1548e5dd7070Spatrick
1549e5dd7070Spatrick // Mark that D is no longer in the decl chain.
1550e5dd7070Spatrick D->NextInContextAndBits.setPointer(nullptr);
1551e5dd7070Spatrick
1552e5dd7070Spatrick // Remove D from the lookup table if necessary.
1553e5dd7070Spatrick if (isa<NamedDecl>(D)) {
1554e5dd7070Spatrick auto *ND = cast<NamedDecl>(D);
1555e5dd7070Spatrick
1556e5dd7070Spatrick // Do not try to remove the declaration if that is invisible to qualified
1557e5dd7070Spatrick // lookup. E.g. template specializations are skipped.
1558e5dd7070Spatrick if (shouldBeHidden(ND))
1559e5dd7070Spatrick return;
1560e5dd7070Spatrick
1561e5dd7070Spatrick // Remove only decls that have a name
1562e5dd7070Spatrick if (!ND->getDeclName())
1563e5dd7070Spatrick return;
1564e5dd7070Spatrick
1565e5dd7070Spatrick auto *DC = D->getDeclContext();
1566e5dd7070Spatrick do {
1567e5dd7070Spatrick StoredDeclsMap *Map = DC->getPrimaryContext()->LookupPtr;
1568e5dd7070Spatrick if (Map) {
1569e5dd7070Spatrick StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
1570e5dd7070Spatrick assert(Pos != Map->end() && "no lookup entry for decl");
1571*12c85518Srobert StoredDeclsList &List = Pos->second;
1572*12c85518Srobert List.remove(ND);
1573*12c85518Srobert // Clean up the entry if there are no more decls.
1574*12c85518Srobert if (List.isNull())
1575*12c85518Srobert Map->erase(Pos);
1576e5dd7070Spatrick }
1577e5dd7070Spatrick } while (DC->isTransparentContext() && (DC = DC->getParent()));
1578e5dd7070Spatrick }
1579e5dd7070Spatrick }
1580e5dd7070Spatrick
addHiddenDecl(Decl * D)1581e5dd7070Spatrick void DeclContext::addHiddenDecl(Decl *D) {
1582e5dd7070Spatrick assert(D->getLexicalDeclContext() == this &&
1583e5dd7070Spatrick "Decl inserted into wrong lexical context");
1584e5dd7070Spatrick assert(!D->getNextDeclInContext() && D != LastDecl &&
1585e5dd7070Spatrick "Decl already inserted into a DeclContext");
1586e5dd7070Spatrick
1587e5dd7070Spatrick if (FirstDecl) {
1588e5dd7070Spatrick LastDecl->NextInContextAndBits.setPointer(D);
1589e5dd7070Spatrick LastDecl = D;
1590e5dd7070Spatrick } else {
1591e5dd7070Spatrick FirstDecl = LastDecl = D;
1592e5dd7070Spatrick }
1593e5dd7070Spatrick
1594e5dd7070Spatrick // Notify a C++ record declaration that we've added a member, so it can
1595e5dd7070Spatrick // update its class-specific state.
1596e5dd7070Spatrick if (auto *Record = dyn_cast<CXXRecordDecl>(this))
1597e5dd7070Spatrick Record->addedMember(D);
1598e5dd7070Spatrick
1599e5dd7070Spatrick // If this is a newly-created (not de-serialized) import declaration, wire
1600e5dd7070Spatrick // it in to the list of local import declarations.
1601e5dd7070Spatrick if (!D->isFromASTFile()) {
1602e5dd7070Spatrick if (auto *Import = dyn_cast<ImportDecl>(D))
1603e5dd7070Spatrick D->getASTContext().addedLocalImportDecl(Import);
1604e5dd7070Spatrick }
1605e5dd7070Spatrick }
1606e5dd7070Spatrick
addDecl(Decl * D)1607e5dd7070Spatrick void DeclContext::addDecl(Decl *D) {
1608e5dd7070Spatrick addHiddenDecl(D);
1609e5dd7070Spatrick
1610e5dd7070Spatrick if (auto *ND = dyn_cast<NamedDecl>(D))
1611e5dd7070Spatrick ND->getDeclContext()->getPrimaryContext()->
1612e5dd7070Spatrick makeDeclVisibleInContextWithFlags(ND, false, true);
1613e5dd7070Spatrick }
1614e5dd7070Spatrick
addDeclInternal(Decl * D)1615e5dd7070Spatrick void DeclContext::addDeclInternal(Decl *D) {
1616e5dd7070Spatrick addHiddenDecl(D);
1617e5dd7070Spatrick
1618e5dd7070Spatrick if (auto *ND = dyn_cast<NamedDecl>(D))
1619e5dd7070Spatrick ND->getDeclContext()->getPrimaryContext()->
1620e5dd7070Spatrick makeDeclVisibleInContextWithFlags(ND, true, true);
1621e5dd7070Spatrick }
1622e5dd7070Spatrick
1623e5dd7070Spatrick /// buildLookup - Build the lookup data structure with all of the
1624e5dd7070Spatrick /// declarations in this DeclContext (and any other contexts linked
1625e5dd7070Spatrick /// to it or transparent contexts nested within it) and return it.
1626e5dd7070Spatrick ///
1627e5dd7070Spatrick /// Note that the produced map may miss out declarations from an
1628e5dd7070Spatrick /// external source. If it does, those entries will be marked with
1629e5dd7070Spatrick /// the 'hasExternalDecls' flag.
buildLookup()1630e5dd7070Spatrick StoredDeclsMap *DeclContext::buildLookup() {
1631e5dd7070Spatrick assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
1632e5dd7070Spatrick
1633e5dd7070Spatrick if (!hasLazyLocalLexicalLookups() &&
1634e5dd7070Spatrick !hasLazyExternalLexicalLookups())
1635e5dd7070Spatrick return LookupPtr;
1636e5dd7070Spatrick
1637e5dd7070Spatrick SmallVector<DeclContext *, 2> Contexts;
1638e5dd7070Spatrick collectAllContexts(Contexts);
1639e5dd7070Spatrick
1640e5dd7070Spatrick if (hasLazyExternalLexicalLookups()) {
1641e5dd7070Spatrick setHasLazyExternalLexicalLookups(false);
1642e5dd7070Spatrick for (auto *DC : Contexts) {
1643e5dd7070Spatrick if (DC->hasExternalLexicalStorage()) {
1644e5dd7070Spatrick bool LoadedDecls = DC->LoadLexicalDeclsFromExternalStorage();
1645e5dd7070Spatrick setHasLazyLocalLexicalLookups(
1646e5dd7070Spatrick hasLazyLocalLexicalLookups() | LoadedDecls );
1647e5dd7070Spatrick }
1648e5dd7070Spatrick }
1649e5dd7070Spatrick
1650e5dd7070Spatrick if (!hasLazyLocalLexicalLookups())
1651e5dd7070Spatrick return LookupPtr;
1652e5dd7070Spatrick }
1653e5dd7070Spatrick
1654e5dd7070Spatrick for (auto *DC : Contexts)
1655e5dd7070Spatrick buildLookupImpl(DC, hasExternalVisibleStorage());
1656e5dd7070Spatrick
1657e5dd7070Spatrick // We no longer have any lazy decls.
1658e5dd7070Spatrick setHasLazyLocalLexicalLookups(false);
1659e5dd7070Spatrick return LookupPtr;
1660e5dd7070Spatrick }
1661e5dd7070Spatrick
1662e5dd7070Spatrick /// buildLookupImpl - Build part of the lookup data structure for the
1663e5dd7070Spatrick /// declarations contained within DCtx, which will either be this
1664e5dd7070Spatrick /// DeclContext, a DeclContext linked to it, or a transparent context
1665e5dd7070Spatrick /// nested within it.
buildLookupImpl(DeclContext * DCtx,bool Internal)1666e5dd7070Spatrick void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
1667e5dd7070Spatrick for (auto *D : DCtx->noload_decls()) {
1668e5dd7070Spatrick // Insert this declaration into the lookup structure, but only if
1669e5dd7070Spatrick // it's semantically within its decl context. Any other decls which
1670e5dd7070Spatrick // should be found in this context are added eagerly.
1671e5dd7070Spatrick //
1672e5dd7070Spatrick // If it's from an AST file, don't add it now. It'll get handled by
1673e5dd7070Spatrick // FindExternalVisibleDeclsByName if needed. Exception: if we're not
1674e5dd7070Spatrick // in C++, we do not track external visible decls for the TU, so in
1675e5dd7070Spatrick // that case we need to collect them all here.
1676e5dd7070Spatrick if (auto *ND = dyn_cast<NamedDecl>(D))
1677e5dd7070Spatrick if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND) &&
1678e5dd7070Spatrick (!ND->isFromASTFile() ||
1679e5dd7070Spatrick (isTranslationUnit() &&
1680e5dd7070Spatrick !getParentASTContext().getLangOpts().CPlusPlus)))
1681e5dd7070Spatrick makeDeclVisibleInContextImpl(ND, Internal);
1682e5dd7070Spatrick
1683e5dd7070Spatrick // If this declaration is itself a transparent declaration context
1684e5dd7070Spatrick // or inline namespace, add the members of this declaration of that
1685e5dd7070Spatrick // context (recursively).
1686e5dd7070Spatrick if (auto *InnerCtx = dyn_cast<DeclContext>(D))
1687e5dd7070Spatrick if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
1688e5dd7070Spatrick buildLookupImpl(InnerCtx, Internal);
1689e5dd7070Spatrick }
1690e5dd7070Spatrick }
1691e5dd7070Spatrick
1692e5dd7070Spatrick DeclContext::lookup_result
lookup(DeclarationName Name) const1693e5dd7070Spatrick DeclContext::lookup(DeclarationName Name) const {
1694*12c85518Srobert // For transparent DeclContext, we should lookup in their enclosing context.
1695*12c85518Srobert if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export)
1696*12c85518Srobert return getParent()->lookup(Name);
1697e5dd7070Spatrick
1698e5dd7070Spatrick const DeclContext *PrimaryContext = getPrimaryContext();
1699e5dd7070Spatrick if (PrimaryContext != this)
1700e5dd7070Spatrick return PrimaryContext->lookup(Name);
1701e5dd7070Spatrick
1702e5dd7070Spatrick // If we have an external source, ensure that any later redeclarations of this
1703e5dd7070Spatrick // context have been loaded, since they may add names to the result of this
1704e5dd7070Spatrick // lookup (or add external visible storage).
1705e5dd7070Spatrick ExternalASTSource *Source = getParentASTContext().getExternalSource();
1706e5dd7070Spatrick if (Source)
1707e5dd7070Spatrick (void)cast<Decl>(this)->getMostRecentDecl();
1708e5dd7070Spatrick
1709e5dd7070Spatrick if (hasExternalVisibleStorage()) {
1710e5dd7070Spatrick assert(Source && "external visible storage but no external source?");
1711e5dd7070Spatrick
1712e5dd7070Spatrick if (hasNeedToReconcileExternalVisibleStorage())
1713e5dd7070Spatrick reconcileExternalVisibleStorage();
1714e5dd7070Spatrick
1715e5dd7070Spatrick StoredDeclsMap *Map = LookupPtr;
1716e5dd7070Spatrick
1717e5dd7070Spatrick if (hasLazyLocalLexicalLookups() ||
1718e5dd7070Spatrick hasLazyExternalLexicalLookups())
1719e5dd7070Spatrick // FIXME: Make buildLookup const?
1720e5dd7070Spatrick Map = const_cast<DeclContext*>(this)->buildLookup();
1721e5dd7070Spatrick
1722e5dd7070Spatrick if (!Map)
1723e5dd7070Spatrick Map = CreateStoredDeclsMap(getParentASTContext());
1724e5dd7070Spatrick
1725e5dd7070Spatrick // If we have a lookup result with no external decls, we are done.
1726e5dd7070Spatrick std::pair<StoredDeclsMap::iterator, bool> R =
1727e5dd7070Spatrick Map->insert(std::make_pair(Name, StoredDeclsList()));
1728e5dd7070Spatrick if (!R.second && !R.first->second.hasExternalDecls())
1729e5dd7070Spatrick return R.first->second.getLookupResult();
1730e5dd7070Spatrick
1731e5dd7070Spatrick if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) {
1732e5dd7070Spatrick if (StoredDeclsMap *Map = LookupPtr) {
1733e5dd7070Spatrick StoredDeclsMap::iterator I = Map->find(Name);
1734e5dd7070Spatrick if (I != Map->end())
1735e5dd7070Spatrick return I->second.getLookupResult();
1736e5dd7070Spatrick }
1737e5dd7070Spatrick }
1738e5dd7070Spatrick
1739e5dd7070Spatrick return {};
1740e5dd7070Spatrick }
1741e5dd7070Spatrick
1742e5dd7070Spatrick StoredDeclsMap *Map = LookupPtr;
1743e5dd7070Spatrick if (hasLazyLocalLexicalLookups() ||
1744e5dd7070Spatrick hasLazyExternalLexicalLookups())
1745e5dd7070Spatrick Map = const_cast<DeclContext*>(this)->buildLookup();
1746e5dd7070Spatrick
1747e5dd7070Spatrick if (!Map)
1748e5dd7070Spatrick return {};
1749e5dd7070Spatrick
1750e5dd7070Spatrick StoredDeclsMap::iterator I = Map->find(Name);
1751e5dd7070Spatrick if (I == Map->end())
1752e5dd7070Spatrick return {};
1753e5dd7070Spatrick
1754e5dd7070Spatrick return I->second.getLookupResult();
1755e5dd7070Spatrick }
1756e5dd7070Spatrick
1757e5dd7070Spatrick DeclContext::lookup_result
noload_lookup(DeclarationName Name)1758e5dd7070Spatrick DeclContext::noload_lookup(DeclarationName Name) {
1759e5dd7070Spatrick assert(getDeclKind() != Decl::LinkageSpec &&
1760e5dd7070Spatrick getDeclKind() != Decl::Export &&
1761e5dd7070Spatrick "should not perform lookups into transparent contexts");
1762e5dd7070Spatrick
1763e5dd7070Spatrick DeclContext *PrimaryContext = getPrimaryContext();
1764e5dd7070Spatrick if (PrimaryContext != this)
1765e5dd7070Spatrick return PrimaryContext->noload_lookup(Name);
1766e5dd7070Spatrick
1767e5dd7070Spatrick loadLazyLocalLexicalLookups();
1768e5dd7070Spatrick StoredDeclsMap *Map = LookupPtr;
1769e5dd7070Spatrick if (!Map)
1770e5dd7070Spatrick return {};
1771e5dd7070Spatrick
1772e5dd7070Spatrick StoredDeclsMap::iterator I = Map->find(Name);
1773e5dd7070Spatrick return I != Map->end() ? I->second.getLookupResult()
1774e5dd7070Spatrick : lookup_result();
1775e5dd7070Spatrick }
1776e5dd7070Spatrick
1777e5dd7070Spatrick // If we have any lazy lexical declarations not in our lookup map, add them
1778e5dd7070Spatrick // now. Don't import any external declarations, not even if we know we have
1779e5dd7070Spatrick // some missing from the external visible lookups.
loadLazyLocalLexicalLookups()1780e5dd7070Spatrick void DeclContext::loadLazyLocalLexicalLookups() {
1781e5dd7070Spatrick if (hasLazyLocalLexicalLookups()) {
1782e5dd7070Spatrick SmallVector<DeclContext *, 2> Contexts;
1783e5dd7070Spatrick collectAllContexts(Contexts);
1784e5dd7070Spatrick for (auto *Context : Contexts)
1785e5dd7070Spatrick buildLookupImpl(Context, hasExternalVisibleStorage());
1786e5dd7070Spatrick setHasLazyLocalLexicalLookups(false);
1787e5dd7070Spatrick }
1788e5dd7070Spatrick }
1789e5dd7070Spatrick
localUncachedLookup(DeclarationName Name,SmallVectorImpl<NamedDecl * > & Results)1790e5dd7070Spatrick void DeclContext::localUncachedLookup(DeclarationName Name,
1791e5dd7070Spatrick SmallVectorImpl<NamedDecl *> &Results) {
1792e5dd7070Spatrick Results.clear();
1793e5dd7070Spatrick
1794e5dd7070Spatrick // If there's no external storage, just perform a normal lookup and copy
1795e5dd7070Spatrick // the results.
1796e5dd7070Spatrick if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) {
1797e5dd7070Spatrick lookup_result LookupResults = lookup(Name);
1798e5dd7070Spatrick Results.insert(Results.end(), LookupResults.begin(), LookupResults.end());
1799*12c85518Srobert if (!Results.empty())
1800e5dd7070Spatrick return;
1801e5dd7070Spatrick }
1802e5dd7070Spatrick
1803e5dd7070Spatrick // If we have a lookup table, check there first. Maybe we'll get lucky.
1804e5dd7070Spatrick // FIXME: Should we be checking these flags on the primary context?
1805e5dd7070Spatrick if (Name && !hasLazyLocalLexicalLookups() &&
1806e5dd7070Spatrick !hasLazyExternalLexicalLookups()) {
1807e5dd7070Spatrick if (StoredDeclsMap *Map = LookupPtr) {
1808e5dd7070Spatrick StoredDeclsMap::iterator Pos = Map->find(Name);
1809e5dd7070Spatrick if (Pos != Map->end()) {
1810e5dd7070Spatrick Results.insert(Results.end(),
1811e5dd7070Spatrick Pos->second.getLookupResult().begin(),
1812e5dd7070Spatrick Pos->second.getLookupResult().end());
1813e5dd7070Spatrick return;
1814e5dd7070Spatrick }
1815e5dd7070Spatrick }
1816e5dd7070Spatrick }
1817e5dd7070Spatrick
1818e5dd7070Spatrick // Slow case: grovel through the declarations in our chain looking for
1819e5dd7070Spatrick // matches.
1820e5dd7070Spatrick // FIXME: If we have lazy external declarations, this will not find them!
1821e5dd7070Spatrick // FIXME: Should we CollectAllContexts and walk them all here?
1822e5dd7070Spatrick for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) {
1823e5dd7070Spatrick if (auto *ND = dyn_cast<NamedDecl>(D))
1824e5dd7070Spatrick if (ND->getDeclName() == Name)
1825e5dd7070Spatrick Results.push_back(ND);
1826e5dd7070Spatrick }
1827e5dd7070Spatrick }
1828e5dd7070Spatrick
getRedeclContext()1829e5dd7070Spatrick DeclContext *DeclContext::getRedeclContext() {
1830e5dd7070Spatrick DeclContext *Ctx = this;
1831e5dd7070Spatrick
1832e5dd7070Spatrick // In C, a record type is the redeclaration context for its fields only. If
1833e5dd7070Spatrick // we arrive at a record context after skipping anything else, we should skip
1834e5dd7070Spatrick // the record as well. Currently, this means skipping enumerations because
1835e5dd7070Spatrick // they're the only transparent context that can exist within a struct or
1836e5dd7070Spatrick // union.
1837e5dd7070Spatrick bool SkipRecords = getDeclKind() == Decl::Kind::Enum &&
1838e5dd7070Spatrick !getParentASTContext().getLangOpts().CPlusPlus;
1839e5dd7070Spatrick
1840e5dd7070Spatrick // Skip through contexts to get to the redeclaration context. Transparent
1841e5dd7070Spatrick // contexts are always skipped.
1842e5dd7070Spatrick while ((SkipRecords && Ctx->isRecord()) || Ctx->isTransparentContext())
1843e5dd7070Spatrick Ctx = Ctx->getParent();
1844e5dd7070Spatrick return Ctx;
1845e5dd7070Spatrick }
1846e5dd7070Spatrick
getEnclosingNamespaceContext()1847e5dd7070Spatrick DeclContext *DeclContext::getEnclosingNamespaceContext() {
1848e5dd7070Spatrick DeclContext *Ctx = this;
1849e5dd7070Spatrick // Skip through non-namespace, non-translation-unit contexts.
1850e5dd7070Spatrick while (!Ctx->isFileContext())
1851e5dd7070Spatrick Ctx = Ctx->getParent();
1852e5dd7070Spatrick return Ctx->getPrimaryContext();
1853e5dd7070Spatrick }
1854e5dd7070Spatrick
getOuterLexicalRecordContext()1855e5dd7070Spatrick RecordDecl *DeclContext::getOuterLexicalRecordContext() {
1856e5dd7070Spatrick // Loop until we find a non-record context.
1857e5dd7070Spatrick RecordDecl *OutermostRD = nullptr;
1858e5dd7070Spatrick DeclContext *DC = this;
1859e5dd7070Spatrick while (DC->isRecord()) {
1860e5dd7070Spatrick OutermostRD = cast<RecordDecl>(DC);
1861e5dd7070Spatrick DC = DC->getLexicalParent();
1862e5dd7070Spatrick }
1863e5dd7070Spatrick return OutermostRD;
1864e5dd7070Spatrick }
1865e5dd7070Spatrick
InEnclosingNamespaceSetOf(const DeclContext * O) const1866e5dd7070Spatrick bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
1867e5dd7070Spatrick // For non-file contexts, this is equivalent to Equals.
1868e5dd7070Spatrick if (!isFileContext())
1869e5dd7070Spatrick return O->Equals(this);
1870e5dd7070Spatrick
1871e5dd7070Spatrick do {
1872e5dd7070Spatrick if (O->Equals(this))
1873e5dd7070Spatrick return true;
1874e5dd7070Spatrick
1875e5dd7070Spatrick const auto *NS = dyn_cast<NamespaceDecl>(O);
1876e5dd7070Spatrick if (!NS || !NS->isInline())
1877e5dd7070Spatrick break;
1878e5dd7070Spatrick O = NS->getParent();
1879e5dd7070Spatrick } while (O);
1880e5dd7070Spatrick
1881e5dd7070Spatrick return false;
1882e5dd7070Spatrick }
1883e5dd7070Spatrick
makeDeclVisibleInContext(NamedDecl * D)1884e5dd7070Spatrick void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
1885e5dd7070Spatrick DeclContext *PrimaryDC = this->getPrimaryContext();
1886e5dd7070Spatrick DeclContext *DeclDC = D->getDeclContext()->getPrimaryContext();
1887e5dd7070Spatrick // If the decl is being added outside of its semantic decl context, we
1888e5dd7070Spatrick // need to ensure that we eagerly build the lookup information for it.
1889e5dd7070Spatrick PrimaryDC->makeDeclVisibleInContextWithFlags(D, false, PrimaryDC == DeclDC);
1890e5dd7070Spatrick }
1891e5dd7070Spatrick
makeDeclVisibleInContextWithFlags(NamedDecl * D,bool Internal,bool Recoverable)1892e5dd7070Spatrick void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
1893e5dd7070Spatrick bool Recoverable) {
1894e5dd7070Spatrick assert(this == getPrimaryContext() && "expected a primary DC");
1895e5dd7070Spatrick
1896e5dd7070Spatrick if (!isLookupContext()) {
1897e5dd7070Spatrick if (isTransparentContext())
1898e5dd7070Spatrick getParent()->getPrimaryContext()
1899e5dd7070Spatrick ->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
1900e5dd7070Spatrick return;
1901e5dd7070Spatrick }
1902e5dd7070Spatrick
1903e5dd7070Spatrick // Skip declarations which should be invisible to name lookup.
1904e5dd7070Spatrick if (shouldBeHidden(D))
1905e5dd7070Spatrick return;
1906e5dd7070Spatrick
1907e5dd7070Spatrick // If we already have a lookup data structure, perform the insertion into
1908e5dd7070Spatrick // it. If we might have externally-stored decls with this name, look them
1909e5dd7070Spatrick // up and perform the insertion. If this decl was declared outside its
1910e5dd7070Spatrick // semantic context, buildLookup won't add it, so add it now.
1911e5dd7070Spatrick //
1912e5dd7070Spatrick // FIXME: As a performance hack, don't add such decls into the translation
1913e5dd7070Spatrick // unit unless we're in C++, since qualified lookup into the TU is never
1914e5dd7070Spatrick // performed.
1915e5dd7070Spatrick if (LookupPtr || hasExternalVisibleStorage() ||
1916e5dd7070Spatrick ((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) &&
1917e5dd7070Spatrick (getParentASTContext().getLangOpts().CPlusPlus ||
1918e5dd7070Spatrick !isTranslationUnit()))) {
1919e5dd7070Spatrick // If we have lazily omitted any decls, they might have the same name as
1920e5dd7070Spatrick // the decl which we are adding, so build a full lookup table before adding
1921e5dd7070Spatrick // this decl.
1922e5dd7070Spatrick buildLookup();
1923e5dd7070Spatrick makeDeclVisibleInContextImpl(D, Internal);
1924e5dd7070Spatrick } else {
1925e5dd7070Spatrick setHasLazyLocalLexicalLookups(true);
1926e5dd7070Spatrick }
1927e5dd7070Spatrick
1928e5dd7070Spatrick // If we are a transparent context or inline namespace, insert into our
1929e5dd7070Spatrick // parent context, too. This operation is recursive.
1930e5dd7070Spatrick if (isTransparentContext() || isInlineNamespace())
1931e5dd7070Spatrick getParent()->getPrimaryContext()->
1932e5dd7070Spatrick makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
1933e5dd7070Spatrick
1934e5dd7070Spatrick auto *DCAsDecl = cast<Decl>(this);
1935e5dd7070Spatrick // Notify that a decl was made visible unless we are a Tag being defined.
1936e5dd7070Spatrick if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
1937e5dd7070Spatrick if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
1938e5dd7070Spatrick L->AddedVisibleDecl(this, D);
1939e5dd7070Spatrick }
1940e5dd7070Spatrick
makeDeclVisibleInContextImpl(NamedDecl * D,bool Internal)1941e5dd7070Spatrick void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
1942e5dd7070Spatrick // Find or create the stored declaration map.
1943e5dd7070Spatrick StoredDeclsMap *Map = LookupPtr;
1944e5dd7070Spatrick if (!Map) {
1945e5dd7070Spatrick ASTContext *C = &getParentASTContext();
1946e5dd7070Spatrick Map = CreateStoredDeclsMap(*C);
1947e5dd7070Spatrick }
1948e5dd7070Spatrick
1949e5dd7070Spatrick // If there is an external AST source, load any declarations it knows about
1950e5dd7070Spatrick // with this declaration's name.
1951e5dd7070Spatrick // If the lookup table contains an entry about this name it means that we
1952e5dd7070Spatrick // have already checked the external source.
1953e5dd7070Spatrick if (!Internal)
1954e5dd7070Spatrick if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
1955e5dd7070Spatrick if (hasExternalVisibleStorage() &&
1956e5dd7070Spatrick Map->find(D->getDeclName()) == Map->end())
1957e5dd7070Spatrick Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
1958e5dd7070Spatrick
1959e5dd7070Spatrick // Insert this declaration into the map.
1960e5dd7070Spatrick StoredDeclsList &DeclNameEntries = (*Map)[D->getDeclName()];
1961e5dd7070Spatrick
1962e5dd7070Spatrick if (Internal) {
1963e5dd7070Spatrick // If this is being added as part of loading an external declaration,
1964e5dd7070Spatrick // this may not be the only external declaration with this name.
1965e5dd7070Spatrick // In this case, we never try to replace an existing declaration; we'll
1966e5dd7070Spatrick // handle that when we finalize the list of declarations for this name.
1967e5dd7070Spatrick DeclNameEntries.setHasExternalDecls();
1968a9ac8606Spatrick DeclNameEntries.prependDeclNoReplace(D);
1969e5dd7070Spatrick return;
1970e5dd7070Spatrick }
1971e5dd7070Spatrick
1972a9ac8606Spatrick DeclNameEntries.addOrReplaceDecl(D);
1973e5dd7070Spatrick }
1974e5dd7070Spatrick
operator *() const1975e5dd7070Spatrick UsingDirectiveDecl *DeclContext::udir_iterator::operator*() const {
1976e5dd7070Spatrick return cast<UsingDirectiveDecl>(*I);
1977e5dd7070Spatrick }
1978e5dd7070Spatrick
1979e5dd7070Spatrick /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
1980e5dd7070Spatrick /// this context.
using_directives() const1981e5dd7070Spatrick DeclContext::udir_range DeclContext::using_directives() const {
1982e5dd7070Spatrick // FIXME: Use something more efficient than normal lookup for using
1983e5dd7070Spatrick // directives. In C++, using directives are looked up more than anything else.
1984e5dd7070Spatrick lookup_result Result = lookup(UsingDirectiveDecl::getName());
1985e5dd7070Spatrick return udir_range(Result.begin(), Result.end());
1986e5dd7070Spatrick }
1987e5dd7070Spatrick
1988e5dd7070Spatrick //===----------------------------------------------------------------------===//
1989e5dd7070Spatrick // Creation and Destruction of StoredDeclsMaps. //
1990e5dd7070Spatrick //===----------------------------------------------------------------------===//
1991e5dd7070Spatrick
CreateStoredDeclsMap(ASTContext & C) const1992e5dd7070Spatrick StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
1993e5dd7070Spatrick assert(!LookupPtr && "context already has a decls map");
1994e5dd7070Spatrick assert(getPrimaryContext() == this &&
1995e5dd7070Spatrick "creating decls map on non-primary context");
1996e5dd7070Spatrick
1997e5dd7070Spatrick StoredDeclsMap *M;
1998e5dd7070Spatrick bool Dependent = isDependentContext();
1999e5dd7070Spatrick if (Dependent)
2000e5dd7070Spatrick M = new DependentStoredDeclsMap();
2001e5dd7070Spatrick else
2002e5dd7070Spatrick M = new StoredDeclsMap();
2003e5dd7070Spatrick M->Previous = C.LastSDM;
2004e5dd7070Spatrick C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
2005e5dd7070Spatrick LookupPtr = M;
2006e5dd7070Spatrick return M;
2007e5dd7070Spatrick }
2008e5dd7070Spatrick
ReleaseDeclContextMaps()2009e5dd7070Spatrick void ASTContext::ReleaseDeclContextMaps() {
2010e5dd7070Spatrick // It's okay to delete DependentStoredDeclsMaps via a StoredDeclsMap
2011e5dd7070Spatrick // pointer because the subclass doesn't add anything that needs to
2012e5dd7070Spatrick // be deleted.
2013e5dd7070Spatrick StoredDeclsMap::DestroyAll(LastSDM.getPointer(), LastSDM.getInt());
2014*12c85518Srobert LastSDM.setPointer(nullptr);
2015e5dd7070Spatrick }
2016e5dd7070Spatrick
DestroyAll(StoredDeclsMap * Map,bool Dependent)2017e5dd7070Spatrick void StoredDeclsMap::DestroyAll(StoredDeclsMap *Map, bool Dependent) {
2018e5dd7070Spatrick while (Map) {
2019e5dd7070Spatrick // Advance the iteration before we invalidate memory.
2020e5dd7070Spatrick llvm::PointerIntPair<StoredDeclsMap*,1> Next = Map->Previous;
2021e5dd7070Spatrick
2022e5dd7070Spatrick if (Dependent)
2023e5dd7070Spatrick delete static_cast<DependentStoredDeclsMap*>(Map);
2024e5dd7070Spatrick else
2025e5dd7070Spatrick delete Map;
2026e5dd7070Spatrick
2027e5dd7070Spatrick Map = Next.getPointer();
2028e5dd7070Spatrick Dependent = Next.getInt();
2029e5dd7070Spatrick }
2030e5dd7070Spatrick }
2031e5dd7070Spatrick
Create(ASTContext & C,DeclContext * Parent,const PartialDiagnostic & PDiag)2032e5dd7070Spatrick DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
2033e5dd7070Spatrick DeclContext *Parent,
2034e5dd7070Spatrick const PartialDiagnostic &PDiag) {
2035e5dd7070Spatrick assert(Parent->isDependentContext()
2036e5dd7070Spatrick && "cannot iterate dependent diagnostics of non-dependent context");
2037e5dd7070Spatrick Parent = Parent->getPrimaryContext();
2038e5dd7070Spatrick if (!Parent->LookupPtr)
2039e5dd7070Spatrick Parent->CreateStoredDeclsMap(C);
2040e5dd7070Spatrick
2041e5dd7070Spatrick auto *Map = static_cast<DependentStoredDeclsMap *>(Parent->LookupPtr);
2042e5dd7070Spatrick
2043e5dd7070Spatrick // Allocate the copy of the PartialDiagnostic via the ASTContext's
2044e5dd7070Spatrick // BumpPtrAllocator, rather than the ASTContext itself.
2045a9ac8606Spatrick DiagnosticStorage *DiagStorage = nullptr;
2046e5dd7070Spatrick if (PDiag.hasStorage())
2047a9ac8606Spatrick DiagStorage = new (C) DiagnosticStorage;
2048e5dd7070Spatrick
2049e5dd7070Spatrick auto *DD = new (C) DependentDiagnostic(PDiag, DiagStorage);
2050e5dd7070Spatrick
2051e5dd7070Spatrick // TODO: Maybe we shouldn't reverse the order during insertion.
2052e5dd7070Spatrick DD->NextDiagnostic = Map->FirstDiagnostic;
2053e5dd7070Spatrick Map->FirstDiagnostic = DD;
2054e5dd7070Spatrick
2055e5dd7070Spatrick return DD;
2056e5dd7070Spatrick }
2057