DeclBase.cpp revision dd4a3b0065b9a7e7b00073df415a798886c090f3
1//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Decl and DeclContext classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclBase.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclContextInternals.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DeclObjC.h"
19#include "clang/AST/DeclTemplate.h"
20#include "clang/AST/ExternalASTSource.h"
21#include "clang/AST/ASTContext.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/Stmt.h"
24#include "clang/AST/StmtCXX.h"
25#include "llvm/ADT/DenseMap.h"
26#include "llvm/Support/raw_ostream.h"
27#include <algorithm>
28#include <cstdio>
29#include <vector>
30using namespace clang;
31
32//===----------------------------------------------------------------------===//
33//  Statistics
34//===----------------------------------------------------------------------===//
35
36#define DECL(Derived, Base) static int n##Derived##s = 0;
37#include "clang/AST/DeclNodes.def"
38
39static bool StatSwitch = false;
40
41const char *Decl::getDeclKindName() const {
42  switch (DeclKind) {
43  default: assert(0 && "Declaration not in DeclNodes.def!");
44#define DECL(Derived, Base) case Derived: return #Derived;
45#include "clang/AST/DeclNodes.def"
46  }
47}
48
49const char *DeclContext::getDeclKindName() const {
50  switch (DeclKind) {
51  default: assert(0 && "Declaration context not in DeclNodes.def!");
52#define DECL(Derived, Base) case Decl::Derived: return #Derived;
53#include "clang/AST/DeclNodes.def"
54  }
55}
56
57bool Decl::CollectingStats(bool Enable) {
58  if (Enable)
59    StatSwitch = true;
60  return StatSwitch;
61}
62
63void Decl::PrintStats() {
64  fprintf(stderr, "*** Decl Stats:\n");
65
66  int totalDecls = 0;
67#define DECL(Derived, Base) totalDecls += n##Derived##s;
68#include "clang/AST/DeclNodes.def"
69  fprintf(stderr, "  %d decls total.\n", totalDecls);
70
71  int totalBytes = 0;
72#define DECL(Derived, Base)                                             \
73  if (n##Derived##s > 0) {                                              \
74    totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl));         \
75    fprintf(stderr, "    %d " #Derived " decls, %d each (%d bytes)\n",  \
76            n##Derived##s, (int)sizeof(Derived##Decl),                  \
77            (int)(n##Derived##s * sizeof(Derived##Decl)));              \
78  }
79#include "clang/AST/DeclNodes.def"
80
81  fprintf(stderr, "Total bytes = %d\n", totalBytes);
82}
83
84void Decl::addDeclKind(Kind k) {
85  switch (k) {
86  default: assert(0 && "Declaration not in DeclNodes.def!");
87#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
88#include "clang/AST/DeclNodes.def"
89  }
90}
91
92bool Decl::isTemplateParameterPack() const {
93  if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
94    return TTP->isParameterPack();
95
96  return false;
97}
98
99bool Decl::isFunctionOrFunctionTemplate() const {
100  if (const UsingDecl *UD = dyn_cast<UsingDecl>(this))
101    return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
102
103  return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
104}
105
106//===----------------------------------------------------------------------===//
107// PrettyStackTraceDecl Implementation
108//===----------------------------------------------------------------------===//
109
110void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
111  SourceLocation TheLoc = Loc;
112  if (TheLoc.isInvalid() && TheDecl)
113    TheLoc = TheDecl->getLocation();
114
115  if (TheLoc.isValid()) {
116    TheLoc.print(OS, SM);
117    OS << ": ";
118  }
119
120  OS << Message;
121
122  if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
123    OS << " '" << DN->getQualifiedNameAsString() << '\'';
124  OS << '\n';
125}
126
127//===----------------------------------------------------------------------===//
128// Decl Implementation
129//===----------------------------------------------------------------------===//
130
131// Out-of-line virtual method providing a home for Decl.
132Decl::~Decl() {
133  if (isOutOfSemaDC())
134    delete getMultipleDC();
135
136  assert(!HasAttrs && "attributes should have been freed by Destroy");
137}
138
139void Decl::setDeclContext(DeclContext *DC) {
140  if (isOutOfSemaDC())
141    delete getMultipleDC();
142
143  DeclCtx = DC;
144}
145
146void Decl::setLexicalDeclContext(DeclContext *DC) {
147  if (DC == getLexicalDeclContext())
148    return;
149
150  if (isInSemaDC()) {
151    MultipleDC *MDC = new MultipleDC();
152    MDC->SemanticDC = getDeclContext();
153    MDC->LexicalDC = DC;
154    DeclCtx = MDC;
155  } else {
156    getMultipleDC()->LexicalDC = DC;
157  }
158}
159
160TranslationUnitDecl *Decl::getTranslationUnitDecl() {
161  if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
162    return TUD;
163
164  DeclContext *DC = getDeclContext();
165  assert(DC && "This decl is not contained in a translation unit!");
166
167  while (!DC->isTranslationUnit()) {
168    DC = DC->getParent();
169    assert(DC && "This decl is not contained in a translation unit!");
170  }
171
172  return cast<TranslationUnitDecl>(DC);
173}
174
175ASTContext &Decl::getASTContext() const {
176  return getTranslationUnitDecl()->getASTContext();
177}
178
179unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
180  switch (DeclKind) {
181    default:
182      if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
183        return IDNS_Ordinary;
184      assert(0 && "Unknown decl kind!");
185    case OverloadedFunction:
186    case Typedef:
187    case EnumConstant:
188    case Var:
189    case ImplicitParam:
190    case ParmVar:
191    case OriginalParmVar:
192    case NonTypeTemplateParm:
193    case Using:
194    case UnresolvedUsing:
195    case ObjCMethod:
196    case ObjCContainer:
197    case ObjCCategory:
198    case ObjCInterface:
199    case ObjCProperty:
200    case ObjCCompatibleAlias:
201      return IDNS_Ordinary;
202
203    case ObjCProtocol:
204      return IDNS_ObjCProtocol;
205
206    case ObjCImplementation:
207      return IDNS_ObjCImplementation;
208
209    case ObjCCategoryImpl:
210      return IDNS_ObjCCategoryImpl;
211
212    case Field:
213    case ObjCAtDefsField:
214    case ObjCIvar:
215      return IDNS_Member;
216
217    case Record:
218    case CXXRecord:
219    case Enum:
220    case TemplateTypeParm:
221      return IDNS_Tag;
222
223    case Namespace:
224    case Template:
225    case FunctionTemplate:
226    case ClassTemplate:
227    case TemplateTemplateParm:
228    case NamespaceAlias:
229      return IDNS_Tag | IDNS_Ordinary;
230
231    // Never have names.
232    case Friend:
233    case FriendTemplate:
234    case LinkageSpec:
235    case FileScopeAsm:
236    case StaticAssert:
237    case ObjCClass:
238    case ObjCPropertyImpl:
239    case ObjCForwardProtocol:
240    case Block:
241    case TranslationUnit:
242
243    // Aren't looked up?
244    case UsingDirective:
245    case ClassTemplateSpecialization:
246    case ClassTemplatePartialSpecialization:
247      return 0;
248  }
249}
250
251void Decl::addAttr(Attr *NewAttr) {
252  Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
253
254  NewAttr->setNext(ExistingAttr);
255  ExistingAttr = NewAttr;
256
257  HasAttrs = true;
258}
259
260void Decl::invalidateAttrs() {
261  if (!HasAttrs) return;
262
263  HasAttrs = false;
264  getASTContext().eraseDeclAttrs(this);
265}
266
267const Attr *Decl::getAttrsImpl() const {
268  assert(HasAttrs && "getAttrs() should verify this!");
269  return getASTContext().getDeclAttrs(this);
270}
271
272void Decl::swapAttrs(Decl *RHS) {
273  bool HasLHSAttr = this->HasAttrs;
274  bool HasRHSAttr = RHS->HasAttrs;
275
276  // Usually, neither decl has attrs, nothing to do.
277  if (!HasLHSAttr && !HasRHSAttr) return;
278
279  // If 'this' has no attrs, swap the other way.
280  if (!HasLHSAttr)
281    return RHS->swapAttrs(this);
282
283  ASTContext &Context = getASTContext();
284
285  // Handle the case when both decls have attrs.
286  if (HasRHSAttr) {
287    std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
288    return;
289  }
290
291  // Otherwise, LHS has an attr and RHS doesn't.
292  Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
293  Context.eraseDeclAttrs(this);
294  this->HasAttrs = false;
295  RHS->HasAttrs = true;
296}
297
298
299void Decl::Destroy(ASTContext &C) {
300  // Free attributes for this decl.
301  if (HasAttrs) {
302    C.getDeclAttrs(this)->Destroy(C);
303    invalidateAttrs();
304    HasAttrs = false;
305  }
306
307#if 0
308  // FIXME: Once ownership is fully understood, we can enable this code
309  if (DeclContext *DC = dyn_cast<DeclContext>(this))
310    DC->decls_begin()->Destroy(C);
311
312  // Observe the unrolled recursion.  By setting N->NextDeclInContext = 0x0
313  // within the loop, only the Destroy method for the first Decl
314  // will deallocate all of the Decls in a chain.
315
316  Decl* N = getNextDeclInContext();
317
318  while (N) {
319    Decl* Tmp = N->getNextDeclInContext();
320    N->NextDeclInContext = 0;
321    N->Destroy(C);
322    N = Tmp;
323  }
324
325  this->~Decl();
326  C.Deallocate((void *)this);
327#endif
328}
329
330Decl *Decl::castFromDeclContext (const DeclContext *D) {
331  Decl::Kind DK = D->getDeclKind();
332  switch(DK) {
333#define DECL_CONTEXT(Name) \
334    case Decl::Name:     \
335      return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
336#define DECL_CONTEXT_BASE(Name)
337#include "clang/AST/DeclNodes.def"
338    default:
339#define DECL_CONTEXT_BASE(Name)                                   \
340      if (DK >= Decl::Name##First && DK <= Decl::Name##Last)    \
341        return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
342#include "clang/AST/DeclNodes.def"
343      assert(false && "a decl that inherits DeclContext isn't handled");
344      return 0;
345  }
346}
347
348DeclContext *Decl::castToDeclContext(const Decl *D) {
349  Decl::Kind DK = D->getKind();
350  switch(DK) {
351#define DECL_CONTEXT(Name) \
352    case Decl::Name:     \
353      return static_cast<Name##Decl*>(const_cast<Decl*>(D));
354#define DECL_CONTEXT_BASE(Name)
355#include "clang/AST/DeclNodes.def"
356    default:
357#define DECL_CONTEXT_BASE(Name)                                   \
358      if (DK >= Decl::Name##First && DK <= Decl::Name##Last)    \
359        return static_cast<Name##Decl*>(const_cast<Decl*>(D));
360#include "clang/AST/DeclNodes.def"
361      assert(false && "a decl that inherits DeclContext isn't handled");
362      return 0;
363  }
364}
365
366CompoundStmt* Decl::getCompoundBody() const {
367  return dyn_cast_or_null<CompoundStmt>(getBody());
368}
369
370SourceLocation Decl::getBodyRBrace() const {
371  Stmt *Body = getBody();
372  if (!Body)
373    return SourceLocation();
374  if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
375    return CS->getRBracLoc();
376  assert(isa<CXXTryStmt>(Body) &&
377         "Body can only be CompoundStmt or CXXTryStmt");
378  return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
379}
380
381#ifndef NDEBUG
382void Decl::CheckAccessDeclContext() const {
383  // If the decl is the toplevel translation unit or if we're not in a
384  // record decl context, we don't need to check anything.
385  if (isa<TranslationUnitDecl>(this) ||
386      !isa<CXXRecordDecl>(getDeclContext()))
387    return;
388
389  assert(Access != AS_none &&
390         "Access specifier is AS_none inside a record decl");
391}
392
393#endif
394
395//===----------------------------------------------------------------------===//
396// DeclContext Implementation
397//===----------------------------------------------------------------------===//
398
399bool DeclContext::classof(const Decl *D) {
400  switch (D->getKind()) {
401#define DECL_CONTEXT(Name) case Decl::Name:
402#define DECL_CONTEXT_BASE(Name)
403#include "clang/AST/DeclNodes.def"
404      return true;
405    default:
406#define DECL_CONTEXT_BASE(Name)                   \
407      if (D->getKind() >= Decl::Name##First &&  \
408          D->getKind() <= Decl::Name##Last)     \
409        return true;
410#include "clang/AST/DeclNodes.def"
411      return false;
412  }
413}
414
415DeclContext::~DeclContext() {
416  delete static_cast<StoredDeclsMap*>(LookupPtr);
417}
418
419void DeclContext::DestroyDecls(ASTContext &C) {
420  for (decl_iterator D = decls_begin(); D != decls_end(); )
421    (*D++)->Destroy(C);
422}
423
424/// \brief Find the parent context of this context that will be
425/// used for unqualified name lookup.
426///
427/// Generally, the parent lookup context is the semantic context. However, for
428/// a friend function the parent lookup context is the lexical context, which
429/// is the class in which the friend is declared.
430DeclContext *DeclContext::getLookupParent() {
431  // FIXME: Find a better way to identify friends
432  if (isa<FunctionDecl>(this))
433    if (getParent()->getLookupContext()->isFileContext() &&
434        getLexicalParent()->getLookupContext()->isRecord())
435      return getLexicalParent();
436
437  return getParent();
438}
439
440bool DeclContext::isDependentContext() const {
441  if (isFileContext())
442    return false;
443
444  if (isa<ClassTemplatePartialSpecializationDecl>(this))
445    return true;
446
447  if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
448    if (Record->getDescribedClassTemplate())
449      return true;
450
451  if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this))
452    if (Function->getDescribedFunctionTemplate())
453      return true;
454
455  return getParent() && getParent()->isDependentContext();
456}
457
458bool DeclContext::isTransparentContext() const {
459  if (DeclKind == Decl::Enum)
460    return true; // FIXME: Check for C++0x scoped enums
461  else if (DeclKind == Decl::LinkageSpec)
462    return true;
463  else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast)
464    return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
465  else if (DeclKind == Decl::Namespace)
466    return false; // FIXME: Check for C++0x inline namespaces
467
468  return false;
469}
470
471bool DeclContext::Encloses(DeclContext *DC) {
472  if (getPrimaryContext() != this)
473    return getPrimaryContext()->Encloses(DC);
474
475  for (; DC; DC = DC->getParent())
476    if (DC->getPrimaryContext() == this)
477      return true;
478  return false;
479}
480
481DeclContext *DeclContext::getPrimaryContext() {
482  switch (DeclKind) {
483  case Decl::TranslationUnit:
484  case Decl::LinkageSpec:
485  case Decl::Block:
486    // There is only one DeclContext for these entities.
487    return this;
488
489  case Decl::Namespace:
490    // The original namespace is our primary context.
491    return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
492
493  case Decl::ObjCMethod:
494    return this;
495
496  case Decl::ObjCInterface:
497  case Decl::ObjCProtocol:
498  case Decl::ObjCCategory:
499    // FIXME: Can Objective-C interfaces be forward-declared?
500    return this;
501
502  case Decl::ObjCImplementation:
503  case Decl::ObjCCategoryImpl:
504    return this;
505
506  default:
507    if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
508      // If this is a tag type that has a definition or is currently
509      // being defined, that definition is our primary context.
510      if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAs<TagType>())
511        if (TagT->isBeingDefined() ||
512            (TagT->getDecl() && TagT->getDecl()->isDefinition()))
513          return TagT->getDecl();
514      return this;
515    }
516
517    assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
518          "Unknown DeclContext kind");
519    return this;
520  }
521}
522
523DeclContext *DeclContext::getNextContext() {
524  switch (DeclKind) {
525  case Decl::Namespace:
526    // Return the next namespace
527    return static_cast<NamespaceDecl*>(this)->getNextNamespace();
528
529  default:
530    return 0;
531  }
532}
533
534/// \brief Load the declarations within this lexical storage from an
535/// external source.
536void
537DeclContext::LoadLexicalDeclsFromExternalStorage() const {
538  ExternalASTSource *Source = getParentASTContext().getExternalSource();
539  assert(hasExternalLexicalStorage() && Source && "No external storage?");
540
541  llvm::SmallVector<uint32_t, 64> Decls;
542  if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
543                                          Decls))
544    return;
545
546  // There is no longer any lexical storage in this context
547  ExternalLexicalStorage = false;
548
549  if (Decls.empty())
550    return;
551
552  // Resolve all of the declaration IDs into declarations, building up
553  // a chain of declarations via the Decl::NextDeclInContext field.
554  Decl *FirstNewDecl = 0;
555  Decl *PrevDecl = 0;
556  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
557    Decl *D = Source->GetDecl(Decls[I]);
558    if (PrevDecl)
559      PrevDecl->NextDeclInContext = D;
560    else
561      FirstNewDecl = D;
562
563    PrevDecl = D;
564  }
565
566  // Splice the newly-read declarations into the beginning of the list
567  // of declarations.
568  PrevDecl->NextDeclInContext = FirstDecl;
569  FirstDecl = FirstNewDecl;
570  if (!LastDecl)
571    LastDecl = PrevDecl;
572}
573
574void
575DeclContext::LoadVisibleDeclsFromExternalStorage() const {
576  DeclContext *This = const_cast<DeclContext *>(this);
577  ExternalASTSource *Source = getParentASTContext().getExternalSource();
578  assert(hasExternalVisibleStorage() && Source && "No external storage?");
579
580  llvm::SmallVector<VisibleDeclaration, 64> Decls;
581  if (Source->ReadDeclsVisibleInContext(This, Decls))
582    return;
583
584  // There is no longer any visible storage in this context
585  ExternalVisibleStorage = false;
586
587  // Load the declaration IDs for all of the names visible in this
588  // context.
589  assert(!LookupPtr && "Have a lookup map before de-serialization?");
590  StoredDeclsMap *Map = new StoredDeclsMap;
591  LookupPtr = Map;
592  for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
593    (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
594  }
595}
596
597DeclContext::decl_iterator DeclContext::decls_begin() const {
598  if (hasExternalLexicalStorage())
599    LoadLexicalDeclsFromExternalStorage();
600
601  // FIXME: Check whether we need to load some declarations from
602  // external storage.
603  return decl_iterator(FirstDecl);
604}
605
606DeclContext::decl_iterator DeclContext::decls_end() const {
607  if (hasExternalLexicalStorage())
608    LoadLexicalDeclsFromExternalStorage();
609
610  return decl_iterator();
611}
612
613bool DeclContext::decls_empty() const {
614  if (hasExternalLexicalStorage())
615    LoadLexicalDeclsFromExternalStorage();
616
617  return !FirstDecl;
618}
619
620void DeclContext::addHiddenDecl(Decl *D) {
621  assert(D->getLexicalDeclContext() == this &&
622         "Decl inserted into wrong lexical context");
623  assert(!D->getNextDeclInContext() && D != LastDecl &&
624         "Decl already inserted into a DeclContext");
625
626  if (FirstDecl) {
627    LastDecl->NextDeclInContext = D;
628    LastDecl = D;
629  } else {
630    FirstDecl = LastDecl = D;
631  }
632}
633
634void DeclContext::addDecl(Decl *D) {
635  addHiddenDecl(D);
636
637  if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
638    ND->getDeclContext()->makeDeclVisibleInContext(ND);
639}
640
641/// buildLookup - Build the lookup data structure with all of the
642/// declarations in DCtx (and any other contexts linked to it or
643/// transparent contexts nested within it).
644void DeclContext::buildLookup(DeclContext *DCtx) {
645  for (; DCtx; DCtx = DCtx->getNextContext()) {
646    for (decl_iterator D = DCtx->decls_begin(),
647                    DEnd = DCtx->decls_end();
648         D != DEnd; ++D) {
649      // Insert this declaration into the lookup structure, but only
650      // if it's semantically in its decl context.  During non-lazy
651      // lookup building, this is implicitly enforced by addDecl.
652      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
653        if (D->getDeclContext() == DCtx)
654          makeDeclVisibleInContextImpl(ND);
655
656      // If this declaration is itself a transparent declaration context,
657      // add its members (recursively).
658      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
659        if (InnerCtx->isTransparentContext())
660          buildLookup(InnerCtx->getPrimaryContext());
661    }
662  }
663}
664
665DeclContext::lookup_result
666DeclContext::lookup(DeclarationName Name) {
667  DeclContext *PrimaryContext = getPrimaryContext();
668  if (PrimaryContext != this)
669    return PrimaryContext->lookup(Name);
670
671  if (hasExternalVisibleStorage())
672    LoadVisibleDeclsFromExternalStorage();
673
674  /// If there is no lookup data structure, build one now by walking
675  /// all of the linked DeclContexts (in declaration order!) and
676  /// inserting their values.
677  if (!LookupPtr) {
678    buildLookup(this);
679
680    if (!LookupPtr)
681      return lookup_result(0, 0);
682  }
683
684  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr);
685  StoredDeclsMap::iterator Pos = Map->find(Name);
686  if (Pos == Map->end())
687    return lookup_result(0, 0);
688  return Pos->second.getLookupResult(getParentASTContext());
689}
690
691DeclContext::lookup_const_result
692DeclContext::lookup(DeclarationName Name) const {
693  return const_cast<DeclContext*>(this)->lookup(Name);
694}
695
696DeclContext *DeclContext::getLookupContext() {
697  DeclContext *Ctx = this;
698  // Skip through transparent contexts.
699  while (Ctx->isTransparentContext())
700    Ctx = Ctx->getParent();
701  return Ctx;
702}
703
704DeclContext *DeclContext::getEnclosingNamespaceContext() {
705  DeclContext *Ctx = this;
706  // Skip through non-namespace, non-translation-unit contexts.
707  while (!Ctx->isFileContext() || Ctx->isTransparentContext())
708    Ctx = Ctx->getParent();
709  return Ctx->getPrimaryContext();
710}
711
712void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
713  // FIXME: This feels like a hack. Should DeclarationName support
714  // template-ids, or is there a better way to keep specializations
715  // from being visible?
716  if (isa<ClassTemplateSpecializationDecl>(D))
717    return;
718
719  DeclContext *PrimaryContext = getPrimaryContext();
720  if (PrimaryContext != this) {
721    PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
722    return;
723  }
724
725  // If we already have a lookup data structure, perform the insertion
726  // into it. Otherwise, be lazy and don't build that structure until
727  // someone asks for it.
728  if (LookupPtr || !Recoverable)
729    makeDeclVisibleInContextImpl(D);
730
731  // If we are a transparent context, insert into our parent context,
732  // too. This operation is recursive.
733  if (isTransparentContext())
734    getParent()->makeDeclVisibleInContext(D, Recoverable);
735}
736
737void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
738  // Skip unnamed declarations.
739  if (!D->getDeclName())
740    return;
741
742  // FIXME: This feels like a hack. Should DeclarationName support
743  // template-ids, or is there a better way to keep specializations
744  // from being visible?
745  if (isa<ClassTemplateSpecializationDecl>(D))
746    return;
747
748  if (!LookupPtr)
749    LookupPtr = new StoredDeclsMap;
750
751  // Insert this declaration into the map.
752  StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr);
753  StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
754  if (DeclNameEntries.isNull()) {
755    DeclNameEntries.setOnlyValue(D);
756    return;
757  }
758
759  // If it is possible that this is a redeclaration, check to see if there is
760  // already a decl for which declarationReplaces returns true.  If there is
761  // one, just replace it and return.
762  if (DeclNameEntries.HandleRedeclaration(getParentASTContext(), D))
763    return;
764
765  // Put this declaration into the appropriate slot.
766  DeclNameEntries.AddSubsequentDecl(D);
767}
768
769/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
770/// this context.
771DeclContext::udir_iterator_range
772DeclContext::getUsingDirectives() const {
773  lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
774  return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
775                             reinterpret_cast<udir_iterator>(Result.second));
776}
777
778void StoredDeclsList::materializeDecls(ASTContext &Context) {
779  if (isNull())
780    return;
781
782  switch ((DataKind)(Data & 0x03)) {
783  case DK_Decl:
784  case DK_Decl_Vector:
785    break;
786
787  case DK_DeclID: {
788    // Resolve this declaration ID to an actual declaration by
789    // querying the external AST source.
790    unsigned DeclID = Data >> 2;
791
792    ExternalASTSource *Source = Context.getExternalSource();
793    assert(Source && "No external AST source available!");
794
795    Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
796    break;
797  }
798
799  case DK_ID_Vector: {
800    // We have a vector of declaration IDs. Resolve all of them to
801    // actual declarations.
802    VectorTy &Vector = *getAsVector();
803    ExternalASTSource *Source = Context.getExternalSource();
804    assert(Source && "No external AST source available!");
805
806    for (unsigned I = 0, N = Vector.size(); I != N; ++I)
807      Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));
808
809    Data = (Data & ~0x03) | DK_Decl_Vector;
810    break;
811  }
812  }
813}
814