#ifndef LLVM_CLANG_AST_DECLBASE_H
#define LLVM_CLANG_AST_DECLBASE_H
#include "clang/AST/Attr.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
namespace clang {
class DeclContext;
class TranslationUnitDecl;
class NamespaceDecl;
class UsingDirectiveDecl;
class NamedDecl;
class FunctionDecl;
class CXXRecordDecl;
class EnumDecl;
class ObjCMethodDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCCategoryDecl;
class ObjCProtocolDecl;
class ObjCImplementationDecl;
class ObjCCategoryImplDecl;
class ObjCImplDecl;
class LinkageSpecDecl;
class BlockDecl;
class DeclarationName;
class CompoundStmt;
class StoredDeclsMap;
class DependentDiagnostic;
class ASTMutationListener;
}
namespace llvm {
template<>
class PointerLikeTypeTraits<clang::DeclContext*> {
typedef clang::DeclContext* PT;
public:
static inline void *getAsVoidPointer(PT P) { return P; }
static inline PT getFromVoidPointer(void *P) {
return static_cast<PT>(P);
}
enum { NumLowBitsAvailable = 2 };
};
}
namespace clang {
enum AvailabilityResult {
AR_Available = 0,
AR_NotYetIntroduced,
AR_Deprecated,
AR_Unavailable
};
class Decl {
public:
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
#define ABSTRACT_DECL(DECL)
#define DECL_RANGE(BASE, START, END) \
first##BASE = START, last##BASE = END,
#define LAST_DECL_RANGE(BASE, START, END) \
first##BASE = START, last##BASE = END
#include "clang/AST/DeclNodes.inc"
};
struct EmptyShell { };
enum IdentifierNamespace {
IDNS_Label = 0x0001,
IDNS_Tag = 0x0002,
IDNS_Type = 0x0004,
IDNS_Member = 0x0008,
IDNS_Namespace = 0x0010,
IDNS_Ordinary = 0x0020,
IDNS_ObjCProtocol = 0x0040,
IDNS_OrdinaryFriend = 0x0080,
IDNS_TagFriend = 0x0100,
IDNS_Using = 0x0200,
IDNS_NonMemberOperator = 0x0400
};
enum ObjCDeclQualifier {
OBJC_TQ_None = 0x0,
OBJC_TQ_In = 0x1,
OBJC_TQ_Inout = 0x2,
OBJC_TQ_Out = 0x4,
OBJC_TQ_Bycopy = 0x8,
OBJC_TQ_Byref = 0x10,
OBJC_TQ_Oneway = 0x20
};
protected:
enum {
TopLevelDeclInObjCContainerFlag = 0x01,
ModulePrivateFlag = 0x02
};
llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
private:
friend class DeclContext;
struct MultipleDC {
DeclContext *SemanticDC;
DeclContext *LexicalDC;
};
llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
inline MultipleDC *getMultipleDC() const {
return DeclCtx.get<MultipleDC*>();
}
inline DeclContext *getSemanticDC() const {
return DeclCtx.get<DeclContext*>();
}
SourceLocation Loc;
unsigned DeclKind : 8;
unsigned InvalidDecl : 1;
unsigned HasAttrs : 1;
unsigned Implicit : 1;
unsigned Used : 1;
unsigned Referenced : 1;
static bool StatisticsEnabled;
protected:
unsigned Access : 2;
friend class CXXClassMemberWrapper;
unsigned FromASTFile : 1;
unsigned Hidden : 1;
unsigned IdentifierNamespace : 12;
mutable unsigned HasCachedLinkage : 1;
mutable unsigned CachedLinkage : 2;
friend class ASTDeclWriter;
friend class ASTDeclReader;
friend class ASTReader;
private:
void CheckAccessDeclContext() const;
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
Decl(Kind DK, EmptyShell Empty)
: NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
virtual ~Decl();
static void *AllocateDeserializedDecl(const ASTContext &Context,
unsigned ID,
unsigned Size);
public:
virtual SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocation(), getLocation());
}
SourceLocation getLocStart() const LLVM_READONLY {
return getSourceRange().getBegin();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getSourceRange().getEnd();
}
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
Kind getKind() const { return static_cast<Kind>(DeclKind); }
const char *getDeclKindName() const;
Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); }
const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();}
DeclContext *getDeclContext() {
if (isInSemaDC())
return getSemanticDC();
return getMultipleDC()->SemanticDC;
}
const DeclContext *getDeclContext() const {
return const_cast<Decl*>(this)->getDeclContext();
}
DeclContext *getNonClosureContext();
const DeclContext *getNonClosureContext() const {
return const_cast<Decl*>(this)->getNonClosureContext();
}
TranslationUnitDecl *getTranslationUnitDecl();
const TranslationUnitDecl *getTranslationUnitDecl() const {
return const_cast<Decl*>(this)->getTranslationUnitDecl();
}
bool isInAnonymousNamespace() const;
ASTContext &getASTContext() const LLVM_READONLY;
void setAccess(AccessSpecifier AS) {
Access = AS;
#ifndef NDEBUG
CheckAccessDeclContext();
#endif
}
AccessSpecifier getAccess() const {
#ifndef NDEBUG
CheckAccessDeclContext();
#endif
return AccessSpecifier(Access);
}
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs) {
return setAttrsImpl(Attrs, getASTContext());
}
AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
void swapAttrs(Decl *D);
void dropAttrs();
void addAttr(Attr *A) {
if (hasAttrs())
getAttrs().push_back(A);
else
setAttrs(AttrVec(1, A));
}
typedef AttrVec::const_iterator attr_iterator;
attr_iterator attr_begin() const {
return hasAttrs() ? getAttrs().begin() : 0;
}
attr_iterator attr_end() const {
return hasAttrs() ? getAttrs().end() : 0;
}
template <typename T>
void dropAttr() {
if (!HasAttrs) return;
AttrVec &Attrs = getAttrs();
for (unsigned i = 0, e = Attrs.size(); i != e; ) {
if (isa<T>(Attrs[i])) {
Attrs.erase(Attrs.begin() + i);
--e;
}
else
++i;
}
if (Attrs.empty())
HasAttrs = false;
}
template <typename T>
specific_attr_iterator<T> specific_attr_begin() const {
return specific_attr_iterator<T>(attr_begin());
}
template <typename T>
specific_attr_iterator<T> specific_attr_end() const {
return specific_attr_iterator<T>(attr_end());
}
template<typename T> T *getAttr() const {
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
}
template<typename T> bool hasAttr() const {
return hasAttrs() && hasSpecificAttr<T>(getAttrs());
}
unsigned getMaxAlignment() const {
return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
}
void setInvalidDecl(bool Invalid = true);
bool isInvalidDecl() const { return (bool) InvalidDecl; }
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
bool isUsed(bool CheckUsedAttr = true) const;
void setUsed(bool U = true) { Used = U; }
bool isReferenced() const;
void setReferenced(bool R = true) { Referenced = R; }
bool isTopLevelDeclInObjCContainer() const {
return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
}
void setTopLevelDeclInObjCContainer(bool V = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (V)
Bits |= TopLevelDeclInObjCContainerFlag;
else
Bits &= ~TopLevelDeclInObjCContainerFlag;
NextInContextAndBits.setInt(Bits);
}
protected:
bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
}
void setModulePrivate(bool MP = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (MP)
Bits |= ModulePrivateFlag;
else
Bits &= ~ModulePrivateFlag;
NextInContextAndBits.setInt(Bits);
}
void setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
*((unsigned*)this - 2) = ID;
}
public:
AvailabilityResult getAvailability(std::string *Message = 0) const;
bool isDeprecated(std::string *Message = 0) const {
return getAvailability(Message) == AR_Deprecated;
}
bool isUnavailable(std::string *Message = 0) const {
return getAvailability(Message) == AR_Unavailable;
}
bool isWeakImported() const;
bool canBeWeakImported(bool &IsDefinition) const;
bool isFromASTFile() const { return FromASTFile; }
unsigned getGlobalID() const {
if (isFromASTFile())
return *((const unsigned*)this - 1);
return 0;
}
unsigned getOwningModuleID() const {
if (isFromASTFile())
return *((const unsigned*)this - 2);
return 0;
}
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
bool isInIdentifierNamespace(unsigned NS) const {
return getIdentifierNamespace() & NS;
}
static unsigned getIdentifierNamespaceForKind(Kind DK);
bool hasTagIdentifierNamespace() const {
return isTagIdentifierNamespace(getIdentifierNamespace());
}
static bool isTagIdentifierNamespace(unsigned NS) {
return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type);
}
DeclContext *getLexicalDeclContext() {
if (isInSemaDC())
return getSemanticDC();
return getMultipleDC()->LexicalDC;
}
const DeclContext *getLexicalDeclContext() const {
return const_cast<Decl*>(this)->getLexicalDeclContext();
}
virtual bool isOutOfLine() const {
return getLexicalDeclContext() != getDeclContext();
}
void setDeclContext(DeclContext *DC);
void setLexicalDeclContext(DeclContext *DC);
bool isDefinedOutsideFunctionOrMethod() const {
return getParentFunctionOrMethod() == 0;
}
const DeclContext *getParentFunctionOrMethod() const;
DeclContext *getParentFunctionOrMethod() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
}
virtual Decl *getCanonicalDecl() { return this; }
const Decl *getCanonicalDecl() const {
return const_cast<Decl*>(this)->getCanonicalDecl();
}
bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
protected:
virtual Decl *getNextRedeclaration() { return this; }
virtual Decl *getPreviousDeclImpl() { return 0; }
virtual Decl *getMostRecentDeclImpl() { return this; }
public:
class redecl_iterator {
Decl *Current;
Decl *Starter;
public:
typedef Decl *value_type;
typedef const value_type &reference;
typedef const value_type *pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
redecl_iterator() : Current(0) { }
explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
reference operator*() const { return Current; }
value_type operator->() const { return Current; }
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
Decl *Next = Current->getNextRedeclaration();
assert(Next && "Should return next redeclaration or itself, never null!");
Current = (Next != Starter ? Next : 0);
return *this;
}
redecl_iterator operator++(int) {
redecl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(redecl_iterator x, redecl_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
return x.Current != y.Current;
}
};
redecl_iterator redecls_begin() const {
return redecl_iterator(const_cast<Decl*>(this));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
const Decl *getPreviousDecl() const {
return const_cast<Decl *>(this)->getPreviousDeclImpl();
}
Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); }
const Decl *getMostRecentDecl() const {
return const_cast<Decl *>(this)->getMostRecentDeclImpl();
}
virtual Stmt* getBody() const { return 0; }
virtual bool hasBody() const { return getBody() != 0; }
SourceLocation getBodyRBrace() const;
static void add(Kind k);
static void EnableStatistics();
static void PrintStats();
bool isTemplateParameter() const;
bool isTemplateParameterPack() const;
bool isParameterPack() const;
bool isTemplateDecl() const;
bool isFunctionOrFunctionTemplate() const;
void setObjectOfFriendDecl(bool PreviouslyDeclared) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes other than ordinary or tag");
IdentifierNamespace = 0;
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
IdentifierNamespace |= IDNS_TagFriend;
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
}
}
enum FriendObjectKind {
FOK_None, FOK_Declared, FOK_Undeclared };
FriendObjectKind getFriendObjectKind() const {
unsigned mask
= (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
if (!mask) return FOK_None;
return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ?
FOK_Declared : FOK_Undeclared);
}
void setNonMemberOperator() {
assert(getKind() == Function || getKind() == FunctionTemplate);
assert((IdentifierNamespace & IDNS_Ordinary) &&
"visible non-member operators should be in ordinary namespace");
IdentifierNamespace |= IDNS_NonMemberOperator;
}
static bool classof(const Decl *) { return true; }
static bool classofKind(Kind K) { return true; }
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
void print(raw_ostream &Out, unsigned Indentation = 0,
bool PrintInstantiation = false) const;
void print(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false) const;
static void printGroup(Decl** Begin, unsigned NumDecls,
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
LLVM_ATTRIBUTE_USED void dump() const;
void dump(raw_ostream &Out) const;
LLVM_ATTRIBUTE_USED void dumpXML() const;
void dumpXML(raw_ostream &OS) const;
private:
void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
ASTContext &Ctx);
protected:
ASTMutationListener *getASTMutationListener() const;
};
inline bool declaresSameEntity(const Decl *D1, const Decl *D2) {
if (!D1 || !D2)
return false;
if (D1 == D2)
return true;
return D1->getCanonicalDecl() == D2->getCanonicalDecl();
}
class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
const Decl *TheDecl;
SourceLocation Loc;
SourceManager &SM;
const char *Message;
public:
PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L,
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
virtual void print(raw_ostream &OS) const;
};
class DeclContextLookupResult
: public std::pair<NamedDecl**,NamedDecl**> {
public:
DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
: std::pair<NamedDecl**,NamedDecl**>(I, E) {}
DeclContextLookupResult()
: std::pair<NamedDecl**,NamedDecl**>() {}
using std::pair<NamedDecl**,NamedDecl**>::operator=;
};
class DeclContextLookupConstResult
: public std::pair<NamedDecl*const*, NamedDecl*const*> {
public:
DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
: std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
: std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
DeclContextLookupConstResult()
: std::pair<NamedDecl*const*, NamedDecl*const*>() {}
using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
};
class DeclContext {
unsigned DeclKind : 8;
mutable unsigned ExternalLexicalStorage : 1;
mutable unsigned ExternalVisibleStorage : 1;
mutable llvm::PointerIntPair<StoredDeclsMap*, 1, bool> LookupPtr;
protected:
mutable Decl *FirstDecl;
mutable Decl *LastDecl;
friend class ExternalASTSource;
friend class ASTWriter;
static std::pair<Decl *, Decl *>
BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false), LookupPtr(0, false), FirstDecl(0),
LastDecl(0) { }
public:
~DeclContext();
Decl::Kind getDeclKind() const {
return static_cast<Decl::Kind>(DeclKind);
}
const char *getDeclKindName() const;
DeclContext *getParent() {
return cast<Decl>(this)->getDeclContext();
}
const DeclContext *getParent() const {
return const_cast<DeclContext*>(this)->getParent();
}
DeclContext *getLexicalParent() {
return cast<Decl>(this)->getLexicalDeclContext();
}
const DeclContext *getLexicalParent() const {
return const_cast<DeclContext*>(this)->getLexicalParent();
}
DeclContext *getLookupParent();
const DeclContext *getLookupParent() const {
return const_cast<DeclContext*>(this)->getLookupParent();
}
ASTContext &getParentASTContext() const {
return cast<Decl>(this)->getASTContext();
}
bool isClosure() const {
return DeclKind == Decl::Block;
}
bool isObjCContainer() const {
switch (DeclKind) {
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCProtocol:
return true;
}
return false;
}
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
case Decl::ObjCMethod:
return true;
default:
return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
}
}
bool isFileContext() const {
return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
}
bool isTranslationUnit() const {
return DeclKind == Decl::TranslationUnit;
}
bool isRecord() const {
return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
}
bool isNamespace() const {
return DeclKind == Decl::Namespace;
}
bool isInlineNamespace() const;
bool isDependentContext() const;
bool isTransparentContext() const;
bool isExternCContext() const;
bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
bool Encloses(const DeclContext *DC) const;
DeclContext *getNonClosureAncestor();
const DeclContext *getNonClosureAncestor() const {
return const_cast<DeclContext*>(this)->getNonClosureAncestor();
}
DeclContext *getPrimaryContext();
const DeclContext *getPrimaryContext() const {
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
DeclContext *getRedeclContext();
const DeclContext *getRedeclContext() const {
return const_cast<DeclContext *>(this)->getRedeclContext();
}
DeclContext *getEnclosingNamespaceContext();
const DeclContext *getEnclosingNamespaceContext() const {
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
void collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts);
class decl_iterator {
Decl *Current;
public:
typedef Decl *value_type;
typedef const value_type &reference;
typedef const value_type *pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
decl_iterator() : Current(0) { }
explicit decl_iterator(Decl *C) : Current(C) { }
reference operator*() const { return Current; }
value_type operator->() const { return Current; }
decl_iterator& operator++() {
Current = Current->getNextDeclInContext();
return *this;
}
decl_iterator operator++(int) {
decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(decl_iterator x, decl_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(decl_iterator x, decl_iterator y) {
return x.Current != y.Current;
}
};
decl_iterator decls_begin() const;
decl_iterator decls_end() const { return decl_iterator(); }
bool decls_empty() const;
decl_iterator noload_decls_begin() const;
decl_iterator noload_decls_end() const { return decl_iterator(); }
template<typename SpecificDecl>
class specific_decl_iterator {
DeclContext::decl_iterator Current;
void SkipToNextDecl() {
while (*Current && !isa<SpecificDecl>(*Current))
++Current;
}
public:
typedef SpecificDecl *value_type;
typedef void reference;
typedef void pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
specific_decl_iterator() : Current() { }
explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
SkipToNextDecl();
}
value_type operator*() const { return cast<SpecificDecl>(*Current); }
value_type operator->() const { return **this; }
specific_decl_iterator& operator++() {
++Current;
SkipToNextDecl();
return *this;
}
specific_decl_iterator operator++(int) {
specific_decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(const specific_decl_iterator& x,
const specific_decl_iterator& y) {
return x.Current == y.Current;
}
friend bool operator!=(const specific_decl_iterator& x,
const specific_decl_iterator& y) {
return x.Current != y.Current;
}
};
template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const>
class filtered_decl_iterator {
DeclContext::decl_iterator Current;
void SkipToNextDecl() {
while (*Current &&
(!isa<SpecificDecl>(*Current) ||
(Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
++Current;
}
public:
typedef SpecificDecl *value_type;
typedef void reference;
typedef void pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
filtered_decl_iterator() : Current() { }
explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
SkipToNextDecl();
}
value_type operator*() const { return cast<SpecificDecl>(*Current); }
value_type operator->() const { return cast<SpecificDecl>(*Current); }
filtered_decl_iterator& operator++() {
++Current;
SkipToNextDecl();
return *this;
}
filtered_decl_iterator operator++(int) {
filtered_decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(const filtered_decl_iterator& x,
const filtered_decl_iterator& y) {
return x.Current == y.Current;
}
friend bool operator!=(const filtered_decl_iterator& x,
const filtered_decl_iterator& y) {
return x.Current != y.Current;
}
};
void addDecl(Decl *D);
void addDeclInternal(Decl *D);
void addHiddenDecl(Decl *D);
void removeDecl(Decl *D);
typedef NamedDecl **lookup_iterator;
typedef NamedDecl * const * lookup_const_iterator;
typedef DeclContextLookupResult lookup_result;
typedef DeclContextLookupConstResult lookup_const_result;
lookup_result lookup(DeclarationName Name);
lookup_const_result lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
void localUncachedLookup(DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl *> &Results);
void makeDeclVisibleInContext(NamedDecl *D);
class all_lookups_iterator;
all_lookups_iterator lookups_begin() const;
all_lookups_iterator lookups_end() const;
typedef UsingDirectiveDecl * const * udir_iterator;
typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
udir_iterator_range getUsingDirectives() const;
udir_iterator using_directives_begin() const {
return getUsingDirectives().first;
}
udir_iterator using_directives_end() const {
return getUsingDirectives().second;
}
class ddiag_iterator;
inline ddiag_iterator ddiag_begin() const;
inline ddiag_iterator ddiag_end() const;
void setMustBuildLookupTable() {
assert(ExternalLexicalStorage && "Requires external lexical storage");
LookupPtr.setInt(true);
}
StoredDeclsMap *getLookupPtr() const { return LookupPtr.getPointer(); }
StoredDeclsMap *buildLookup();
bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
void setHasExternalLexicalStorage(bool ES = true) {
ExternalLexicalStorage = ES;
}
bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
void setHasExternalVisibleStorage(bool ES = true) {
ExternalVisibleStorage = ES;
}
bool isDeclInLexicalTraversal(const Decl *D) const {
return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
D == LastDecl);
}
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
#define DECL(NAME, BASE)
#define DECL_CONTEXT(NAME) \
static bool classof(const NAME##Decl *D) { return true; }
#include "clang/AST/DeclNodes.inc"
LLVM_ATTRIBUTE_USED void dumpDeclContext() const;
private:
void LoadLexicalDeclsFromExternalStorage() const;
void makeDeclVisibleInContextInternal(NamedDecl *D);
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
void buildLookupImpl(DeclContext *DCtx);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal);
};
inline bool Decl::isTemplateParameter() const {
return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm ||
getKind() == TemplateTemplateParm;
}
template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
struct cast_convert_decl_context {
static const ToTy *doit(const DeclContext *Val) {
return static_cast<const ToTy*>(Decl::castFromDeclContext(Val));
}
static ToTy *doit(DeclContext *Val) {
return static_cast<ToTy*>(Decl::castFromDeclContext(Val));
}
};
template <class ToTy>
struct cast_convert_decl_context<ToTy, true> {
static const ToTy *doit(const DeclContext *Val) {
return static_cast<const ToTy*>(Val);
}
static ToTy *doit(DeclContext *Val) {
return static_cast<ToTy*>(Val);
}
};
}
namespace llvm {
template <typename To>
struct isa_impl<To, ::clang::DeclContext> {
static bool doit(const ::clang::DeclContext &Val) {
return To::classofKind(Val.getDeclKind());
}
};
template<class ToTy>
struct cast_convert_val<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {
static const ToTy &doit(const ::clang::DeclContext &Val) {
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
}
};
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> {
static ToTy &doit(::clang::DeclContext &Val) {
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
}
};
template<class ToTy>
struct cast_convert_val<ToTy,
const ::clang::DeclContext*, const ::clang::DeclContext*> {
static const ToTy *doit(const ::clang::DeclContext *Val) {
return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
}
};
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> {
static ToTy *doit(::clang::DeclContext *Val) {
return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> {
static ::clang::DeclContext &doit(const FromTy &Val) {
return *FromTy::castToDeclContext(&Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> {
static ::clang::DeclContext *doit(const FromTy *Val) {
return FromTy::castToDeclContext(Val);
}
};
template<class FromTy>
struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
static const ::clang::DeclContext &doit(const FromTy &Val) {
return *FromTy::castToDeclContext(&Val);
}
};
template<class FromTy>
struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
static const ::clang::DeclContext *doit(const FromTy *Val) {
return FromTy::castToDeclContext(Val);
}
};
}
#endif