DeclBase.cpp revision 40b598eea1310ec9ed554d56ce3e25b34c585458
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 DeclContext *DC = getDeclContext(); 162 assert(DC && "This decl is not contained in a translation unit!"); 163 164 while (!DC->isTranslationUnit()) { 165 DC = DC->getParent(); 166 assert(DC && "This decl is not contained in a translation unit!"); 167 } 168 169 return cast<TranslationUnitDecl>(DC); 170} 171 172ASTContext &Decl::getASTContext() const { 173 return getTranslationUnitDecl()->getASTContext(); 174} 175 176unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { 177 switch (DeclKind) { 178 default: 179 if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast) 180 return IDNS_Ordinary; 181 assert(0 && "Unknown decl kind!"); 182 case OverloadedFunction: 183 case Typedef: 184 case EnumConstant: 185 case Var: 186 case ImplicitParam: 187 case ParmVar: 188 case OriginalParmVar: 189 case NonTypeTemplateParm: 190 case Using: 191 case ObjCMethod: 192 case ObjCContainer: 193 case ObjCCategory: 194 case ObjCInterface: 195 case ObjCProperty: 196 case ObjCCompatibleAlias: 197 return IDNS_Ordinary; 198 199 case ObjCProtocol: 200 return IDNS_ObjCProtocol; 201 202 case ObjCImplementation: 203 return IDNS_ObjCImplementation; 204 205 case ObjCCategoryImpl: 206 return IDNS_ObjCCategoryImpl; 207 208 case Field: 209 case ObjCAtDefsField: 210 case ObjCIvar: 211 return IDNS_Member; 212 213 case Record: 214 case CXXRecord: 215 case Enum: 216 case TemplateTypeParm: 217 return IDNS_Tag; 218 219 case Namespace: 220 case Template: 221 case FunctionTemplate: 222 case ClassTemplate: 223 case TemplateTemplateParm: 224 case NamespaceAlias: 225 return IDNS_Tag | IDNS_Ordinary; 226 227 // Never have names. 228 case LinkageSpec: 229 case FileScopeAsm: 230 case StaticAssert: 231 case ObjCClass: 232 case ObjCPropertyImpl: 233 case ObjCForwardProtocol: 234 case Block: 235 case TranslationUnit: 236 237 // Aren't looked up? 238 case UsingDirective: 239 case ClassTemplateSpecialization: 240 case ClassTemplatePartialSpecialization: 241 return 0; 242 } 243} 244 245void Decl::addAttr(Attr *NewAttr) { 246 Attr *&ExistingAttr = getASTContext().getDeclAttrs(this); 247 248 NewAttr->setNext(ExistingAttr); 249 ExistingAttr = NewAttr; 250 251 HasAttrs = true; 252} 253 254void Decl::invalidateAttrs() { 255 if (!HasAttrs) return; 256 257 HasAttrs = false; 258 getASTContext().eraseDeclAttrs(this); 259} 260 261const Attr *Decl::getAttrsImpl() const { 262 assert(HasAttrs && "getAttrs() should verify this!"); 263 return getASTContext().getDeclAttrs(this); 264} 265 266void Decl::swapAttrs(Decl *RHS) { 267 bool HasLHSAttr = this->HasAttrs; 268 bool HasRHSAttr = RHS->HasAttrs; 269 270 // Usually, neither decl has attrs, nothing to do. 271 if (!HasLHSAttr && !HasRHSAttr) return; 272 273 // If 'this' has no attrs, swap the other way. 274 if (!HasLHSAttr) 275 return RHS->swapAttrs(this); 276 277 ASTContext &Context = getASTContext(); 278 279 // Handle the case when both decls have attrs. 280 if (HasRHSAttr) { 281 std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS)); 282 return; 283 } 284 285 // Otherwise, LHS has an attr and RHS doesn't. 286 Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this); 287 Context.eraseDeclAttrs(this); 288 this->HasAttrs = false; 289 RHS->HasAttrs = true; 290} 291 292 293void Decl::Destroy(ASTContext &C) { 294 // Free attributes for this decl. 295 if (HasAttrs) { 296 C.getDeclAttrs(this)->Destroy(C); 297 invalidateAttrs(); 298 HasAttrs = false; 299 } 300 301#if 0 302 // FIXME: Once ownership is fully understood, we can enable this code 303 if (DeclContext *DC = dyn_cast<DeclContext>(this)) 304 DC->decls_begin()->Destroy(C); 305 306 // Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0 307 // within the loop, only the Destroy method for the first Decl 308 // will deallocate all of the Decls in a chain. 309 310 Decl* N = getNextDeclInContext(); 311 312 while (N) { 313 Decl* Tmp = N->getNextDeclInContext(); 314 N->NextDeclInContext = 0; 315 N->Destroy(C); 316 N = Tmp; 317 } 318 319 this->~Decl(); 320 C.Deallocate((void *)this); 321#endif 322} 323 324Decl *Decl::castFromDeclContext (const DeclContext *D) { 325 Decl::Kind DK = D->getDeclKind(); 326 switch(DK) { 327#define DECL_CONTEXT(Name) \ 328 case Decl::Name: \ 329 return static_cast<Name##Decl*>(const_cast<DeclContext*>(D)); 330#define DECL_CONTEXT_BASE(Name) 331#include "clang/AST/DeclNodes.def" 332 default: 333#define DECL_CONTEXT_BASE(Name) \ 334 if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \ 335 return static_cast<Name##Decl*>(const_cast<DeclContext*>(D)); 336#include "clang/AST/DeclNodes.def" 337 assert(false && "a decl that inherits DeclContext isn't handled"); 338 return 0; 339 } 340} 341 342DeclContext *Decl::castToDeclContext(const Decl *D) { 343 Decl::Kind DK = D->getKind(); 344 switch(DK) { 345#define DECL_CONTEXT(Name) \ 346 case Decl::Name: \ 347 return static_cast<Name##Decl*>(const_cast<Decl*>(D)); 348#define DECL_CONTEXT_BASE(Name) 349#include "clang/AST/DeclNodes.def" 350 default: 351#define DECL_CONTEXT_BASE(Name) \ 352 if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \ 353 return static_cast<Name##Decl*>(const_cast<Decl*>(D)); 354#include "clang/AST/DeclNodes.def" 355 assert(false && "a decl that inherits DeclContext isn't handled"); 356 return 0; 357 } 358} 359 360CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const { 361 return dyn_cast_or_null<CompoundStmt>(getBody(Context)); 362} 363 364SourceLocation Decl::getBodyRBrace(ASTContext &Context) const { 365 Stmt *Body = getBody(Context); 366 if (!Body) 367 return SourceLocation(); 368 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body)) 369 return CS->getRBracLoc(); 370 assert(isa<CXXTryStmt>(Body) && 371 "Body can only be CompoundStmt or CXXTryStmt"); 372 return cast<CXXTryStmt>(Body)->getSourceRange().getEnd(); 373} 374 375#ifndef NDEBUG 376void Decl::CheckAccessDeclContext() const { 377 assert((Access != AS_none || isa<TranslationUnitDecl>(this) || 378 !isa<CXXRecordDecl>(getDeclContext())) && 379 "Access specifier is AS_none inside a record decl"); 380} 381 382#endif 383 384//===----------------------------------------------------------------------===// 385// DeclContext Implementation 386//===----------------------------------------------------------------------===// 387 388bool DeclContext::classof(const Decl *D) { 389 switch (D->getKind()) { 390#define DECL_CONTEXT(Name) case Decl::Name: 391#define DECL_CONTEXT_BASE(Name) 392#include "clang/AST/DeclNodes.def" 393 return true; 394 default: 395#define DECL_CONTEXT_BASE(Name) \ 396 if (D->getKind() >= Decl::Name##First && \ 397 D->getKind() <= Decl::Name##Last) \ 398 return true; 399#include "clang/AST/DeclNodes.def" 400 return false; 401 } 402} 403 404DeclContext::~DeclContext() { 405 delete static_cast<StoredDeclsMap*>(LookupPtr); 406} 407 408void DeclContext::DestroyDecls(ASTContext &C) { 409 for (decl_iterator D = decls_begin(C); D != decls_end(C); ) 410 (*D++)->Destroy(C); 411} 412 413bool DeclContext::isDependentContext() const { 414 if (isFileContext()) 415 return false; 416 417 if (isa<ClassTemplatePartialSpecializationDecl>(this)) 418 return true; 419 420 if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) 421 if (Record->getDescribedClassTemplate()) 422 return true; 423 424 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) 425 if (Function->getDescribedFunctionTemplate()) 426 return true; 427 428 return getParent() && getParent()->isDependentContext(); 429} 430 431bool DeclContext::isTransparentContext() const { 432 if (DeclKind == Decl::Enum) 433 return true; // FIXME: Check for C++0x scoped enums 434 else if (DeclKind == Decl::LinkageSpec) 435 return true; 436 else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast) 437 return cast<RecordDecl>(this)->isAnonymousStructOrUnion(); 438 else if (DeclKind == Decl::Namespace) 439 return false; // FIXME: Check for C++0x inline namespaces 440 441 return false; 442} 443 444DeclContext *DeclContext::getPrimaryContext() { 445 switch (DeclKind) { 446 case Decl::TranslationUnit: 447 case Decl::LinkageSpec: 448 case Decl::Block: 449 // There is only one DeclContext for these entities. 450 return this; 451 452 case Decl::Namespace: 453 // The original namespace is our primary context. 454 return static_cast<NamespaceDecl*>(this)->getOriginalNamespace(); 455 456 case Decl::ObjCMethod: 457 return this; 458 459 case Decl::ObjCInterface: 460 case Decl::ObjCProtocol: 461 case Decl::ObjCCategory: 462 // FIXME: Can Objective-C interfaces be forward-declared? 463 return this; 464 465 case Decl::ObjCImplementation: 466 case Decl::ObjCCategoryImpl: 467 return this; 468 469 default: 470 if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) { 471 // If this is a tag type that has a definition or is currently 472 // being defined, that definition is our primary context. 473 if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAsTagType()) 474 if (TagT->isBeingDefined() || 475 (TagT->getDecl() && TagT->getDecl()->isDefinition())) 476 return TagT->getDecl(); 477 return this; 478 } 479 480 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast && 481 "Unknown DeclContext kind"); 482 return this; 483 } 484} 485 486DeclContext *DeclContext::getNextContext() { 487 switch (DeclKind) { 488 case Decl::Namespace: 489 // Return the next namespace 490 return static_cast<NamespaceDecl*>(this)->getNextNamespace(); 491 492 default: 493 return 0; 494 } 495} 496 497/// \brief Load the declarations within this lexical storage from an 498/// external source. 499void 500DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const { 501 ExternalASTSource *Source = Context.getExternalSource(); 502 assert(hasExternalLexicalStorage() && Source && "No external storage?"); 503 504 llvm::SmallVector<uint32_t, 64> Decls; 505 if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this), 506 Decls)) 507 return; 508 509 // There is no longer any lexical storage in this context 510 ExternalLexicalStorage = false; 511 512 if (Decls.empty()) 513 return; 514 515 // Resolve all of the declaration IDs into declarations, building up 516 // a chain of declarations via the Decl::NextDeclInContext field. 517 Decl *FirstNewDecl = 0; 518 Decl *PrevDecl = 0; 519 for (unsigned I = 0, N = Decls.size(); I != N; ++I) { 520 Decl *D = Source->GetDecl(Decls[I]); 521 if (PrevDecl) 522 PrevDecl->NextDeclInContext = D; 523 else 524 FirstNewDecl = D; 525 526 PrevDecl = D; 527 } 528 529 // Splice the newly-read declarations into the beginning of the list 530 // of declarations. 531 PrevDecl->NextDeclInContext = FirstDecl; 532 FirstDecl = FirstNewDecl; 533 if (!LastDecl) 534 LastDecl = PrevDecl; 535} 536 537void 538DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const { 539 DeclContext *This = const_cast<DeclContext *>(this); 540 ExternalASTSource *Source = Context.getExternalSource(); 541 assert(hasExternalVisibleStorage() && Source && "No external storage?"); 542 543 llvm::SmallVector<VisibleDeclaration, 64> Decls; 544 if (Source->ReadDeclsVisibleInContext(This, Decls)) 545 return; 546 547 // There is no longer any visible storage in this context 548 ExternalVisibleStorage = false; 549 550 // Load the declaration IDs for all of the names visible in this 551 // context. 552 assert(!LookupPtr && "Have a lookup map before de-serialization?"); 553 StoredDeclsMap *Map = new StoredDeclsMap; 554 LookupPtr = Map; 555 for (unsigned I = 0, N = Decls.size(); I != N; ++I) { 556 (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations); 557 } 558} 559 560DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const { 561 if (hasExternalLexicalStorage()) 562 LoadLexicalDeclsFromExternalStorage(Context); 563 564 // FIXME: Check whether we need to load some declarations from 565 // external storage. 566 return decl_iterator(FirstDecl); 567} 568 569DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const { 570 if (hasExternalLexicalStorage()) 571 LoadLexicalDeclsFromExternalStorage(Context); 572 573 return decl_iterator(); 574} 575 576bool DeclContext::decls_empty(ASTContext &Context) const { 577 if (hasExternalLexicalStorage()) 578 LoadLexicalDeclsFromExternalStorage(Context); 579 580 return !FirstDecl; 581} 582 583void DeclContext::addDecl(ASTContext &Context, Decl *D) { 584 assert(D->getLexicalDeclContext() == this && 585 "Decl inserted into wrong lexical context"); 586 assert(!D->getNextDeclInContext() && D != LastDecl && 587 "Decl already inserted into a DeclContext"); 588 589 if (FirstDecl) { 590 LastDecl->NextDeclInContext = D; 591 LastDecl = D; 592 } else { 593 FirstDecl = LastDecl = D; 594 } 595 596 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) 597 ND->getDeclContext()->makeDeclVisibleInContext(Context, ND); 598} 599 600/// buildLookup - Build the lookup data structure with all of the 601/// declarations in DCtx (and any other contexts linked to it or 602/// transparent contexts nested within it). 603void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) { 604 for (; DCtx; DCtx = DCtx->getNextContext()) { 605 for (decl_iterator D = DCtx->decls_begin(Context), 606 DEnd = DCtx->decls_end(Context); 607 D != DEnd; ++D) { 608 // Insert this declaration into the lookup structure 609 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) 610 makeDeclVisibleInContextImpl(Context, ND); 611 612 // If this declaration is itself a transparent declaration context, 613 // add its members (recursively). 614 if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) 615 if (InnerCtx->isTransparentContext()) 616 buildLookup(Context, InnerCtx->getPrimaryContext()); 617 } 618 } 619} 620 621DeclContext::lookup_result 622DeclContext::lookup(ASTContext &Context, DeclarationName Name) { 623 DeclContext *PrimaryContext = getPrimaryContext(); 624 if (PrimaryContext != this) 625 return PrimaryContext->lookup(Context, Name); 626 627 if (hasExternalVisibleStorage()) 628 LoadVisibleDeclsFromExternalStorage(Context); 629 630 /// If there is no lookup data structure, build one now by walking 631 /// all of the linked DeclContexts (in declaration order!) and 632 /// inserting their values. 633 if (!LookupPtr) { 634 buildLookup(Context, this); 635 636 if (!LookupPtr) 637 return lookup_result(0, 0); 638 } 639 640 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr); 641 StoredDeclsMap::iterator Pos = Map->find(Name); 642 if (Pos == Map->end()) 643 return lookup_result(0, 0); 644 return Pos->second.getLookupResult(Context); 645} 646 647DeclContext::lookup_const_result 648DeclContext::lookup(ASTContext &Context, DeclarationName Name) const { 649 return const_cast<DeclContext*>(this)->lookup(Context, Name); 650} 651 652DeclContext *DeclContext::getLookupContext() { 653 DeclContext *Ctx = this; 654 // Skip through transparent contexts. 655 while (Ctx->isTransparentContext()) 656 Ctx = Ctx->getParent(); 657 return Ctx; 658} 659 660DeclContext *DeclContext::getEnclosingNamespaceContext() { 661 DeclContext *Ctx = this; 662 // Skip through non-namespace, non-translation-unit contexts. 663 while (!Ctx->isFileContext() || Ctx->isTransparentContext()) 664 Ctx = Ctx->getParent(); 665 return Ctx->getPrimaryContext(); 666} 667 668void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) { 669 // FIXME: This feels like a hack. Should DeclarationName support 670 // template-ids, or is there a better way to keep specializations 671 // from being visible? 672 if (isa<ClassTemplateSpecializationDecl>(D)) 673 return; 674 675 DeclContext *PrimaryContext = getPrimaryContext(); 676 if (PrimaryContext != this) { 677 PrimaryContext->makeDeclVisibleInContext(Context, D); 678 return; 679 } 680 681 // If we already have a lookup data structure, perform the insertion 682 // into it. Otherwise, be lazy and don't build that structure until 683 // someone asks for it. 684 if (LookupPtr) 685 makeDeclVisibleInContextImpl(Context, D); 686 687 // If we are a transparent context, insert into our parent context, 688 // too. This operation is recursive. 689 if (isTransparentContext()) 690 getParent()->makeDeclVisibleInContext(Context, D); 691} 692 693void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context, 694 NamedDecl *D) { 695 // Skip unnamed declarations. 696 if (!D->getDeclName()) 697 return; 698 699 // FIXME: This feels like a hack. Should DeclarationName support 700 // template-ids, or is there a better way to keep specializations 701 // from being visible? 702 if (isa<ClassTemplateSpecializationDecl>(D)) 703 return; 704 705 if (!LookupPtr) 706 LookupPtr = new StoredDeclsMap; 707 708 // Insert this declaration into the map. 709 StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr); 710 StoredDeclsList &DeclNameEntries = Map[D->getDeclName()]; 711 if (DeclNameEntries.isNull()) { 712 DeclNameEntries.setOnlyValue(D); 713 return; 714 } 715 716 // If it is possible that this is a redeclaration, check to see if there is 717 // already a decl for which declarationReplaces returns true. If there is 718 // one, just replace it and return. 719 if (DeclNameEntries.HandleRedeclaration(Context, D)) 720 return; 721 722 // Put this declaration into the appropriate slot. 723 DeclNameEntries.AddSubsequentDecl(D); 724} 725 726/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within 727/// this context. 728DeclContext::udir_iterator_range 729DeclContext::getUsingDirectives(ASTContext &Context) const { 730 lookup_const_result Result = lookup(Context, UsingDirectiveDecl::getName()); 731 return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first), 732 reinterpret_cast<udir_iterator>(Result.second)); 733} 734 735void StoredDeclsList::materializeDecls(ASTContext &Context) { 736 if (isNull()) 737 return; 738 739 switch ((DataKind)(Data & 0x03)) { 740 case DK_Decl: 741 case DK_Decl_Vector: 742 break; 743 744 case DK_DeclID: { 745 // Resolve this declaration ID to an actual declaration by 746 // querying the external AST source. 747 unsigned DeclID = Data >> 2; 748 749 ExternalASTSource *Source = Context.getExternalSource(); 750 assert(Source && "No external AST source available!"); 751 752 Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID)); 753 break; 754 } 755 756 case DK_ID_Vector: { 757 // We have a vector of declaration IDs. Resolve all of them to 758 // actual declarations. 759 VectorTy &Vector = *getAsVector(); 760 ExternalASTSource *Source = Context.getExternalSource(); 761 assert(Source && "No external AST source available!"); 762 763 for (unsigned I = 0, N = Vector.size(); I != N; ++I) 764 Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I])); 765 766 Data = (Data & ~0x03) | DK_Decl_Vector; 767 break; 768 } 769 } 770} 771