clang API Documentation
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