1 //===--- ASTTypeTraits.h ----------------------------------------*- 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 // Provides a dynamic type identifier and a dynamically typed node container 11 // that can be used to store an AST base node at runtime in the same storage in 12 // a type safe way. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H 17 #define LLVM_CLANG_AST_AST_TYPE_TRAITS_H 18 19 #include "clang/AST/ASTFwd.h" 20 #include "clang/AST/Decl.h" 21 #include "clang/AST/NestedNameSpecifier.h" 22 #include "clang/AST/Stmt.h" 23 #include "clang/AST/TemplateBase.h" 24 #include "clang/AST/TypeLoc.h" 25 #include "clang/Basic/LLVM.h" 26 #include "llvm/Support/AlignOf.h" 27 28 namespace llvm { 29 30 class raw_ostream; 31 32 } 33 34 namespace clang { 35 36 struct PrintingPolicy; 37 38 namespace ast_type_traits { 39 40 /// \brief Kind identifier. 41 /// 42 /// It can be constructed from any node kind and allows for runtime type 43 /// hierarchy checks. 44 /// Use getFromNodeKind<T>() to construct them. 45 class ASTNodeKind { 46 public: 47 /// \brief Empty identifier. It matches nothing. ASTNodeKind()48 ASTNodeKind() : KindId(NKI_None) {} 49 50 /// \brief Construct an identifier for T. 51 template <class T> getFromNodeKind()52 static ASTNodeKind getFromNodeKind() { 53 return ASTNodeKind(KindToKindId<T>::Id); 54 } 55 56 /// \brief Returns \c true if \c this and \c Other represent the same kind. 57 bool isSame(ASTNodeKind Other) const; 58 59 /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. 60 /// \param Distance If non-null, used to return the distance between \c this 61 /// and \c Other in the class hierarchy. 62 bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; 63 64 /// \brief String representation of the kind. 65 StringRef asStringRef() const; 66 67 /// \brief Strict weak ordering for ASTNodeKind. 68 bool operator<(const ASTNodeKind &Other) const { 69 return KindId < Other.KindId; 70 } 71 72 private: 73 /// \brief Kind ids. 74 /// 75 /// Includes all possible base and derived kinds. 76 enum NodeKindId { 77 NKI_None, 78 NKI_CXXCtorInitializer, 79 NKI_TemplateArgument, 80 NKI_NestedNameSpecifier, 81 NKI_NestedNameSpecifierLoc, 82 NKI_QualType, 83 NKI_TypeLoc, 84 NKI_Decl, 85 #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, 86 #include "clang/AST/DeclNodes.inc" 87 NKI_Stmt, 88 #define STMT(DERIVED, BASE) NKI_##DERIVED, 89 #include "clang/AST/StmtNodes.inc" 90 NKI_Type, 91 #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, 92 #include "clang/AST/TypeNodes.def" 93 NKI_NumberOfKinds 94 }; 95 96 /// \brief Use getFromNodeKind<T>() to construct the kind. ASTNodeKind(NodeKindId KindId)97 ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} 98 99 /// \brief Returns \c true if \c Base is a base kind of (or same as) \c 100 /// Derived. 101 /// \param Distance If non-null, used to return the distance between \c Base 102 /// and \c Derived in the class hierarchy. 103 static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); 104 105 /// \brief Helper meta-function to convert a kind T to its enum value. 106 /// 107 /// This struct is specialized below for all known kinds. 108 template <class T> struct KindToKindId { 109 static const NodeKindId Id = NKI_None; 110 }; 111 112 /// \brief Per kind info. 113 struct KindInfo { 114 /// \brief The id of the parent kind, or None if it has no parent. 115 NodeKindId ParentId; 116 /// \brief Name of the kind. 117 const char *Name; 118 }; 119 static const KindInfo AllKindInfo[NKI_NumberOfKinds]; 120 121 NodeKindId KindId; 122 }; 123 124 #define KIND_TO_KIND_ID(Class) \ 125 template <> struct ASTNodeKind::KindToKindId<Class> { \ 126 static const NodeKindId Id = NKI_##Class; \ 127 }; 128 KIND_TO_KIND_ID(CXXCtorInitializer) 129 KIND_TO_KIND_ID(TemplateArgument) 130 KIND_TO_KIND_ID(NestedNameSpecifier) 131 KIND_TO_KIND_ID(NestedNameSpecifierLoc) 132 KIND_TO_KIND_ID(QualType) 133 KIND_TO_KIND_ID(TypeLoc) 134 KIND_TO_KIND_ID(Decl) 135 KIND_TO_KIND_ID(Stmt) 136 KIND_TO_KIND_ID(Type) 137 #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) 138 #include "clang/AST/DeclNodes.inc" 139 #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) 140 #include "clang/AST/StmtNodes.inc" 141 #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) 142 #include "clang/AST/TypeNodes.def" 143 #undef KIND_TO_KIND_ID 144 145 inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { 146 OS << K.asStringRef(); 147 return OS; 148 } 149 150 /// \brief A dynamically typed AST node container. 151 /// 152 /// Stores an AST node in a type safe way. This allows writing code that 153 /// works with different kinds of AST nodes, despite the fact that they don't 154 /// have a common base class. 155 /// 156 /// Use \c create(Node) to create a \c DynTypedNode from an AST node, 157 /// and \c get<T>() to retrieve the node as type T if the types match. 158 /// 159 /// See \c ASTNodeKind for which node base types are currently supported; 160 /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of 161 /// the supported base types. 162 class DynTypedNode { 163 public: 164 /// \brief Creates a \c DynTypedNode from \c Node. 165 template <typename T> create(const T & Node)166 static DynTypedNode create(const T &Node) { 167 return BaseConverter<T>::create(Node); 168 } 169 170 /// \brief Retrieve the stored node as type \c T. 171 /// 172 /// Returns NULL if the stored node does not have a type that is 173 /// convertible to \c T. 174 /// 175 /// For types that have identity via their pointer in the AST 176 /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned 177 /// pointer points to the referenced AST node. 178 /// For other types (like \c QualType) the value is stored directly 179 /// in the \c DynTypedNode, and the returned pointer points at 180 /// the storage inside DynTypedNode. For those nodes, do not 181 /// use the pointer outside the scope of the DynTypedNode. 182 template <typename T> get()183 const T *get() const { 184 return BaseConverter<T>::get(NodeKind, Storage.buffer); 185 } 186 187 /// \brief Returns a pointer that identifies the stored AST node. 188 /// 189 /// Note that this is not supported by all AST nodes. For AST nodes 190 /// that don't have a pointer-defined identity inside the AST, this 191 /// method returns NULL. 192 const void *getMemoizationData() const; 193 194 /// \brief Prints the node to the given output stream. 195 void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; 196 197 /// \brief Dumps the node to the given output stream. 198 void dump(llvm::raw_ostream &OS, SourceManager &SM) const; 199 200 /// \brief For nodes which represent textual entities in the source code, 201 /// return their SourceRange. For all other nodes, return SourceRange(). 202 SourceRange getSourceRange() const; 203 204 /// @{ 205 /// \brief Imposes an order on \c DynTypedNode. 206 /// 207 /// Supports comparison of nodes that support memoization. 208 /// FIXME: Implement comparsion for other node types (currently 209 /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). 210 bool operator<(const DynTypedNode &Other) const { 211 assert(getMemoizationData() && Other.getMemoizationData()); 212 return getMemoizationData() < Other.getMemoizationData(); 213 } 214 bool operator==(const DynTypedNode &Other) const { 215 if (!NodeKind.isBaseOf(Other.NodeKind) && 216 !Other.NodeKind.isBaseOf(NodeKind)) 217 return false; 218 219 // FIXME: Implement for other types. 220 if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) { 221 return *get<QualType>() == *Other.get<QualType>(); 222 } 223 assert(getMemoizationData() && Other.getMemoizationData()); 224 return getMemoizationData() == Other.getMemoizationData(); 225 } 226 bool operator!=(const DynTypedNode &Other) const { 227 return !operator==(Other); 228 } 229 /// @} 230 231 private: 232 /// \brief Takes care of converting from and to \c T. 233 template <typename T, typename EnablerT = void> struct BaseConverter; 234 235 /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. 236 template <typename T, typename BaseT> struct DynCastPtrConverter { getDynCastPtrConverter237 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 238 if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) 239 return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); 240 return nullptr; 241 } createDynCastPtrConverter242 static DynTypedNode create(const BaseT &Node) { 243 DynTypedNode Result; 244 Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 245 new (Result.Storage.buffer) const BaseT * (&Node); 246 return Result; 247 } 248 }; 249 250 /// \brief Converter that stores T* (by pointer). 251 template <typename T> struct PtrConverter { getPtrConverter252 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 253 if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 254 return *reinterpret_cast<T *const *>(Storage); 255 return nullptr; 256 } createPtrConverter257 static DynTypedNode create(const T &Node) { 258 DynTypedNode Result; 259 Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 260 new (Result.Storage.buffer) const T * (&Node); 261 return Result; 262 } 263 }; 264 265 /// \brief Converter that stores T (by value). 266 template <typename T> struct ValueConverter { getValueConverter267 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 268 if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 269 return reinterpret_cast<const T *>(Storage); 270 return nullptr; 271 } createValueConverter272 static DynTypedNode create(const T &Node) { 273 DynTypedNode Result; 274 Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 275 new (Result.Storage.buffer) T(Node); 276 return Result; 277 } 278 }; 279 280 ASTNodeKind NodeKind; 281 282 /// \brief Stores the data of the node. 283 /// 284 /// Note that we can store \c Decls, \c Stmts, \c Types, 285 /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are 286 /// guaranteed to be unique pointers pointing to dedicated storage in the AST. 287 /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and 288 /// \c TemplateArguments on the other hand do not have storage or unique 289 /// pointers and thus need to be stored by value. 290 typedef llvm::AlignedCharArrayUnion< 291 Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *> 292 KindsByPointer; 293 llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument, 294 NestedNameSpecifierLoc, QualType, TypeLoc> 295 Storage; 296 }; 297 298 template <typename T> 299 struct DynTypedNode::BaseConverter< 300 T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> 301 : public DynCastPtrConverter<T, Decl> {}; 302 303 template <typename T> 304 struct DynTypedNode::BaseConverter< 305 T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> 306 : public DynCastPtrConverter<T, Stmt> {}; 307 308 template <typename T> 309 struct DynTypedNode::BaseConverter< 310 T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> 311 : public DynCastPtrConverter<T, Type> {}; 312 313 template <> 314 struct DynTypedNode::BaseConverter< 315 NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; 316 317 template <> 318 struct DynTypedNode::BaseConverter< 319 CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; 320 321 template <> 322 struct DynTypedNode::BaseConverter< 323 TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; 324 325 template <> 326 struct DynTypedNode::BaseConverter< 327 NestedNameSpecifierLoc, 328 void> : public ValueConverter<NestedNameSpecifierLoc> {}; 329 330 template <> 331 struct DynTypedNode::BaseConverter<QualType, 332 void> : public ValueConverter<QualType> {}; 333 334 template <> 335 struct DynTypedNode::BaseConverter< 336 TypeLoc, void> : public ValueConverter<TypeLoc> {}; 337 338 // The only operation we allow on unsupported types is \c get. 339 // This allows to conveniently use \c DynTypedNode when having an arbitrary 340 // AST node that is not supported, but prevents misuse - a user cannot create 341 // a DynTypedNode from arbitrary types. 342 template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { 343 static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 344 return NULL; 345 } 346 }; 347 348 inline const void *DynTypedNode::getMemoizationData() const { 349 if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) { 350 return BaseConverter<Decl>::get(NodeKind, Storage.buffer); 351 } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) { 352 return BaseConverter<Stmt>::get(NodeKind, Storage.buffer); 353 } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) { 354 return BaseConverter<Type>::get(NodeKind, Storage.buffer); 355 } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) { 356 return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer); 357 } 358 return nullptr; 359 } 360 361 } // end namespace ast_type_traits 362 } // end namespace clang 363 364 #endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H 365