| //===--- ASTLocation.h - A <Decl, Stmt> 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<Decl *, 2, NodeKind> 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<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { } |
| |
| ASTLocation(const Decl *parentDecl, const Stmt *stm) |
| : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt), |
| Stm(const_cast<Stmt*>(stm)) { |
| if (!stm) ParentDecl.setPointer(0); |
| } |
| |
| ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc) |
| : ParentDecl(const_cast<Decl*>(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<Decl*>(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<ASTLocation*>(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 |