clang API Documentation

ASTTypeTraits.h
Go to the documentation of this file.
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