//===--- ASTLocation.h - A pair --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // ASTLocation is Decl or a Stmt and its immediate Decl parent. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_INDEX_ASTLOCATION_H #define LLVM_CLANG_INDEX_ASTLOCATION_H #include "clang/AST/TypeLoc.h" #include "llvm/ADT/PointerIntPair.h" namespace llvm { class raw_ostream; } namespace clang { class Decl; class Stmt; class NamedDecl; namespace idx { class TranslationUnit; /// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's /// immutable. /// /// ASTLocation is intended to be used as a "pointer" into the AST. It is either /// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid /// of context, its parent Decl provides all the additional missing information /// like the declaration context, ASTContext, etc. /// class ASTLocation { public: enum NodeKind { N_Decl, N_NamedRef, N_Stmt, N_Type }; struct NamedRef { NamedDecl *ND; SourceLocation Loc; NamedRef() : ND(0) { } NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { } }; private: llvm::PointerIntPair ParentDecl; union { Decl *D; Stmt *Stm; struct { NamedDecl *ND; unsigned RawLoc; } NDRef; struct { void *TyPtr; void *Data; } Ty; }; public: ASTLocation() { } explicit ASTLocation(const Decl *d) : ParentDecl(const_cast(d), N_Decl), D(const_cast(d)) { } ASTLocation(const Decl *parentDecl, const Stmt *stm) : ParentDecl(const_cast(parentDecl), N_Stmt), Stm(const_cast(stm)) { if (!stm) ParentDecl.setPointer(0); } ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc) : ParentDecl(const_cast(parentDecl), N_NamedRef) { if (ndRef) { NDRef.ND = ndRef; NDRef.RawLoc = loc.getRawEncoding(); } else ParentDecl.setPointer(0); } ASTLocation(const Decl *parentDecl, TypeLoc tyLoc) : ParentDecl(const_cast(parentDecl), N_Type) { if (tyLoc) { Ty.TyPtr = tyLoc.getType().getAsOpaquePtr(); Ty.Data = tyLoc.getOpaqueData(); } else ParentDecl.setPointer(0); } bool isValid() const { return ParentDecl.getPointer() != 0; } bool isInvalid() const { return !isValid(); } NodeKind getKind() const { assert(isValid()); return (NodeKind)ParentDecl.getInt(); } Decl *getParentDecl() const { return ParentDecl.getPointer(); } Decl *AsDecl() const { assert(getKind() == N_Decl); return D; } Stmt *AsStmt() const { assert(getKind() == N_Stmt); return Stm; } NamedRef AsNamedRef() const { assert(getKind() == N_NamedRef); return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc)); } TypeLoc AsTypeLoc() const { assert(getKind() == N_Type); return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data); } Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; } NamedRef dyn_AsNamedRef() const { return getKind() == N_Type ? AsNamedRef() : NamedRef(); } TypeLoc dyn_AsTypeLoc() const { return getKind() == N_Type ? AsTypeLoc() : TypeLoc(); } bool isDecl() const { return isValid() && getKind() == N_Decl; } bool isStmt() const { return isValid() && getKind() == N_Stmt; } bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; } bool isType() const { return isValid() && getKind() == N_Type; } /// \brief Returns the declaration that this ASTLocation references. /// /// If this points to a Decl, that Decl is returned. /// If this points to an Expr that references a Decl, that Decl is returned, /// otherwise it returns NULL. Decl *getReferencedDecl(); const Decl *getReferencedDecl() const { return const_cast(this)->getReferencedDecl(); } SourceRange getSourceRange() const; void print(llvm::raw_ostream &OS) const; }; /// \brief Like ASTLocation but also contains the TranslationUnit that the /// ASTLocation originated from. class TULocation : public ASTLocation { TranslationUnit *TU; public: TULocation(TranslationUnit *tu, ASTLocation astLoc) : ASTLocation(astLoc), TU(tu) { assert(tu && "Passed null translation unit"); } TranslationUnit *getTU() const { return TU; } }; } // namespace idx } // namespace clang #endif