clang API Documentation

ASTLocation.h
Go to the documentation of this file.
00001 //===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  ASTLocation is Decl or a Stmt and its immediate Decl parent.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_INDEX_ASTLOCATION_H
00015 #define LLVM_CLANG_INDEX_ASTLOCATION_H
00016 
00017 #include "clang/AST/TypeLoc.h"
00018 #include "llvm/ADT/PointerIntPair.h"
00019 #include "llvm/Support/Compiler.h"
00020 
00021 namespace clang {
00022   class Decl;
00023   class Stmt;
00024   class NamedDecl;
00025 
00026 namespace idx {
00027   class TranslationUnit;
00028 
00029 /// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's
00030 /// immutable.
00031 ///
00032 /// ASTLocation is intended to be used as a "pointer" into the AST. It is either
00033 /// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid
00034 /// of context, its parent Decl provides all the additional missing information
00035 /// like the declaration context, ASTContext, etc.
00036 ///
00037 class ASTLocation {
00038 public:
00039   enum NodeKind {
00040     N_Decl, N_NamedRef, N_Stmt, N_Type
00041   };
00042 
00043   struct NamedRef {
00044     NamedDecl *ND;
00045     SourceLocation Loc;
00046 
00047     NamedRef() : ND(0) { }
00048     NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { }
00049   };
00050 
00051 private:
00052   llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl;
00053 
00054   union {
00055     Decl *D;
00056     Stmt *Stm;
00057     struct {
00058       NamedDecl *ND;
00059       unsigned RawLoc;
00060     } NDRef;
00061     struct {
00062       void *TyPtr;
00063       void *Data;
00064     } Ty;
00065   };
00066 
00067 public:
00068   ASTLocation() { }
00069 
00070   explicit ASTLocation(const Decl *d)
00071     : ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { }
00072 
00073   ASTLocation(const Decl *parentDecl, const Stmt *stm)
00074     : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt),
00075       Stm(const_cast<Stmt*>(stm)) {
00076     if (!stm) ParentDecl.setPointer(0);
00077   }
00078 
00079   ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc)
00080     : ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) {
00081     if (ndRef) {
00082       NDRef.ND = ndRef;
00083       NDRef.RawLoc = loc.getRawEncoding();
00084     } else
00085       ParentDecl.setPointer(0);
00086   }
00087 
00088   ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)
00089     : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {
00090     if (tyLoc) {
00091       Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();
00092       Ty.Data = tyLoc.getOpaqueData();
00093     } else
00094       ParentDecl.setPointer(0);
00095   }
00096 
00097   bool isValid() const { return ParentDecl.getPointer() != 0; }
00098   bool isInvalid() const { return !isValid(); }
00099 
00100   NodeKind getKind() const {
00101     assert(isValid());
00102     return (NodeKind)ParentDecl.getInt();
00103   }
00104 
00105   Decl *getParentDecl() const { return ParentDecl.getPointer(); }
00106 
00107   Decl *AsDecl() const {
00108     assert(getKind() == N_Decl);
00109     return D;
00110   }
00111   Stmt *AsStmt() const {
00112     assert(getKind() == N_Stmt);
00113     return Stm;
00114   }
00115   NamedRef AsNamedRef() const {
00116     assert(getKind() == N_NamedRef);
00117     return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc));
00118   }
00119   TypeLoc AsTypeLoc() const {
00120     assert(getKind() == N_Type);
00121     return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);
00122   }
00123 
00124   Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; }
00125   Stmt *dyn_AsStmt() const {
00126     return isValid() && getKind() == N_Stmt ? Stm : 0;
00127   }
00128   NamedRef dyn_AsNamedRef() const {
00129     return getKind() == N_Type ? AsNamedRef() : NamedRef();
00130   }
00131   TypeLoc dyn_AsTypeLoc() const {
00132     return getKind() == N_Type ? AsTypeLoc() : TypeLoc();
00133   }
00134 
00135   bool isDecl() const { return isValid() && getKind() == N_Decl; }
00136   bool isStmt() const { return isValid() && getKind() == N_Stmt; }
00137   bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; }
00138   bool isType() const { return isValid() && getKind() == N_Type; }
00139 
00140   /// \brief Returns the declaration that this ASTLocation references.
00141   ///
00142   /// If this points to a Decl, that Decl is returned.
00143   /// If this points to an Expr that references a Decl, that Decl is returned,
00144   /// otherwise it returns NULL.
00145   Decl *getReferencedDecl();
00146   const Decl *getReferencedDecl() const {
00147     return const_cast<ASTLocation*>(this)->getReferencedDecl();
00148   }
00149 
00150   SourceRange getSourceRange() const LLVM_READONLY;
00151 
00152   void print(raw_ostream &OS) const;
00153 };
00154 
00155 /// \brief Like ASTLocation but also contains the TranslationUnit that the
00156 /// ASTLocation originated from.
00157 class TULocation : public ASTLocation {
00158   TranslationUnit *TU;
00159 
00160 public:
00161   TULocation(TranslationUnit *tu, ASTLocation astLoc)
00162     : ASTLocation(astLoc), TU(tu) {
00163     assert(tu && "Passed null translation unit");
00164   }
00165 
00166   TranslationUnit *getTU() const { return TU; }
00167 };
00168 
00169 } // namespace idx
00170 
00171 } // namespace clang
00172 
00173 #endif