aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/DeclBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/DeclBase.cpp')
-rw-r--r--lib/AST/DeclBase.cpp164
1 files changed, 108 insertions, 56 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 96ba19b9a6b9..224bf877ad24 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -62,12 +62,12 @@ bool Decl::CollectingStats(bool Enable) {
void Decl::PrintStats() {
fprintf(stderr, "*** Decl Stats:\n");
-
+
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) { \
@@ -77,7 +77,7 @@ void Decl::PrintStats() {
(int)(n##Derived##s * sizeof(Derived##Decl))); \
}
#include "clang/AST/DeclNodes.def"
-
+
fprintf(stderr, "Total bytes = %d\n", totalBytes);
}
@@ -92,26 +92,26 @@ void Decl::addDeclKind(Kind k) {
bool Decl::isTemplateParameterPack() const {
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
return TTP->isParameterPack();
-
+
return false;
}
bool Decl::isFunctionOrFunctionTemplate() const {
if (const UsingDecl *UD = dyn_cast<UsingDecl>(this))
return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
-
+
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
//===----------------------------------------------------------------------===//
// 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 << ": ";
@@ -123,7 +123,7 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
OS << " '" << DN->getQualifiedNameAsString() << '\'';
OS << '\n';
}
-
+
//===----------------------------------------------------------------------===//
// Decl Implementation
//===----------------------------------------------------------------------===//
@@ -132,14 +132,14 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
Decl::~Decl() {
if (isOutOfSemaDC())
delete getMultipleDC();
-
+
assert(!HasAttrs && "attributes should have been freed by Destroy");
}
void Decl::setDeclContext(DeclContext *DC) {
if (isOutOfSemaDC())
delete getMultipleDC();
-
+
DeclCtx = DC;
}
@@ -157,28 +157,39 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
}
}
+bool Decl::isInAnonymousNamespace() const {
+ const DeclContext *DC = getDeclContext();
+ do {
+ if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
+ if (ND->isAnonymousNamespace())
+ return true;
+ } while ((DC = DC->getParent()));
+
+ return false;
+}
+
TranslationUnitDecl *Decl::getTranslationUnitDecl() {
if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
return TUD;
DeclContext *DC = getDeclContext();
assert(DC && "This decl is not contained in a translation unit!");
-
+
while (!DC->isTranslationUnit()) {
DC = DC->getParent();
assert(DC && "This decl is not contained in a translation unit!");
}
-
+
return cast<TranslationUnitDecl>(DC);
}
ASTContext &Decl::getASTContext() const {
- return getTranslationUnitDecl()->getASTContext();
+ return getTranslationUnitDecl()->getASTContext();
}
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
switch (DeclKind) {
- default:
+ default:
if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
return IDNS_Ordinary;
assert(0 && "Unknown decl kind!");
@@ -191,6 +202,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case OriginalParmVar:
case NonTypeTemplateParm:
case Using:
+ case UnresolvedUsing:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
@@ -198,10 +210,10 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCProperty:
case ObjCCompatibleAlias:
return IDNS_Ordinary;
-
+
case ObjCProtocol:
return IDNS_ObjCProtocol;
-
+
case ObjCImplementation:
return IDNS_ObjCImplementation;
@@ -212,13 +224,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCAtDefsField:
case ObjCIvar:
return IDNS_Member;
-
+
case Record:
case CXXRecord:
case Enum:
case TemplateTypeParm:
return IDNS_Tag;
-
+
case Namespace:
case Template:
case FunctionTemplate:
@@ -226,8 +238,10 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case TemplateTemplateParm:
case NamespaceAlias:
return IDNS_Tag | IDNS_Ordinary;
-
+
// Never have names.
+ case Friend:
+ case FriendTemplate:
case LinkageSpec:
case FileScopeAsm:
case StaticAssert:
@@ -250,41 +264,41 @@ void Decl::addAttr(Attr *NewAttr) {
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
-
+
HasAttrs = true;
}
void Decl::invalidateAttrs() {
if (!HasAttrs) return;
-
+
HasAttrs = false;
getASTContext().eraseDeclAttrs(this);
}
const Attr *Decl::getAttrsImpl() const {
- assert(HasAttrs && "getAttrs() should verify this!");
+ assert(HasAttrs && "getAttrs() should verify this!");
return getASTContext().getDeclAttrs(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);
-
+
ASTContext &Context = getASTContext();
-
+
// Handle the case when both decls have attrs.
if (HasRHSAttr) {
std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
return;
}
-
+
// Otherwise, LHS has an attr and RHS doesn't.
Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
Context.eraseDeclAttrs(this);
@@ -300,7 +314,7 @@ void Decl::Destroy(ASTContext &C) {
invalidateAttrs();
HasAttrs = false;
}
-
+
#if 0
// FIXME: Once ownership is fully understood, we can enable this code
if (DeclContext *DC = dyn_cast<DeclContext>(this))
@@ -309,15 +323,15 @@ void Decl::Destroy(ASTContext &C) {
// Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0
// within the loop, only the Destroy method for the first Decl
// will deallocate all of the Decls in a chain.
-
+
Decl* N = getNextDeclInContext();
-
+
while (N) {
Decl* Tmp = N->getNextDeclInContext();
N->NextDeclInContext = 0;
N->Destroy(C);
N = Tmp;
- }
+ }
this->~Decl();
C.Deallocate((void *)this);
@@ -377,8 +391,13 @@ SourceLocation Decl::getBodyRBrace() const {
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
- assert((Access != AS_none || isa<TranslationUnitDecl>(this) ||
- !isa<CXXRecordDecl>(getDeclContext())) &&
+ // If the decl is the toplevel translation unit or if we're not in a
+ // record decl context, we don't need to check anything.
+ if (isa<TranslationUnitDecl>(this) ||
+ !isa<CXXRecordDecl>(getDeclContext()))
+ return;
+
+ assert(Access != AS_none &&
"Access specifier is AS_none inside a record decl");
}
@@ -413,6 +432,22 @@ void DeclContext::DestroyDecls(ASTContext &C) {
(*D++)->Destroy(C);
}
+/// \brief Find the parent context of this context that will be
+/// used for unqualified name lookup.
+///
+/// Generally, the parent lookup context is the semantic context. However, for
+/// a friend function the parent lookup context is the lexical context, which
+/// is the class in which the friend is declared.
+DeclContext *DeclContext::getLookupParent() {
+ // FIXME: Find a better way to identify friends
+ if (isa<FunctionDecl>(this))
+ if (getParent()->getLookupContext()->isFileContext() &&
+ getLexicalParent()->getLookupContext()->isRecord())
+ return getLexicalParent();
+
+ return getParent();
+}
+
bool DeclContext::isDependentContext() const {
if (isFileContext())
return false;
@@ -427,7 +462,7 @@ bool DeclContext::isDependentContext() const {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this))
if (Function->getDescribedFunctionTemplate())
return true;
-
+
return getParent() && getParent()->isDependentContext();
}
@@ -444,11 +479,21 @@ bool DeclContext::isTransparentContext() const {
return false;
}
+bool DeclContext::Encloses(DeclContext *DC) {
+ if (getPrimaryContext() != this)
+ return getPrimaryContext()->Encloses(DC);
+
+ for (; DC; DC = DC->getParent())
+ if (DC->getPrimaryContext() == this)
+ return true;
+ return false;
+}
+
DeclContext *DeclContext::getPrimaryContext() {
switch (DeclKind) {
case Decl::TranslationUnit:
case Decl::LinkageSpec:
- case Decl::Block:
+ case Decl::Block:
// There is only one DeclContext for these entities.
return this;
@@ -473,8 +518,8 @@ DeclContext *DeclContext::getPrimaryContext() {
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.
- if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAsTagType())
- if (TagT->isBeingDefined() ||
+ if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAs<TagType>())
+ if (TagT->isBeingDefined() ||
(TagT->getDecl() && TagT->getDecl()->isDefinition()))
return TagT->getDecl();
return this;
@@ -499,13 +544,13 @@ DeclContext *DeclContext::getNextContext() {
/// \brief Load the declarations within this lexical storage from an
/// external source.
-void
+void
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
llvm::SmallVector<uint32_t, 64> Decls;
- if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
+ if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
Decls))
return;
@@ -537,7 +582,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
LastDecl = PrevDecl;
}
-void
+void
DeclContext::LoadVisibleDeclsFromExternalStorage() const {
DeclContext *This = const_cast<DeclContext *>(this);
ExternalASTSource *Source = getParentASTContext().getExternalSource();
@@ -566,14 +611,14 @@ DeclContext::decl_iterator DeclContext::decls_begin() const {
// FIXME: Check whether we need to load some declarations from
// external storage.
- return decl_iterator(FirstDecl);
+ return decl_iterator(FirstDecl);
}
DeclContext::decl_iterator DeclContext::decls_end() const {
if (hasExternalLexicalStorage())
LoadLexicalDeclsFromExternalStorage();
- return decl_iterator();
+ return decl_iterator();
}
bool DeclContext::decls_empty() const {
@@ -583,10 +628,10 @@ bool DeclContext::decls_empty() const {
return !FirstDecl;
}
-void DeclContext::addDecl(Decl *D) {
+void DeclContext::addHiddenDecl(Decl *D) {
assert(D->getLexicalDeclContext() == this &&
"Decl inserted into wrong lexical context");
- assert(!D->getNextDeclInContext() && D != LastDecl &&
+ assert(!D->getNextDeclInContext() && D != LastDecl &&
"Decl already inserted into a DeclContext");
if (FirstDecl) {
@@ -595,6 +640,10 @@ void DeclContext::addDecl(Decl *D) {
} else {
FirstDecl = LastDecl = D;
}
+}
+
+void DeclContext::addDecl(Decl *D) {
+ addHiddenDecl(D);
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
ND->getDeclContext()->makeDeclVisibleInContext(ND);
@@ -605,12 +654,15 @@ void DeclContext::addDecl(Decl *D) {
/// transparent contexts nested within it).
void DeclContext::buildLookup(DeclContext *DCtx) {
for (; DCtx; DCtx = DCtx->getNextContext()) {
- for (decl_iterator D = DCtx->decls_begin(),
- DEnd = DCtx->decls_end();
+ for (decl_iterator D = DCtx->decls_begin(),
+ DEnd = DCtx->decls_end();
D != DEnd; ++D) {
- // Insert this declaration into the lookup structure
+ // Insert this declaration into the lookup structure, but only
+ // if it's semantically in its decl context. During non-lazy
+ // lookup building, this is implicitly enforced by addDecl.
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- makeDeclVisibleInContextImpl(ND);
+ if (D->getDeclContext() == DCtx)
+ makeDeclVisibleInContextImpl(ND);
// If this declaration is itself a transparent declaration context,
// add its members (recursively).
@@ -621,7 +673,7 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
}
}
-DeclContext::lookup_result
+DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
@@ -647,7 +699,7 @@ DeclContext::lookup(DeclarationName Name) {
return Pos->second.getLookupResult(getParentASTContext());
}
-DeclContext::lookup_const_result
+DeclContext::lookup_const_result
DeclContext::lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
@@ -668,7 +720,7 @@ DeclContext *DeclContext::getEnclosingNamespaceContext() {
return Ctx->getPrimaryContext();
}
-void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
// from being visible?
@@ -677,20 +729,20 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this) {
- PrimaryContext->makeDeclVisibleInContext(D);
+ PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
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.
- if (LookupPtr)
+ if (LookupPtr || !Recoverable)
makeDeclVisibleInContextImpl(D);
// If we are a transparent context, insert into our parent context,
// too. This operation is recursive.
if (isTransparentContext())
- getParent()->makeDeclVisibleInContext(D);
+ getParent()->makeDeclVisibleInContext(D, Recoverable);
}
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
@@ -720,14 +772,14 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
// one, just replace it and return.
if (DeclNameEntries.HandleRedeclaration(getParentASTContext(), D))
return;
-
+
// Put this declaration into the appropriate slot.
DeclNameEntries.AddSubsequentDecl(D);
}
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
-DeclContext::udir_iterator_range
+DeclContext::udir_iterator_range
DeclContext::getUsingDirectives() const {
lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),