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"
|
2009-04-27 04:35:05 +08:00
|
|
|
#include "clang/AST/Stmt.h"
|
|
|
|
#include "clang/AST/StmtCXX.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;
|
|
|
|
|
|
|
|
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) {
|
2009-11-29 22:54:35 +08:00
|
|
|
if (Enable) StatSwitch = true;
|
2008-06-08 00:52:53 +08:00
|
|
|
return StatSwitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::PrintStats() {
|
|
|
|
fprintf(stderr, "*** Decl Stats:\n");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-03 07:39:07 +08:00
|
|
|
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"
|
2009-09-09 23:08:12 +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-06-13 08:08:58 +08:00
|
|
|
bool Decl::isTemplateParameterPack() const {
|
|
|
|
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
|
|
|
|
return TTP->isParameterPack();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-13 08:08:58 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
bool Decl::isFunctionOrFunctionTemplate() const {
|
2009-11-17 13:59:44 +08:00
|
|
|
if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
|
2009-06-26 13:26:50 +08:00
|
|
|
return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
|
|
|
|
}
|
|
|
|
|
2010-01-17 04:21:20 +08:00
|
|
|
bool Decl::isDefinedOutsideFunctionOrMethod() const {
|
|
|
|
for (const DeclContext *DC = getDeclContext();
|
|
|
|
DC && !DC->isTranslationUnit();
|
|
|
|
DC = DC->getParent())
|
|
|
|
if (DC->isFunctionOrMethod())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-05 16:00:35 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PrettyStackTraceDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-05 16:00:35 +08:00
|
|
|
void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
|
|
|
|
SourceLocation TheLoc = Loc;
|
|
|
|
if (TheLoc.isInvalid() && TheDecl)
|
|
|
|
TheLoc = TheDecl->getLocation();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-05 16:00:35 +08:00
|
|
|
if (TheLoc.isValid()) {
|
|
|
|
TheLoc.print(OS, SM);
|
|
|
|
OS << ": ";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << Message;
|
|
|
|
|
2009-11-21 17:05:59 +08:00
|
|
|
if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
|
2009-03-05 16:00:35 +08:00
|
|
|
OS << " '" << DN->getQualifiedNameAsString() << '\'';
|
|
|
|
OS << '\n';
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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() {
|
|
|
|
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-09-09 23:08:12 +08:00
|
|
|
|
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()) {
|
2009-12-01 08:07:10 +08:00
|
|
|
MultipleDC *MDC = new (getASTContext()) MultipleDC();
|
2009-01-20 09:17:11 +08:00
|
|
|
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-10-01 08:25:31 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-06-30 01:38:40 +08:00
|
|
|
TranslationUnitDecl *Decl::getTranslationUnitDecl() {
|
2009-06-30 10:34:53 +08:00
|
|
|
if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
|
|
|
|
return TUD;
|
|
|
|
|
2009-06-30 01:38:40 +08:00
|
|
|
DeclContext *DC = getDeclContext();
|
|
|
|
assert(DC && "This decl is not contained in a translation unit!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-30 01:38:40 +08:00
|
|
|
while (!DC->isTranslationUnit()) {
|
|
|
|
DC = DC->getParent();
|
|
|
|
assert(DC && "This decl is not contained in a translation unit!");
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-30 01:38:40 +08:00
|
|
|
return cast<TranslationUnitDecl>(DC);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTContext &Decl::getASTContext() const {
|
2009-09-09 23:08:12 +08:00
|
|
|
return getTranslationUnitDecl()->getASTContext();
|
2009-06-30 01:38:40 +08:00
|
|
|
}
|
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|
|
|
switch (DeclKind) {
|
2009-11-17 13:59:44 +08:00
|
|
|
case Function:
|
|
|
|
case CXXMethod:
|
|
|
|
case CXXConstructor:
|
|
|
|
case CXXDestructor:
|
|
|
|
case CXXConversion:
|
2009-03-28 04:18:19 +08:00
|
|
|
case Typedef:
|
|
|
|
case EnumConstant:
|
|
|
|
case Var:
|
|
|
|
case ImplicitParam:
|
|
|
|
case ParmVar:
|
|
|
|
case NonTypeTemplateParm:
|
|
|
|
case ObjCMethod:
|
|
|
|
case ObjCContainer:
|
|
|
|
case ObjCInterface:
|
|
|
|
case ObjCProperty:
|
|
|
|
case ObjCCompatibleAlias:
|
|
|
|
return IDNS_Ordinary;
|
2009-08-11 14:59:38 +08:00
|
|
|
|
2009-11-17 13:59:44 +08:00
|
|
|
case UsingShadow:
|
|
|
|
return 0; // we'll actually overwrite this later
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
case UnresolvedUsingValue:
|
|
|
|
case UnresolvedUsingTypename:
|
|
|
|
return IDNS_Ordinary | IDNS_Using;
|
2009-11-17 13:59:44 +08:00
|
|
|
|
|
|
|
case Using:
|
|
|
|
return IDNS_Using;
|
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
case ObjCProtocol:
|
2009-04-24 08:11:27 +08:00
|
|
|
return IDNS_ObjCProtocol;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-24 08:11:27 +08:00
|
|
|
case ObjCImplementation:
|
|
|
|
return IDNS_ObjCImplementation;
|
|
|
|
|
2009-12-11 08:26:36 +08:00
|
|
|
case ObjCCategory:
|
2009-04-24 08:11:27 +08:00
|
|
|
case ObjCCategoryImpl:
|
2009-12-11 08:26:36 +08:00
|
|
|
return IDNS_ObjCCategoryName;
|
2009-04-24 08:11:27 +08:00
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
case Field:
|
|
|
|
case ObjCAtDefsField:
|
|
|
|
case ObjCIvar:
|
|
|
|
return IDNS_Member;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
case Record:
|
|
|
|
case CXXRecord:
|
|
|
|
case Enum:
|
|
|
|
case TemplateTypeParm:
|
|
|
|
return IDNS_Tag;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
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;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-28 04:18:19 +08:00
|
|
|
// Never have names.
|
2009-08-28 15:59:38 +08:00
|
|
|
case Friend:
|
2009-09-17 06:47:08 +08:00
|
|
|
case FriendTemplate:
|
2009-03-28 04:18:19 +08:00
|
|
|
case LinkageSpec:
|
|
|
|
case FileScopeAsm:
|
|
|
|
case StaticAssert:
|
|
|
|
case ObjCClass:
|
|
|
|
case ObjCPropertyImpl:
|
|
|
|
case ObjCForwardProtocol:
|
|
|
|
case Block:
|
|
|
|
case TranslationUnit:
|
|
|
|
|
|
|
|
// Aren't looked up?
|
|
|
|
case UsingDirective:
|
|
|
|
case ClassTemplateSpecialization:
|
2009-05-31 17:31:02 +08:00
|
|
|
case ClassTemplatePartialSpecialization:
|
2009-03-28 04:18:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2009-11-17 13:59:44 +08:00
|
|
|
|
|
|
|
return 0;
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
void Decl::addAttr(Attr *NewAttr) {
|
|
|
|
Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
|
2008-06-08 00:52:53 +08:00
|
|
|
|
|
|
|
NewAttr->setNext(ExistingAttr);
|
|
|
|
ExistingAttr = NewAttr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
HasAttrs = true;
|
|
|
|
}
|
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
void Decl::invalidateAttrs() {
|
2008-06-08 00:52:53 +08:00
|
|
|
if (!HasAttrs) return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
HasAttrs = false;
|
2009-06-30 10:34:44 +08:00
|
|
|
getASTContext().eraseDeclAttrs(this);
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
const Attr *Decl::getAttrsImpl() const {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(HasAttrs && "getAttrs() should verify this!");
|
2009-06-30 10:34:44 +08:00
|
|
|
return getASTContext().getDeclAttrs(this);
|
2008-06-08 00:52:53 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
void Decl::swapAttrs(Decl *RHS) {
|
2008-06-08 00:52:53 +08:00
|
|
|
bool HasLHSAttr = this->HasAttrs;
|
|
|
|
bool HasRHSAttr = RHS->HasAttrs;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
// Usually, neither decl has attrs, nothing to do.
|
|
|
|
if (!HasLHSAttr && !HasRHSAttr) return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
// If 'this' has no attrs, swap the other way.
|
|
|
|
if (!HasLHSAttr)
|
2009-06-30 10:34:44 +08:00
|
|
|
return RHS->swapAttrs(this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
// Handle the case when both decls have attrs.
|
|
|
|
if (HasRHSAttr) {
|
2009-06-19 00:11:24 +08:00
|
|
|
std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
|
2008-06-08 00:52:53 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
// Otherwise, LHS has an attr and RHS doesn't.
|
2009-06-19 00:11:24 +08:00
|
|
|
Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
|
|
|
|
Context.eraseDeclAttrs(this);
|
2008-06-08 00:52:53 +08:00
|
|
|
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) {
|
2009-06-19 00:11:24 +08:00
|
|
|
C.getDeclAttrs(this)->Destroy(C);
|
2009-06-30 10:34:44 +08:00
|
|
|
invalidateAttrs();
|
2009-03-04 14:05:19 +08:00
|
|
|
HasAttrs = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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-09-09 23:08:12 +08:00
|
|
|
|
2009-03-28 14:04:26 +08:00
|
|
|
Decl* N = getNextDeclInContext();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-14 03:47:12 +08:00
|
|
|
|
2009-12-01 08:07:10 +08:00
|
|
|
if (isOutOfSemaDC())
|
|
|
|
delete (C) getMultipleDC();
|
|
|
|
|
2008-06-08 00:52:53 +08:00
|
|
|
this->~Decl();
|
2009-01-28 05:25:57 +08:00
|
|
|
C.Deallocate((void *)this);
|
2009-12-01 08:07:10 +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-06-30 10:35:26 +08:00
|
|
|
CompoundStmt* Decl::getCompoundBody() const {
|
|
|
|
return dyn_cast_or_null<CompoundStmt>(getBody());
|
2009-04-27 04:35:05 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:35:26 +08:00
|
|
|
SourceLocation Decl::getBodyRBrace() const {
|
|
|
|
Stmt *Body = getBody();
|
2009-04-27 04:35:05 +08:00
|
|
|
if (!Body)
|
|
|
|
return SourceLocation();
|
|
|
|
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
|
|
|
|
return CS->getRBracLoc();
|
|
|
|
assert(isa<CXXTryStmt>(Body) &&
|
|
|
|
"Body can only be CompoundStmt or CXXTryStmt");
|
|
|
|
return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
|
|
|
|
}
|
|
|
|
|
2009-03-26 07:38:06 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
void Decl::CheckAccessDeclContext() const {
|
2010-01-21 05:53:11 +08:00
|
|
|
// Suppress this check if any of the following hold:
|
|
|
|
// 1. this is the translation unit (and thus has no parent)
|
|
|
|
// 2. this is a template parameter (and thus doesn't belong to its context)
|
|
|
|
// 3. this is a ParmVarDecl (which can be in a record context during
|
|
|
|
// the brief period between its creation and the creation of the
|
|
|
|
// FunctionDecl)
|
|
|
|
// 4. the context is not a record
|
2009-08-30 04:47:47 +08:00
|
|
|
if (isa<TranslationUnitDecl>(this) ||
|
|
|
|
!isa<CXXRecordDecl>(getDeclContext()))
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
assert(Access != AS_none &&
|
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-06-30 10:36:12 +08:00
|
|
|
for (decl_iterator D = decls_begin(); D != decls_end(); )
|
2009-01-20 12:25:11 +08:00
|
|
|
(*D++)->Destroy(C);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-11 00:57:35 +08:00
|
|
|
/// \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();
|
|
|
|
}
|
|
|
|
|
2009-05-29 00:34:51 +08:00
|
|
|
bool DeclContext::isDependentContext() const {
|
|
|
|
if (isFileContext())
|
|
|
|
return false;
|
2009-05-31 17:31:02 +08:00
|
|
|
|
|
|
|
if (isa<ClassTemplatePartialSpecializationDecl>(this))
|
|
|
|
return true;
|
2009-05-29 00:34:51 +08:00
|
|
|
|
|
|
|
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
|
|
|
|
if (Record->getDescribedClassTemplate())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this))
|
|
|
|
if (Function->getDescribedFunctionTemplate())
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-29 00:34:51 +08:00
|
|
|
return getParent() && getParent()->isDependentContext();
|
|
|
|
}
|
|
|
|
|
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-08-27 14:03:53 +08:00
|
|
|
bool DeclContext::Encloses(DeclContext *DC) {
|
|
|
|
if (getPrimaryContext() != this)
|
|
|
|
return getPrimaryContext()->Encloses(DC);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-27 14:03:53 +08:00
|
|
|
for (; DC; DC = DC->getParent())
|
|
|
|
if (DC->getPrimaryContext() == this)
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
return false;
|
2009-08-27 14:03:53 +08:00
|
|
|
}
|
|
|
|
|
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:
|
2009-09-09 23:08:12 +08:00
|
|
|
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-07-30 05:53:49 +08:00
|
|
|
if (const TagType *TagT =cast<TagDecl>(this)->TypeForDecl->getAs<TagType>())
|
2009-09-09 23:08:12 +08:00
|
|
|
if (TagT->isBeingDefined() ||
|
2009-02-18 07:15:12 +08:00
|
|
|
(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.
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
|
|
|
|
ExternalASTSource *Source = getParentASTContext().getExternalSource();
|
2009-04-10 06:27:44 +08:00
|
|
|
assert(hasExternalLexicalStorage() && Source && "No external storage?");
|
|
|
|
|
2009-04-28 07:43:36 +08:00
|
|
|
llvm::SmallVector<uint32_t, 64> Decls;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
|
2009-04-10 06:27:44 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::LoadVisibleDeclsFromExternalStorage() const {
|
2009-04-10 06:27:44 +08:00
|
|
|
DeclContext *This = const_cast<DeclContext *>(this);
|
2009-06-30 10:36:12 +08:00
|
|
|
ExternalASTSource *Source = getParentASTContext().getExternalSource();
|
2009-04-10 06:27:44 +08:00
|
|
|
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-06-30 10:36:12 +08:00
|
|
|
DeclContext::decl_iterator DeclContext::decls_begin() const {
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalLexicalStorage())
|
2009-06-30 10:36:12 +08:00
|
|
|
LoadLexicalDeclsFromExternalStorage();
|
2009-04-10 06:27:44 +08:00
|
|
|
|
|
|
|
// FIXME: Check whether we need to load some declarations from
|
|
|
|
// external storage.
|
2009-09-09 23:08:12 +08:00
|
|
|
return decl_iterator(FirstDecl);
|
2009-04-10 05:40:53 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::decl_iterator DeclContext::decls_end() const {
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalLexicalStorage())
|
2009-06-30 10:36:12 +08:00
|
|
|
LoadLexicalDeclsFromExternalStorage();
|
2009-04-10 06:27:44 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
return decl_iterator();
|
2009-04-10 05:40:53 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
bool DeclContext::decls_empty() const {
|
2009-04-11 01:25:41 +08:00
|
|
|
if (hasExternalLexicalStorage())
|
2009-06-30 10:36:12 +08:00
|
|
|
LoadLexicalDeclsFromExternalStorage();
|
2009-04-11 01:25:41 +08:00
|
|
|
|
|
|
|
return !FirstDecl;
|
|
|
|
}
|
|
|
|
|
2009-12-10 17:41:52 +08:00
|
|
|
void DeclContext::removeDecl(Decl *D) {
|
|
|
|
assert(D->getLexicalDeclContext() == this &&
|
|
|
|
"decl being removed from non-lexical context");
|
|
|
|
assert((D->NextDeclInContext || D == LastDecl) &&
|
|
|
|
"decl is not in decls list");
|
|
|
|
|
|
|
|
// Remove D from the decl chain. This is O(n) but hopefully rare.
|
|
|
|
if (D == FirstDecl) {
|
|
|
|
if (D == LastDecl)
|
|
|
|
FirstDecl = LastDecl = 0;
|
|
|
|
else
|
|
|
|
FirstDecl = D->NextDeclInContext;
|
|
|
|
} else {
|
|
|
|
for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
|
|
|
|
assert(I && "decl not found in linked list");
|
|
|
|
if (I->NextDeclInContext == D) {
|
|
|
|
I->NextDeclInContext = D->NextDeclInContext;
|
|
|
|
if (D == LastDecl) LastDecl = I;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark that D is no longer in the decl chain.
|
|
|
|
D->NextDeclInContext = 0;
|
|
|
|
|
|
|
|
// Remove D from the lookup table if necessary.
|
|
|
|
if (isa<NamedDecl>(D)) {
|
|
|
|
NamedDecl *ND = cast<NamedDecl>(D);
|
|
|
|
|
|
|
|
void *OpaqueMap = getPrimaryContext()->LookupPtr;
|
|
|
|
if (!OpaqueMap) return;
|
|
|
|
|
|
|
|
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap);
|
|
|
|
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
|
|
|
|
assert(Pos != Map->end() && "no lookup entry for decl");
|
|
|
|
Pos->second.remove(ND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-11 14:59:38 +08:00
|
|
|
void DeclContext::addHiddenDecl(Decl *D) {
|
2009-02-20 08:56:18 +08:00
|
|
|
assert(D->getLexicalDeclContext() == this &&
|
|
|
|
"Decl inserted into wrong lexical context");
|
2009-09-09 23:08:12 +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-08-11 14:59:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclContext::addDecl(Decl *D) {
|
|
|
|
addHiddenDecl(D);
|
2009-01-20 09:17:11 +08:00
|
|
|
|
|
|
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
2009-06-30 10:36:12 +08:00
|
|
|
ND->getDeclContext()->makeDeclVisibleInContext(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-06-30 10:36:12 +08:00
|
|
|
void DeclContext::buildLookup(DeclContext *DCtx) {
|
2009-01-06 03:45:36 +08:00
|
|
|
for (; DCtx; DCtx = DCtx->getNextContext()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
for (decl_iterator D = DCtx->decls_begin(),
|
|
|
|
DEnd = DCtx->decls_end();
|
2009-01-06 15:17:58 +08:00
|
|
|
D != DEnd; ++D) {
|
2009-08-11 14:59:38 +08:00
|
|
|
// 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.
|
2009-01-20 09:17:11 +08:00
|
|
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
|
2009-08-11 14:59:38 +08:00
|
|
|
if (D->getDeclContext() == DCtx)
|
|
|
|
makeDeclVisibleInContextImpl(ND);
|
2009-01-06 03:45:36 +08:00
|
|
|
|
2009-11-18 06:58:30 +08:00
|
|
|
// Insert any forward-declared Objective-C interfaces into the lookup
|
|
|
|
// data structure.
|
|
|
|
if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
|
|
|
|
for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
|
|
|
|
I != IEnd; ++I)
|
2009-11-18 08:28:11 +08:00
|
|
|
makeDeclVisibleInContextImpl(I->getInterface());
|
2009-11-18 06:58:30 +08:00
|
|
|
|
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-06-30 10:36:12 +08:00
|
|
|
buildLookup(InnerCtx->getPrimaryContext());
|
2009-01-06 03:45:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclContext::lookup_result
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::lookup(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-06-30 10:36:12 +08:00
|
|
|
return PrimaryContext->lookup(Name);
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-04-10 06:27:44 +08:00
|
|
|
if (hasExternalVisibleStorage())
|
2009-06-30 10:36:12 +08:00
|
|
|
LoadVisibleDeclsFromExternalStorage();
|
2009-04-10 06:27:44 +08:00
|
|
|
|
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-06-30 10:36:12 +08:00
|
|
|
buildLookup(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-06-30 10:36:12 +08:00
|
|
|
return Pos->second.getLookupResult(getParentASTContext());
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclContext::lookup_const_result
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::lookup(DeclarationName Name) const {
|
|
|
|
return const_cast<DeclContext*>(this)->lookup(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-09-01 06:39:49 +08:00
|
|
|
void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
|
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-12-08 13:40:03 +08:00
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
|
|
|
if (FD->isFunctionTemplateSpecialization())
|
|
|
|
return;
|
2009-02-18 07:15:12 +08:00
|
|
|
|
2009-01-09 01:28:14 +08:00
|
|
|
DeclContext *PrimaryContext = getPrimaryContext();
|
2008-12-12 00:49:14 +08:00
|
|
|
if (PrimaryContext != this) {
|
2009-09-01 06:39:49 +08:00
|
|
|
PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
|
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-09-01 06:39:49 +08:00
|
|
|
if (LookupPtr || !Recoverable)
|
2009-06-30 10:36:12 +08:00
|
|
|
makeDeclVisibleInContextImpl(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-09-01 06:39:49 +08:00
|
|
|
getParent()->makeDeclVisibleInContext(D, Recoverable);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
void DeclContext::makeDeclVisibleInContextImpl(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-06-30 10:36:12 +08:00
|
|
|
if (DeclNameEntries.HandleRedeclaration(getParentASTContext(), D))
|
2009-02-20 09:44:05 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +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-09-09 23:08:12 +08:00
|
|
|
DeclContext::udir_iterator_range
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::getUsingDirectives() const {
|
|
|
|
lookup_const_result Result = lookup(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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|