1 //===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // ASTLocation is Decl or a Stmt and its immediate Decl parent. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_INDEX_ASTLOCATION_H 15 #define LLVM_CLANG_INDEX_ASTLOCATION_H 16 17 #include "clang/AST/TypeLoc.h" 18 #include "llvm/ADT/PointerIntPair.h" 19 20 namespace llvm { 21 class raw_ostream; 22 } 23 24 namespace clang { 25 class Decl; 26 class Stmt; 27 class NamedDecl; 28 29 namespace idx { 30 class TranslationUnit; 31 32 /// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's 33 /// immutable. 34 /// 35 /// ASTLocation is intended to be used as a "pointer" into the AST. It is either 36 /// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid 37 /// of context, its parent Decl provides all the additional missing information 38 /// like the declaration context, ASTContext, etc. 39 /// 40 class ASTLocation { 41 public: 42 enum NodeKind { 43 N_Decl, N_NamedRef, N_Stmt, N_Type 44 }; 45 46 struct NamedRef { 47 NamedDecl *ND; 48 SourceLocation Loc; 49 NamedRefNamedRef50 NamedRef() : ND(0) { } NamedRefNamedRef51 NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { } 52 }; 53 54 private: 55 llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl; 56 57 union { 58 Decl *D; 59 Stmt *Stm; 60 struct { 61 NamedDecl *ND; 62 unsigned RawLoc; 63 } NDRef; 64 struct { 65 void *TyPtr; 66 void *Data; 67 } Ty; 68 }; 69 70 public: ASTLocation()71 ASTLocation() { } 72 ASTLocation(const Decl * d)73 explicit ASTLocation(const Decl *d) 74 : ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { } 75 ASTLocation(const Decl * parentDecl,const Stmt * stm)76 ASTLocation(const Decl *parentDecl, const Stmt *stm) 77 : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt), 78 Stm(const_cast<Stmt*>(stm)) { 79 if (!stm) ParentDecl.setPointer(0); 80 } 81 ASTLocation(const Decl * parentDecl,NamedDecl * ndRef,SourceLocation loc)82 ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc) 83 : ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) { 84 if (ndRef) { 85 NDRef.ND = ndRef; 86 NDRef.RawLoc = loc.getRawEncoding(); 87 } else 88 ParentDecl.setPointer(0); 89 } 90 ASTLocation(const Decl * parentDecl,TypeLoc tyLoc)91 ASTLocation(const Decl *parentDecl, TypeLoc tyLoc) 92 : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) { 93 if (tyLoc) { 94 Ty.TyPtr = tyLoc.getType().getAsOpaquePtr(); 95 Ty.Data = tyLoc.getOpaqueData(); 96 } else 97 ParentDecl.setPointer(0); 98 } 99 isValid()100 bool isValid() const { return ParentDecl.getPointer() != 0; } isInvalid()101 bool isInvalid() const { return !isValid(); } 102 getKind()103 NodeKind getKind() const { 104 assert(isValid()); 105 return (NodeKind)ParentDecl.getInt(); 106 } 107 getParentDecl()108 Decl *getParentDecl() const { return ParentDecl.getPointer(); } 109 AsDecl()110 Decl *AsDecl() const { 111 assert(getKind() == N_Decl); 112 return D; 113 } AsStmt()114 Stmt *AsStmt() const { 115 assert(getKind() == N_Stmt); 116 return Stm; 117 } AsNamedRef()118 NamedRef AsNamedRef() const { 119 assert(getKind() == N_NamedRef); 120 return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc)); 121 } AsTypeLoc()122 TypeLoc AsTypeLoc() const { 123 assert(getKind() == N_Type); 124 return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data); 125 } 126 dyn_AsDecl()127 Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } dyn_AsStmt()128 Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; } dyn_AsNamedRef()129 NamedRef dyn_AsNamedRef() const { 130 return getKind() == N_Type ? AsNamedRef() : NamedRef(); 131 } dyn_AsTypeLoc()132 TypeLoc dyn_AsTypeLoc() const { 133 return getKind() == N_Type ? AsTypeLoc() : TypeLoc(); 134 } 135 isDecl()136 bool isDecl() const { return isValid() && getKind() == N_Decl; } isStmt()137 bool isStmt() const { return isValid() && getKind() == N_Stmt; } isNamedRef()138 bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; } isType()139 bool isType() const { return isValid() && getKind() == N_Type; } 140 141 /// \brief Returns the declaration that this ASTLocation references. 142 /// 143 /// If this points to a Decl, that Decl is returned. 144 /// If this points to an Expr that references a Decl, that Decl is returned, 145 /// otherwise it returns NULL. 146 Decl *getReferencedDecl(); getReferencedDecl()147 const Decl *getReferencedDecl() const { 148 return const_cast<ASTLocation*>(this)->getReferencedDecl(); 149 } 150 151 SourceRange getSourceRange() const; 152 153 void print(llvm::raw_ostream &OS) const; 154 }; 155 156 /// \brief Like ASTLocation but also contains the TranslationUnit that the 157 /// ASTLocation originated from. 158 class TULocation : public ASTLocation { 159 TranslationUnit *TU; 160 161 public: TULocation(TranslationUnit * tu,ASTLocation astLoc)162 TULocation(TranslationUnit *tu, ASTLocation astLoc) 163 : ASTLocation(astLoc), TU(tu) { 164 assert(tu && "Passed null translation unit"); 165 } 166 getTU()167 TranslationUnit *getTU() const { return TU; } 168 }; 169 170 } // namespace idx 171 172 } // namespace clang 173 174 #endif 175