2008-06-08 00:52:53 +08:00
|
|
|
//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Decl and DeclContext classes.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclBase.h"
|
2009-02-03 07:39:07 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
2009-04-08 01:20:56 +08:00
|
|
|
#include "clang/AST/DeclContextInternals.h"
|
2008-06-10 05:05:31 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2009-02-05 03:02:06 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-04-10 06:27:44 +08:00
|
|
|
#include "clang/AST/ExternalASTSource.h"
|
2008-06-08 00:52:53 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-12-12 00:49:14 +08:00
|
|
|
#include "clang/AST/Type.h"
|
2008-06-08 00:52:53 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2009-03-05 16:00:35 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-12-24 05:05:05 +08:00
|
|
|
#include <algorithm>
|
2009-03-03 06:20:04 +08:00
|
|
|
#include <cstdio>
|
2008-12-23 08:26:44 +08:00
|
|
|
#include <vector>
|
2008-06-08 00:52:53 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Statistics
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-03 07:39:07 +08:00
|
|
|
#define DECL(Derived, Base) static int n##Derived##s = 0;
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
2008-06-08 00:52:53 +08:00
|
|
|
|
|
|
|
static bool StatSwitch = false;
|
|
|
|
|
|
|
|
// This keeps track of all decl attributes. Since so few decls have attrs, we
|
|
|
|
// keep them in a hash map instead of wasting space in the Decl class.
|
|
|
|
typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
|
|
|
|
|
|
|
|
static DeclAttrMapTy *DeclAttrs = 0;
|
|
|
|
|
|
|
|
const char *Decl::getDeclKindName() const {
|
|
|
|
switch (DeclKind) {
|
2009-02-03 07:39:07 +08:00
|
|
|
default: assert(0 && "Declaration not in DeclNodes.def!");
|
|
|
|
#define DECL(Derived, Base) case Derived: return #Derived;
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-21 03:53:53 +08:00
|
|
|
const char *DeclContext::getDeclKindName() const {
|
|
|
|
switch (DeclKind) {
|
2009-02-03 07:39:07 +08:00
|
|
|
default: assert(0 && "Declaration context not in DeclNodes.def!");
|
2009-02-16 22:28:33 +08:00
|
|
|
#define DECL(Derived, Base) case Decl::Derived: return #Derived;
|
2009-02-03 07:39:07 +08:00
|
|
|
#include "clang/AST/DeclNodes.def"
|
2009-01-21 03:53:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
bool Decl::CollectingStats(bool Enable) {
|
|
|
|
if (Enable)
|
|
|
|
StatSwitch = true;
|
|
|
|
return StatSwitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::PrintStats() {
|
|
|
|
fprintf(stderr, "*** Decl Stats:\n");
|
|
|
|
|
2009-02-03 07:39:07 +08:00
|
|
|
int totalDecls = 0;
|
|
|
|
#define DECL(Derived, Base) totalDecls += n##Derived##s;
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
fprintf(stderr, " %d decls total.\n", totalDecls);
|
|
|
|
|
|
|
|
int totalBytes = 0;
|
|
|
|
#define DECL(Derived, Base) \
|
|
|
|
if (n##Derived##s > 0) { \
|
|
|
|
totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl)); \
|
|
|
|
fprintf(stderr, " %d " #Derived " decls, %d each (%d bytes)\n", \
|
|
|
|
n##Derived##s, (int)sizeof(Derived##Decl), \
|
|
|
|
(int)(n##Derived##s * sizeof(Derived##Decl))); \
|
|
|
|
}
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
2008-06-08 00:52:53 +08:00
|
|
|
|
2009-02-03 07:39:07 +08:00
|
|
|
fprintf(stderr, "Total bytes = %d\n", totalBytes);
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::addDeclKind(Kind k) {
|
|
|
|
switch (k) {
|
2009-02-03 07:39:07 +08:00
|
|
|
default: assert(0 && "Declaration not in DeclNodes.def!");
|
|
|
|
#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-05 16:00:35 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PrettyStackTraceDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
|
|
|
|
SourceLocation TheLoc = Loc;
|
|
|
|
if (TheLoc.isInvalid() && TheDecl)
|
|
|
|
TheLoc = TheDecl->getLocation();
|
|
|
|
|
|
|
|
if (TheLoc.isValid()) {
|
|
|
|
TheLoc.print(OS, SM);
|
|
|
|
OS << ": ";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << Message;
|
|
|
|
|
|
|
|
if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
|
|
|
|
OS << " '" << DN->getQualifiedNameAsString() << '\'';
|
|
|
|
OS << '\n';
|
|
|
|
}
|
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Decl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
// Out-of-line virtual method providing a home for Decl.
|
|
|
|
Decl::~Decl() {
|
|
|
|
if (isOutOfSemaDC())
|
|
|
|
delete getMultipleDC();
|
|
|
|
|
|
|
|
assert(!HasAttrs && "attributes should have been freed by Destroy");
|
|
|
|
}
|
|
|
|
|
2009-01-20 09:17:11 +08:00
|
|
|
void Decl::setDeclContext(DeclContext *DC) {
|
|
|
|
if (isOutOfSemaDC())
|
|
|
|
delete getMultipleDC();
|
|
|
|
|
2009-03-29 14:06:59 +08:00
|
|
|
DeclCtx = DC;
|
2009-01-20 09:17:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::setLexicalDeclContext(DeclContext *DC) {
|
|
|
|
if (DC == getLexicalDeclContext())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isInSemaDC()) {
|
|
|
|
MultipleDC *MDC = new MultipleDC();
|
|
|
|
MDC->SemanticDC = getDeclContext();
|
|
|
|
MDC->LexicalDC = DC;
|
2009-03-29 14:06:59 +08:00
|
|
|
DeclCtx = MDC;
|
2009-01-20 09:17:11 +08:00
|
|
|
} else {
|
|
|
|
getMultipleDC()->LexicalDC = DC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|
|
|
switch (DeclKind) {
|
|
|
|
default:
|
|
|
|
if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
|
|
|
|
return IDNS_Ordinary;
|
|
|
|
assert(0 && "Unknown decl kind!");
|
|
|
|
case OverloadedFunction:
|
|
|
|
case Typedef:
|
|
|
|
case EnumConstant:
|
|
|
|
case Var:
|
|
|
|
case ImplicitParam:
|
|
|
|
case ParmVar:
|
|
|
|
case OriginalParmVar:
|
|
|
|
case NonTypeTemplateParm:
|
|
|
|
case ObjCMethod:
|
|
|
|
case ObjCContainer:
|
|
|
|
case ObjCCategory:
|
|
|
|
case ObjCInterface:
|
|
|
|
case ObjCCategoryImpl:
|
|
|
|
case ObjCProperty:
|
|
|
|
case ObjCCompatibleAlias:
|
|
|
|
return IDNS_Ordinary;
|
|
|
|
|
|
|
|
case ObjCProtocol:
|
|
|
|
return IDNS_Protocol;
|
|
|
|
|
|
|
|
case Field:
|
|
|
|
case ObjCAtDefsField:
|
|
|
|
case ObjCIvar:
|
|
|
|
return IDNS_Member;
|
|
|
|
|
|
|
|
case Record:
|
|
|
|
case CXXRecord:
|
|
|
|
case Enum:
|
|
|
|
case TemplateTypeParm:
|
|
|
|
return IDNS_Tag;
|
|
|
|
|
|
|
|
case Namespace:
|
|
|
|
case Template:
|
|
|
|
case FunctionTemplate:
|
|
|
|
case ClassTemplate:
|
|
|
|
case TemplateTemplateParm:
|
2009-03-29 07:02:53 +08:00
|
|
|
case NamespaceAlias:
|
2009-03-28 04:18:19 +08:00
|
|
|
return IDNS_Tag | IDNS_Ordinary;
|
|
|
|
|
|
|
|
// Never have names.
|
|
|
|
case LinkageSpec:
|
|
|
|
case FileScopeAsm:
|
|
|
|
case StaticAssert:
|
|
|
|
case ObjCClass:
|
|
|
|
case ObjCImplementation:
|
|
|
|
case ObjCPropertyImpl:
|
|
|
|
case ObjCForwardProtocol:
|
|
|
|
case Block:
|
|
|
|
case TranslationUnit:
|
|
|
|
|
|
|
|
// Aren't looked up?
|
|
|
|
case UsingDirective:
|
|
|
|
case ClassTemplateSpecialization:
|
|
|
|
return 0;
|
|
|
|
}
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::addAttr(Attr *NewAttr) {
|
|
|
|
if (!DeclAttrs)
|
|
|
|
DeclAttrs = new DeclAttrMapTy();
|
|
|
|
|
|
|
|
Attr *&ExistingAttr = (*DeclAttrs)[this];
|
|
|
|
|
|
|
|
NewAttr->setNext(ExistingAttr);
|
|
|
|
ExistingAttr = NewAttr;
|
|
|
|
|
|
|
|
HasAttrs = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::invalidateAttrs() {
|
|
|
|
if (!HasAttrs) return;
|
|
|
|
|
|
|
|
HasAttrs = false;
|
|
|
|
(*DeclAttrs)[this] = 0;
|
|
|
|
DeclAttrs->erase(this);
|
|
|
|
|
|
|
|
if (DeclAttrs->empty()) {
|
|
|
|
delete DeclAttrs;
|
|
|
|
DeclAttrs = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-21 14:27:31 +08:00
|
|
|
const Attr *Decl::getAttrsImpl() const {
|
|
|
|
assert(HasAttrs && "getAttrs() should verify this!");
|
2008-06-08 00:52:53 +08:00
|
|
|
return (*DeclAttrs)[this];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::swapAttrs(Decl *RHS) {
|
|
|
|
bool HasLHSAttr = this->HasAttrs;
|
|
|
|
bool HasRHSAttr = RHS->HasAttrs;
|
|
|
|
|
|
|
|
// Usually, neither decl has attrs, nothing to do.
|
|
|
|
if (!HasLHSAttr && !HasRHSAttr) return;
|
|
|
|
|
|
|
|
// If 'this' has no attrs, swap the other way.
|
|
|
|
if (!HasLHSAttr)
|
|
|
|
return RHS->swapAttrs(this);
|
|
|
|
|
|
|
|
// Handle the case when both decls have attrs.
|
|
|
|
if (HasRHSAttr) {
|
|
|
|
std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, LHS has an attr and RHS doesn't.
|
|
|
|
(*DeclAttrs)[RHS] = (*DeclAttrs)[this];
|
|
|
|
(*DeclAttrs).erase(this);
|
|
|
|
this->HasAttrs = false;
|
|
|
|
RHS->HasAttrs = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-04 14:05:19 +08:00
|
|
|
void Decl::Destroy(ASTContext &C) {
|
|
|
|
// Free attributes for this decl.
|
|
|
|
if (HasAttrs) {
|
|
|
|
DeclAttrMapTy::iterator it = DeclAttrs->find(this);
|
|
|
|
assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
|
|
|
|
|
|
|
|
// release attributes.
|
|
|
|
it->second->Destroy(C);
|
|
|
|
invalidateAttrs();
|
|
|
|
HasAttrs = false;
|
|
|
|
}
|
|
|
|
|
2009-01-14 03:47:12 +08:00
|
|
|
#if 0
|
2009-01-20 12:25:11 +08:00
|
|
|
// FIXME: Once ownership is fully understood, we can enable this code
|
|
|
|
if (DeclContext *DC = dyn_cast<DeclContext>(this))
|
|
|
|
DC->decls_begin()->Destroy(C);
|
2008-06-08 00:52:53 +08:00
|
|
|
|
2009-03-28 14:04:26 +08:00
|
|
|
// Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0
|
2009-01-20 09:17:11 +08:00
|
|
|
// within the loop, only the Destroy method for the first Decl
|
|
|
|
// will deallocate all of the Decls in a chain.
|
|
|
|
|
2009-03-28 14:04:26 +08:00
|
|
|
Decl* N = getNextDeclInContext();
|
2009-01-20 09:17:11 +08:00
|
|
|
|
|
|
|
while (N) {
|
2009-03-28 14:04:26 +08:00
|
|
|
Decl* Tmp = N->getNextDeclInContext();
|
|
|
|
N->NextDeclInContext = 0;
|
2009-01-20 09:17:11 +08:00
|
|
|
N->Destroy(C);
|
|
|
|
N = Tmp;
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
2009-01-14 03:47:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
this->~Decl();
|
2009-01-28 05:25:57 +08:00
|
|
|
C.Deallocate((void *)this);
|
2009-01-20 12:25:11 +08:00
|
|
|
#endif
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
2008-10-13 00:14:48 +08:00
|
|
|
Decl *Decl::castFromDeclContext (const DeclContext *D) {
|
2009-02-16 22:29:28 +08:00
|
|
|
Decl::Kind DK = D->getDeclKind();
|
|
|
|
switch(DK) {
|
|
|
|
#define DECL_CONTEXT(Name) \
|
|
|
|
case Decl::Name: \
|
|
|
|
return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
|
|
|
|
#define DECL_CONTEXT_BASE(Name)
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
default:
|
|
|
|
#define DECL_CONTEXT_BASE(Name) \
|
|
|
|
if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
|
|
|
|
return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
assert(false && "a decl that inherits DeclContext isn't handled");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-13 00:14:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DeclContext *Decl::castToDeclContext(const Decl *D) {
|
2009-02-16 22:29:28 +08:00
|
|
|
Decl::Kind DK = D->getKind();
|
|
|
|
switch(DK) {
|
|
|
|
#define DECL_CONTEXT(Name) \
|
|
|
|
case Decl::Name: \
|
|
|
|
return static_cast<Name##Decl*>(const_cast<Decl*>(D));
|
|
|
|
#define DECL_CONTEXT_BASE(Name)
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
default:
|
|
|
|
#define DECL_CONTEXT_BASE(Name) \
|
|
|
|
if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
|
|
|
|
return static_cast<Name##Decl*>(const_cast<Decl*>(D));
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
assert(false && "a decl that inherits DeclContext isn't handled");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-13 00:14:48 +08:00
|
|
|
}
|
|
|
|
|
2009-03-26 07:38:06 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
void Decl::CheckAccessDeclContext() const {
|
2009-04-08 04:58:25 +08:00
|
|
|
assert((Access != AS_none || isa<TranslationUnitDecl>(this) ||
|
|
|
|
!isa<CXXRecordDecl>(getDeclContext())) &&
|
2009-03-26 07:38:06 +08:00
|
|
|
"Access specifier is AS_none inside a record decl");
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DeclContext Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-16 22:29:28 +08:00
|
|
|
bool DeclContext::classof(const Decl *D) {
|
|
|
|
switch (D->getKind()) {
|
|
|
|
#define DECL_CONTEXT(Name) case Decl::Name:
|
|
|
|
#define DECL_CONTEXT_BASE(Name)
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
#define DECL_CONTEXT_BASE(Name) \
|
|
|
|
if (D->getKind() >= Decl::Name##First && \
|
|
|
|
D->getKind() <= Decl::Name##Last) \
|
|
|
|
return true;
|
|
|
|
#include "clang/AST/DeclNodes.def"
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
DeclContext::~DeclContext() {
|
2009-04-10 01:29:08 +08:00
|
|
|
delete static_cast<StoredDeclsMap*>(LookupPtr);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclContext::DestroyDecls(ASTContext &C) {
|
2009-04-10 05:40:53 +08:00
|
|
|
for (decl_iterator D = decls_begin(C); D != decls_end(C); )
|
2009-01-20 12:25:11 +08:00
|
|
|
(*D++)->Destroy(C);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-01-06 03:45:36 +08:00
|
|
|
bool DeclContext::isTransparentContext() const {
|
|
|
|
if (DeclKind == Decl::Enum)
|
|
|
|
return true; // FIXME: Check for C++0x scoped enums
|
|
|
|
else if (DeclKind == Decl::LinkageSpec)
|
|
|
|
return true;
|
2009-02-26 08:02:51 +08:00
|
|
|
else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast)
|
2009-01-07 08:43:41 +08:00
|
|
|
return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
|
2009-01-06 03:45:36 +08:00
|
|
|
else if (DeclKind == Decl::Namespace)
|
|
|
|
return false; // FIXME: Check for C++0x inline namespaces
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-09 01:28:14 +08:00
|
|
|
DeclContext *DeclContext::getPrimaryContext() {
|
2008-12-12 00:49:14 +08:00
|
|
|
switch (DeclKind) {
|
|
|
|
case Decl::TranslationUnit:
|
2009-01-06 03:45:36 +08:00
|
|
|
case Decl::LinkageSpec:
|
|
|
|
case Decl::Block:
|
2008-12-12 00:49:14 +08:00
|
|
|
// There is only one DeclContext for these entities.
|
|
|
|
return this;
|
|
|
|
|
|
|
|
case Decl::Namespace:
|
|
|
|
// The original namespace is our primary context.
|
|
|
|
return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
|
|
|
|
|
|
|
|
case Decl::ObjCMethod:
|
|
|
|
return this;
|
|
|
|
|
|
|
|
case Decl::ObjCInterface:
|
2009-01-09 01:28:14 +08:00
|
|
|
case Decl::ObjCProtocol:
|
|
|
|
case Decl::ObjCCategory:
|
2008-12-12 00:49:14 +08:00
|
|
|
// FIXME: Can Objective-C interfaces be forward-declared?
|
|
|
|
return this;
|
|
|
|
|
2009-01-09 01:28:14 +08:00
|
|
|
case Decl::ObjCImplementation:
|
|
|
|
case Decl::ObjCCategoryImpl:
|
|
|
|
return this;
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
default:
|
2009-02-18 07:15:12 +08:00
|
|
|
if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
|
|
|
|
// If this is a tag type that has a definition or is currently
|
|
|
|
// being defined, that definition is our primary context.
|
2009-03-28 14:04:26 +08:00
|
|
|
if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAsTagType())
|
2009-02-18 07:15:12 +08:00
|
|
|
if (TagT->isBeingDefined() ||
|
|
|
|
(TagT->getDecl() && TagT->getDecl()->isDefinition()))
|
|
|
|
return TagT->getDecl();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
|
|
|
|
"Unknown DeclContext kind");
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclContext *DeclContext::getNextContext() {
|
|
|
|
switch (DeclKind) {
|
|
|
|
case Decl::Namespace:
|
|
|
|
// Return the next namespace
|
|
|
|
return static_cast<NamespaceDecl*>(this)->getNextNamespace();
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-10 06:27:44 +08:00
|
|
|
/// \brief Load the declarations within this lexical storage from an
|
|
|
|
/// external source.
|
|
|
|
void
|
|
|
|
DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const {
|
|
|
|
ExternalASTSource *Source = Context.getExternalSource();
|
|
|
|
assert(hasExternalLexicalStorage() && Source && "No external storage?");
|
|
|
|
|
|
|
|
llvm::SmallVector<unsigned, 64> Decls;
|
|
|
|
if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
|
|
|
|
Decls))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// There is no longer any lexical storage in this context
|
|
|
|
ExternalLexicalStorage = false;
|
|
|
|
|
|
|
|
if (Decls.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Resolve all of the declaration IDs into declarations, building up
|
|
|
|
// a chain of declarations via the Decl::NextDeclInContext field.
|
|
|
|
Decl *FirstNewDecl = 0;
|
|
|
|
Decl *PrevDecl = 0;
|
|
|
|
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
|
|
|
|
Decl *D = Source->GetDecl(Decls[I]);
|
|
|
|
if (PrevDecl)
|
|
|
|
PrevDecl->NextDeclInContext = D;
|
|
|
|
else
|
|
|
|
FirstNewDecl = D;
|
|
|
|
|
|
|
|
PrevDecl = D;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Splice the newly-read declarations into the beginning of the list
|
|
|
|
// of declarations.
|
|
|
|
PrevDecl->NextDeclInContext = FirstDecl;
|
|
|
|
FirstDecl = FirstNewDecl;
|
|
|
|
if (!LastDecl)
|
|
|
|
LastDecl = PrevDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const {
|
|
|
|
DeclContext *This = const_cast<DeclContext *>(this);
|
|
|
|
ExternalASTSource *Source = Context.getExternalSource();
|
|
|
|
assert(hasExternalVisibleStorage() && Source && "No external storage?");
|
|
|
|
|
|
|
|
llvm::SmallVector<VisibleDeclaration, 64> Decls;
|
|
|
|
if (Source->ReadDeclsVisibleInContext(This, Decls))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// There is no longer any visible storage in this context
|
|
|
|
ExternalVisibleStorage = false;
|
|
|
|
|
|
|
|
// Load the declaration IDs for all of the names visible in this
|
|
|
|
// context.
|
|
|
|
assert(!LookupPtr && "Have a lookup map before de-serialization?");
|
|
|
|
StoredDeclsMap *Map = new StoredDeclsMap;
|
|
|
|
LookupPtr = Map;
|
|
|
|
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
|
|
|
|
(*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const {
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalLexicalStorage())
|
|
|
|
LoadLexicalDeclsFromExternalStorage(Context);
|
|
|
|
|
|
|
|
// FIXME: Check whether we need to load some declarations from
|
|
|
|
// external storage.
|
2009-04-10 05:40:53 +08:00
|
|
|
return decl_iterator(FirstDecl);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const {
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalLexicalStorage())
|
|
|
|
LoadLexicalDeclsFromExternalStorage(Context);
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
return decl_iterator();
|
|
|
|
}
|
|
|
|
|
2009-04-11 01:25:41 +08:00
|
|
|
bool DeclContext::decls_empty(ASTContext &Context) const {
|
|
|
|
if (hasExternalLexicalStorage())
|
|
|
|
LoadLexicalDeclsFromExternalStorage(Context);
|
|
|
|
|
|
|
|
return !FirstDecl;
|
|
|
|
}
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
void DeclContext::addDecl(ASTContext &Context, Decl *D) {
|
2009-02-20 08:56:18 +08:00
|
|
|
assert(D->getLexicalDeclContext() == this &&
|
|
|
|
"Decl inserted into wrong lexical context");
|
2009-03-28 14:04:26 +08:00
|
|
|
assert(!D->getNextDeclInContext() && D != LastDecl &&
|
2009-01-10 03:42:16 +08:00
|
|
|
"Decl already inserted into a DeclContext");
|
|
|
|
|
|
|
|
if (FirstDecl) {
|
2009-03-28 14:04:26 +08:00
|
|
|
LastDecl->NextDeclInContext = D;
|
2009-01-10 03:42:16 +08:00
|
|
|
LastDecl = D;
|
|
|
|
} else {
|
|
|
|
FirstDecl = LastDecl = D;
|
|
|
|
}
|
2009-01-20 09:17:11 +08:00
|
|
|
|
|
|
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
2009-04-10 05:40:53 +08:00
|
|
|
ND->getDeclContext()->makeDeclVisibleInContext(Context, ND);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-01-06 03:45:36 +08:00
|
|
|
/// buildLookup - Build the lookup data structure with all of the
|
|
|
|
/// declarations in DCtx (and any other contexts linked to it or
|
|
|
|
/// transparent contexts nested within it).
|
2009-04-10 05:40:53 +08:00
|
|
|
void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
|
2009-01-06 03:45:36 +08:00
|
|
|
for (; DCtx; DCtx = DCtx->getNextContext()) {
|
2009-04-10 05:40:53 +08:00
|
|
|
for (decl_iterator D = DCtx->decls_begin(Context),
|
|
|
|
DEnd = DCtx->decls_end(Context);
|
2009-01-06 15:17:58 +08:00
|
|
|
D != DEnd; ++D) {
|
2009-01-06 03:45:36 +08:00
|
|
|
// Insert this declaration into the lookup structure
|
2009-01-20 09:17:11 +08:00
|
|
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
|
2009-04-10 05:40:53 +08:00
|
|
|
makeDeclVisibleInContextImpl(Context, ND);
|
2009-01-06 03:45:36 +08:00
|
|
|
|
|
|
|
// If this declaration is itself a transparent declaration context,
|
|
|
|
// add its members (recursively).
|
|
|
|
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
|
|
|
|
if (InnerCtx->isTransparentContext())
|
2009-04-10 05:40:53 +08:00
|
|
|
buildLookup(Context, InnerCtx->getPrimaryContext());
|
2009-01-06 03:45:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
DeclContext::lookup_result
|
2009-04-10 05:40:53 +08:00
|
|
|
DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
|
2009-01-09 01:28:14 +08:00
|
|
|
DeclContext *PrimaryContext = getPrimaryContext();
|
2008-12-12 00:49:14 +08:00
|
|
|
if (PrimaryContext != this)
|
2009-04-10 05:40:53 +08:00
|
|
|
return PrimaryContext->lookup(Context, Name);
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalVisibleStorage())
|
|
|
|
LoadVisibleDeclsFromExternalStorage(Context);
|
|
|
|
|
2008-12-23 08:26:44 +08:00
|
|
|
/// If there is no lookup data structure, build one now by walking
|
2008-12-12 00:49:14 +08:00
|
|
|
/// all of the linked DeclContexts (in declaration order!) and
|
|
|
|
/// inserting their values.
|
2009-04-10 01:29:08 +08:00
|
|
|
if (!LookupPtr) {
|
2009-04-10 05:40:53 +08:00
|
|
|
buildLookup(Context, this);
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-04-10 01:29:08 +08:00
|
|
|
if (!LookupPtr)
|
2009-02-20 08:55:03 +08:00
|
|
|
return lookup_result(0, 0);
|
2009-04-10 01:29:08 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-04-10 01:29:08 +08:00
|
|
|
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr);
|
|
|
|
StoredDeclsMap::iterator Pos = Map->find(Name);
|
|
|
|
if (Pos == Map->end())
|
|
|
|
return lookup_result(0, 0);
|
2009-04-10 05:40:53 +08:00
|
|
|
return Pos->second.getLookupResult(Context);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DeclContext::lookup_const_result
|
2009-04-10 05:40:53 +08:00
|
|
|
DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
|
|
|
|
return const_cast<DeclContext*>(this)->lookup(Context, Name);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-03-28 03:19:59 +08:00
|
|
|
DeclContext *DeclContext::getLookupContext() {
|
|
|
|
DeclContext *Ctx = this;
|
Unify the code for defining tags in C and C++, so that we always
introduce a Scope for the body of a tag. This reduces the number of
semantic differences between C and C++ structs and unions, and will
help with other features (e.g., anonymous unions) in C. Some important
points:
- Fields are now in the "member" namespace (IDNS_Member), to keep
them separate from tags and ordinary names in C. See the new test
in Sema/member-reference.c for an example of why this matters. In
C++, ordinary and member name lookup will find members in both the
ordinary and member namespace, so the difference between
IDNS_Member and IDNS_Ordinary is erased by Sema::LookupDecl (but
only in C++!).
- We always introduce a Scope and push a DeclContext when we're
defining a tag, in both C and C++. Previously, we had different
actions and different Scope/CurContext behavior for enums, C
structs/unions, and C++ structs/unions/classes. Now, it's one pair
of actions. (Yay!)
There's still some fuzziness in the handling of struct/union/enum
definitions within other struct/union/enum definitions in C. We'll
need to do some more cleanup to eliminate some reliance on CurContext
before we can solve this issue for real. What we want is for something
like this:
struct X {
struct T { int x; } t;
};
to introduce T into translation unit scope (placing it at the
appropriate point in the IdentifierResolver chain, too), but it should
still have struct X as its lexical declaration
context. PushOnScopeChains isn't smart enough to do that yet, though,
so there's a FIXME test in nested-redef.c
llvm-svn: 61940
2009-01-09 04:45:30 +08:00
|
|
|
// Skip through transparent contexts.
|
2009-01-07 07:51:29 +08:00
|
|
|
while (Ctx->isTransparentContext())
|
|
|
|
Ctx = Ctx->getParent();
|
|
|
|
return Ctx;
|
|
|
|
}
|
|
|
|
|
2009-02-26 06:02:03 +08:00
|
|
|
DeclContext *DeclContext::getEnclosingNamespaceContext() {
|
|
|
|
DeclContext *Ctx = this;
|
|
|
|
// Skip through non-namespace, non-translation-unit contexts.
|
|
|
|
while (!Ctx->isFileContext() || Ctx->isTransparentContext())
|
|
|
|
Ctx = Ctx->getParent();
|
|
|
|
return Ctx->getPrimaryContext();
|
|
|
|
}
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) {
|
2009-02-18 07:15:12 +08:00
|
|
|
// FIXME: This feels like a hack. Should DeclarationName support
|
|
|
|
// template-ids, or is there a better way to keep specializations
|
|
|
|
// from being visible?
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(D))
|
|
|
|
return;
|
|
|
|
|
2009-01-09 01:28:14 +08:00
|
|
|
DeclContext *PrimaryContext = getPrimaryContext();
|
2008-12-12 00:49:14 +08:00
|
|
|
if (PrimaryContext != this) {
|
2009-04-10 05:40:53 +08:00
|
|
|
PrimaryContext->makeDeclVisibleInContext(Context, D);
|
2008-12-12 00:49:14 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we already have a lookup data structure, perform the insertion
|
|
|
|
// into it. Otherwise, be lazy and don't build that structure until
|
|
|
|
// someone asks for it.
|
2009-04-10 01:29:08 +08:00
|
|
|
if (LookupPtr)
|
2009-04-10 05:40:53 +08:00
|
|
|
makeDeclVisibleInContextImpl(Context, D);
|
2009-01-06 03:45:36 +08:00
|
|
|
|
|
|
|
// If we are a transparent context, insert into our parent context,
|
|
|
|
// too. This operation is recursive.
|
|
|
|
if (isTransparentContext())
|
2009-04-10 05:40:53 +08:00
|
|
|
getParent()->makeDeclVisibleInContext(Context, D);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context,
|
|
|
|
NamedDecl *D) {
|
2009-01-06 03:45:36 +08:00
|
|
|
// Skip unnamed declarations.
|
|
|
|
if (!D->getDeclName())
|
|
|
|
return;
|
|
|
|
|
2009-02-18 07:15:12 +08:00
|
|
|
// FIXME: This feels like a hack. Should DeclarationName support
|
|
|
|
// template-ids, or is there a better way to keep specializations
|
|
|
|
// from being visible?
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(D))
|
|
|
|
return;
|
|
|
|
|
2009-04-10 01:29:08 +08:00
|
|
|
if (!LookupPtr)
|
|
|
|
LookupPtr = new StoredDeclsMap;
|
2008-12-12 00:49:14 +08:00
|
|
|
|
|
|
|
// Insert this declaration into the map.
|
2009-04-10 01:29:08 +08:00
|
|
|
StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr);
|
2009-02-20 09:44:05 +08:00
|
|
|
StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
|
|
|
|
if (DeclNameEntries.isNull()) {
|
|
|
|
DeclNameEntries.setOnlyValue(D);
|
2009-02-19 15:00:44 +08:00
|
|
|
return;
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
2009-02-20 08:55:03 +08:00
|
|
|
|
2009-02-20 09:10:07 +08:00
|
|
|
// If it is possible that this is a redeclaration, check to see if there is
|
|
|
|
// already a decl for which declarationReplaces returns true. If there is
|
|
|
|
// one, just replace it and return.
|
2009-04-10 05:40:53 +08:00
|
|
|
if (DeclNameEntries.HandleRedeclaration(Context, D))
|
2009-02-20 09:44:05 +08:00
|
|
|
return;
|
2009-02-20 08:55:03 +08:00
|
|
|
|
2009-02-19 15:00:44 +08:00
|
|
|
// Put this declaration into the appropriate slot.
|
2009-02-20 09:44:05 +08:00
|
|
|
DeclNameEntries.AddSubsequentDecl(D);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
|
|
|
|
/// this context.
|
2009-04-10 05:40:53 +08:00
|
|
|
DeclContext::udir_iterator_range
|
|
|
|
DeclContext::getUsingDirectives(ASTContext &Context) const {
|
|
|
|
lookup_const_result Result = lookup(Context, UsingDirectiveDecl::getName());
|
2009-02-04 03:21:40 +08:00
|
|
|
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
|
|
|
|
reinterpret_cast<udir_iterator>(Result.second));
|
|
|
|
}
|
2009-04-10 06:27:44 +08:00
|
|
|
|
|
|
|
void StoredDeclsList::materializeDecls(ASTContext &Context) {
|
|
|
|
if (isNull())
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch ((DataKind)(Data & 0x03)) {
|
|
|
|
case DK_Decl:
|
|
|
|
case DK_Decl_Vector:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DK_DeclID: {
|
|
|
|
// Resolve this declaration ID to an actual declaration by
|
|
|
|
// querying the external AST source.
|
|
|
|
unsigned DeclID = Data >> 2;
|
|
|
|
|
|
|
|
ExternalASTSource *Source = Context.getExternalSource();
|
|
|
|
assert(Source && "No external AST source available!");
|
|
|
|
|
|
|
|
Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case DK_ID_Vector: {
|
|
|
|
// We have a vector of declaration IDs. Resolve all of them to
|
|
|
|
// actual declarations.
|
|
|
|
VectorTy &Vector = *getAsVector();
|
|
|
|
ExternalASTSource *Source = Context.getExternalSource();
|
|
|
|
assert(Source && "No external AST source available!");
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = Vector.size(); I != N; ++I)
|
|
|
|
Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));
|
|
|
|
|
|
|
|
Data = (Data & ~0x03) | DK_Decl_Vector;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|