clang API Documentation
00001 //===--- ASTTypeTraits.h ----------------------------------------*- 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 // Provides a dynamic type identifier and a dynamically typed node container 00011 // that can be used to store an AST base node at runtime in the same storage in 00012 // a type safe way. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H 00017 #define LLVM_CLANG_AST_ASTTYPETRAITS_H 00018 00019 #include "clang/AST/ASTFwd.h" 00020 #include "clang/AST/Decl.h" 00021 #include "clang/AST/NestedNameSpecifier.h" 00022 #include "clang/AST/Stmt.h" 00023 #include "clang/AST/TemplateBase.h" 00024 #include "clang/AST/TypeLoc.h" 00025 #include "clang/Basic/LLVM.h" 00026 #include "llvm/Support/AlignOf.h" 00027 00028 namespace llvm { 00029 00030 class raw_ostream; 00031 00032 } 00033 00034 namespace clang { 00035 00036 struct PrintingPolicy; 00037 00038 namespace ast_type_traits { 00039 00040 /// \brief Kind identifier. 00041 /// 00042 /// It can be constructed from any node kind and allows for runtime type 00043 /// hierarchy checks. 00044 /// Use getFromNodeKind<T>() to construct them. 00045 class ASTNodeKind { 00046 public: 00047 /// \brief Empty identifier. It matches nothing. 00048 ASTNodeKind() : KindId(NKI_None) {} 00049 00050 /// \brief Construct an identifier for T. 00051 template <class T> 00052 static ASTNodeKind getFromNodeKind() { 00053 return ASTNodeKind(KindToKindId<T>::Id); 00054 } 00055 00056 /// \{ 00057 /// \brief Construct an identifier for the dynamic type of the node 00058 static ASTNodeKind getFromNode(const Decl &D); 00059 static ASTNodeKind getFromNode(const Stmt &S); 00060 static ASTNodeKind getFromNode(const Type &T); 00061 /// \} 00062 00063 /// \brief Returns \c true if \c this and \c Other represent the same kind. 00064 bool isSame(ASTNodeKind Other) const; 00065 00066 /// \brief Returns \c true only for the default \c ASTNodeKind() 00067 bool isNone() const { return KindId == NKI_None; } 00068 00069 /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. 00070 /// \param Distance If non-null, used to return the distance between \c this 00071 /// and \c Other in the class hierarchy. 00072 bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; 00073 00074 /// \brief String representation of the kind. 00075 StringRef asStringRef() const; 00076 00077 /// \brief Strict weak ordering for ASTNodeKind. 00078 bool operator<(const ASTNodeKind &Other) const { 00079 return KindId < Other.KindId; 00080 } 00081 00082 /// \brief Return the most derived type between \p Kind1 and \p Kind2. 00083 /// 00084 /// Return ASTNodeKind() if they are not related. 00085 static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); 00086 00087 /// \brief Return the most derived common ancestor between Kind1 and Kind2. 00088 /// 00089 /// Return ASTNodeKind() if they are not related. 00090 static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, 00091 ASTNodeKind Kind2); 00092 00093 private: 00094 /// \brief Kind ids. 00095 /// 00096 /// Includes all possible base and derived kinds. 00097 enum NodeKindId { 00098 NKI_None, 00099 NKI_CXXCtorInitializer, 00100 NKI_TemplateArgument, 00101 NKI_NestedNameSpecifier, 00102 NKI_NestedNameSpecifierLoc, 00103 NKI_QualType, 00104 NKI_TypeLoc, 00105 NKI_Decl, 00106 #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, 00107 #include "clang/AST/DeclNodes.inc" 00108 NKI_Stmt, 00109 #define STMT(DERIVED, BASE) NKI_##DERIVED, 00110 #include "clang/AST/StmtNodes.inc" 00111 NKI_Type, 00112 #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, 00113 #include "clang/AST/TypeNodes.def" 00114 NKI_NumberOfKinds 00115 }; 00116 00117 /// \brief Use getFromNodeKind<T>() to construct the kind. 00118 ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} 00119 00120 /// \brief Returns \c true if \c Base is a base kind of (or same as) \c 00121 /// Derived. 00122 /// \param Distance If non-null, used to return the distance between \c Base 00123 /// and \c Derived in the class hierarchy. 00124 static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); 00125 00126 /// \brief Helper meta-function to convert a kind T to its enum value. 00127 /// 00128 /// This struct is specialized below for all known kinds. 00129 template <class T> struct KindToKindId { 00130 static const NodeKindId Id = NKI_None; 00131 }; 00132 00133 /// \brief Per kind info. 00134 struct KindInfo { 00135 /// \brief The id of the parent kind, or None if it has no parent. 00136 NodeKindId ParentId; 00137 /// \brief Name of the kind. 00138 const char *Name; 00139 }; 00140 static const KindInfo AllKindInfo[NKI_NumberOfKinds]; 00141 00142 NodeKindId KindId; 00143 }; 00144 00145 #define KIND_TO_KIND_ID(Class) \ 00146 template <> struct ASTNodeKind::KindToKindId<Class> { \ 00147 static const NodeKindId Id = NKI_##Class; \ 00148 }; 00149 KIND_TO_KIND_ID(CXXCtorInitializer) 00150 KIND_TO_KIND_ID(TemplateArgument) 00151 KIND_TO_KIND_ID(NestedNameSpecifier) 00152 KIND_TO_KIND_ID(NestedNameSpecifierLoc) 00153 KIND_TO_KIND_ID(QualType) 00154 KIND_TO_KIND_ID(TypeLoc) 00155 KIND_TO_KIND_ID(Decl) 00156 KIND_TO_KIND_ID(Stmt) 00157 KIND_TO_KIND_ID(Type) 00158 #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) 00159 #include "clang/AST/DeclNodes.inc" 00160 #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) 00161 #include "clang/AST/StmtNodes.inc" 00162 #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) 00163 #include "clang/AST/TypeNodes.def" 00164 #undef KIND_TO_KIND_ID 00165 00166 inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { 00167 OS << K.asStringRef(); 00168 return OS; 00169 } 00170 00171 /// \brief A dynamically typed AST node container. 00172 /// 00173 /// Stores an AST node in a type safe way. This allows writing code that 00174 /// works with different kinds of AST nodes, despite the fact that they don't 00175 /// have a common base class. 00176 /// 00177 /// Use \c create(Node) to create a \c DynTypedNode from an AST node, 00178 /// and \c get<T>() to retrieve the node as type T if the types match. 00179 /// 00180 /// See \c ASTNodeKind for which node base types are currently supported; 00181 /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of 00182 /// the supported base types. 00183 class DynTypedNode { 00184 public: 00185 /// \brief Creates a \c DynTypedNode from \c Node. 00186 template <typename T> 00187 static DynTypedNode create(const T &Node) { 00188 return BaseConverter<T>::create(Node); 00189 } 00190 00191 /// \brief Retrieve the stored node as type \c T. 00192 /// 00193 /// Returns NULL if the stored node does not have a type that is 00194 /// convertible to \c T. 00195 /// 00196 /// For types that have identity via their pointer in the AST 00197 /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned 00198 /// pointer points to the referenced AST node. 00199 /// For other types (like \c QualType) the value is stored directly 00200 /// in the \c DynTypedNode, and the returned pointer points at 00201 /// the storage inside DynTypedNode. For those nodes, do not 00202 /// use the pointer outside the scope of the DynTypedNode. 00203 template <typename T> 00204 const T *get() const { 00205 return BaseConverter<T>::get(NodeKind, Storage.buffer); 00206 } 00207 00208 ASTNodeKind getNodeKind() const { return NodeKind; } 00209 00210 /// \brief Returns a pointer that identifies the stored AST node. 00211 /// 00212 /// Note that this is not supported by all AST nodes. For AST nodes 00213 /// that don't have a pointer-defined identity inside the AST, this 00214 /// method returns NULL. 00215 const void *getMemoizationData() const { return MemoizationData; } 00216 00217 /// \brief Prints the node to the given output stream. 00218 void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; 00219 00220 /// \brief Dumps the node to the given output stream. 00221 void dump(llvm::raw_ostream &OS, SourceManager &SM) const; 00222 00223 /// \brief For nodes which represent textual entities in the source code, 00224 /// return their SourceRange. For all other nodes, return SourceRange(). 00225 SourceRange getSourceRange() const; 00226 00227 /// @{ 00228 /// \brief Imposes an order on \c DynTypedNode. 00229 /// 00230 /// Supports comparison of nodes that support memoization. 00231 /// FIXME: Implement comparsion for other node types (currently 00232 /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). 00233 bool operator<(const DynTypedNode &Other) const { 00234 assert(getMemoizationData() && Other.getMemoizationData()); 00235 return getMemoizationData() < Other.getMemoizationData(); 00236 } 00237 bool operator==(const DynTypedNode &Other) const { 00238 if (!NodeKind.isBaseOf(Other.NodeKind) && 00239 !Other.NodeKind.isBaseOf(NodeKind)) 00240 return false; 00241 00242 // FIXME: Implement for other types. 00243 if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) { 00244 return *get<QualType>() == *Other.get<QualType>(); 00245 } 00246 assert(getMemoizationData() && Other.getMemoizationData()); 00247 return getMemoizationData() == Other.getMemoizationData(); 00248 } 00249 bool operator!=(const DynTypedNode &Other) const { 00250 return !operator==(Other); 00251 } 00252 /// @} 00253 00254 private: 00255 /// \brief Takes care of converting from and to \c T. 00256 template <typename T, typename EnablerT = void> struct BaseConverter; 00257 00258 /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. 00259 template <typename T, typename BaseT> struct DynCastPtrConverter { 00260 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 00261 if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) 00262 return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); 00263 return nullptr; 00264 } 00265 static DynTypedNode create(const BaseT &Node) { 00266 DynTypedNode Result; 00267 Result.NodeKind = ASTNodeKind::getFromNode(Node); 00268 Result.MemoizationData = &Node; 00269 new (Result.Storage.buffer) const BaseT * (&Node); 00270 return Result; 00271 } 00272 }; 00273 00274 /// \brief Converter that stores T* (by pointer). 00275 template <typename T> struct PtrConverter { 00276 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 00277 if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 00278 return *reinterpret_cast<T *const *>(Storage); 00279 return nullptr; 00280 } 00281 static DynTypedNode create(const T &Node) { 00282 DynTypedNode Result; 00283 Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 00284 Result.MemoizationData = &Node; 00285 new (Result.Storage.buffer) const T * (&Node); 00286 return Result; 00287 } 00288 }; 00289 00290 /// \brief Converter that stores T (by value). 00291 template <typename T> struct ValueConverter { 00292 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 00293 if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 00294 return reinterpret_cast<const T *>(Storage); 00295 return nullptr; 00296 } 00297 static DynTypedNode create(const T &Node) { 00298 DynTypedNode Result; 00299 Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 00300 Result.MemoizationData = nullptr; 00301 new (Result.Storage.buffer) T(Node); 00302 return Result; 00303 } 00304 }; 00305 00306 ASTNodeKind NodeKind; 00307 const void *MemoizationData; 00308 00309 /// \brief Stores the data of the node. 00310 /// 00311 /// Note that we can store \c Decls, \c Stmts, \c Types, 00312 /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are 00313 /// guaranteed to be unique pointers pointing to dedicated storage in the AST. 00314 /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and 00315 /// \c TemplateArguments on the other hand do not have storage or unique 00316 /// pointers and thus need to be stored by value. 00317 typedef llvm::AlignedCharArrayUnion< 00318 Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *> 00319 KindsByPointer; 00320 llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument, 00321 NestedNameSpecifierLoc, QualType, TypeLoc> 00322 Storage; 00323 }; 00324 00325 template <typename T> 00326 struct DynTypedNode::BaseConverter< 00327 T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> 00328 : public DynCastPtrConverter<T, Decl> {}; 00329 00330 template <typename T> 00331 struct DynTypedNode::BaseConverter< 00332 T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> 00333 : public DynCastPtrConverter<T, Stmt> {}; 00334 00335 template <typename T> 00336 struct DynTypedNode::BaseConverter< 00337 T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> 00338 : public DynCastPtrConverter<T, Type> {}; 00339 00340 template <> 00341 struct DynTypedNode::BaseConverter< 00342 NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; 00343 00344 template <> 00345 struct DynTypedNode::BaseConverter< 00346 CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; 00347 00348 template <> 00349 struct DynTypedNode::BaseConverter< 00350 TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; 00351 00352 template <> 00353 struct DynTypedNode::BaseConverter< 00354 NestedNameSpecifierLoc, 00355 void> : public ValueConverter<NestedNameSpecifierLoc> {}; 00356 00357 template <> 00358 struct DynTypedNode::BaseConverter<QualType, 00359 void> : public ValueConverter<QualType> {}; 00360 00361 template <> 00362 struct DynTypedNode::BaseConverter< 00363 TypeLoc, void> : public ValueConverter<TypeLoc> {}; 00364 00365 // The only operation we allow on unsupported types is \c get. 00366 // This allows to conveniently use \c DynTypedNode when having an arbitrary 00367 // AST node that is not supported, but prevents misuse - a user cannot create 00368 // a DynTypedNode from arbitrary types. 00369 template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { 00370 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 00371 return NULL; 00372 } 00373 }; 00374 00375 } // end namespace ast_type_traits 00376 } // end namespace clang 00377 00378 #endif