| //===-- Type.h --------------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_Type_h_ |
| #define liblldb_Type_h_ |
| |
| #include "lldb/Core/ClangForward.h" |
| #include "lldb/Symbol/CompilerDecl.h" |
| #include "lldb/Symbol/CompilerType.h" |
| #include "lldb/Symbol/Declaration.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/UserID.h" |
| #include "lldb/lldb-private.h" |
| |
| #include "llvm/ADT/APSInt.h" |
| |
| #include <set> |
| |
| namespace lldb_private { |
| //---------------------------------------------------------------------- |
| // CompilerContext allows an array of these items to be passed to perform |
| // detailed lookups in SymbolVendor and SymbolFile functions. |
| //---------------------------------------------------------------------- |
| struct CompilerContext { |
| CompilerContext(CompilerContextKind t, const ConstString &n) |
| : type(t), name(n) {} |
| |
| bool operator==(const CompilerContext &rhs) const { |
| return type == rhs.type && name == rhs.name; |
| } |
| |
| void Dump() const; |
| |
| CompilerContextKind type; |
| ConstString name; |
| }; |
| |
| class SymbolFileType : public std::enable_shared_from_this<SymbolFileType>, |
| public UserID { |
| public: |
| SymbolFileType(SymbolFile &symbol_file, lldb::user_id_t uid) |
| : UserID(uid), m_symbol_file(symbol_file) {} |
| |
| SymbolFileType(SymbolFile &symbol_file, const lldb::TypeSP &type_sp); |
| |
| ~SymbolFileType() {} |
| |
| Type *operator->() { return GetType(); } |
| |
| Type *GetType(); |
| |
| protected: |
| SymbolFile &m_symbol_file; |
| lldb::TypeSP m_type_sp; |
| }; |
| |
| class Type : public std::enable_shared_from_this<Type>, public UserID { |
| public: |
| typedef enum EncodingDataTypeTag { |
| eEncodingInvalid, |
| eEncodingIsUID, ///< This type is the type whose UID is m_encoding_uid |
| eEncodingIsConstUID, ///< This type is the type whose UID is m_encoding_uid |
| ///with the const qualifier added |
| eEncodingIsRestrictUID, ///< This type is the type whose UID is |
| ///m_encoding_uid with the restrict qualifier added |
| eEncodingIsVolatileUID, ///< This type is the type whose UID is |
| ///m_encoding_uid with the volatile qualifier added |
| eEncodingIsTypedefUID, ///< This type is pointer to a type whose UID is |
| ///m_encoding_uid |
| eEncodingIsPointerUID, ///< This type is pointer to a type whose UID is |
| ///m_encoding_uid |
| eEncodingIsLValueReferenceUID, ///< This type is L value reference to a type |
| ///whose UID is m_encoding_uid |
| eEncodingIsRValueReferenceUID, ///< This type is R value reference to a type |
| ///whose UID is m_encoding_uid |
| eEncodingIsSyntheticUID |
| } EncodingDataType; |
| |
| // We must force the underlying type of the enum to be unsigned here. Not |
| // all compilers behave the same with regards to the default underlying type |
| // of an enum, but because this enum is used in an enum bitfield and integer |
| // comparisons are done with the value we need to guarantee that it's always |
| // unsigned so that, for example, eResolveStateFull doesn't compare less than |
| // eResolveStateUnresolved when used in a 2-bit bitfield. |
| typedef enum ResolveStateTag : unsigned { |
| eResolveStateUnresolved = 0, |
| eResolveStateForward = 1, |
| eResolveStateLayout = 2, |
| eResolveStateFull = 3 |
| } ResolveState; |
| |
| Type(lldb::user_id_t uid, SymbolFile *symbol_file, const ConstString &name, |
| uint64_t byte_size, SymbolContextScope *context, |
| lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, |
| const Declaration &decl, const CompilerType &compiler_qual_type, |
| ResolveState compiler_type_resolve_state); |
| |
| // This makes an invalid type. Used for functions that return a Type when |
| // they get an error. |
| Type(); |
| |
| Type(const Type &rhs); |
| |
| const Type &operator=(const Type &rhs); |
| |
| void Dump(Stream *s, bool show_context); |
| |
| void DumpTypeName(Stream *s); |
| |
| // Since Type instances only keep a "SymbolFile *" internally, other classes |
| // like TypeImpl need make sure the module is still around before playing |
| // with |
| // Type instances. They can store a weak pointer to the Module; |
| lldb::ModuleSP GetModule(); |
| |
| void GetDescription(Stream *s, lldb::DescriptionLevel level, bool show_name); |
| |
| SymbolFile *GetSymbolFile() { return m_symbol_file; } |
| const SymbolFile *GetSymbolFile() const { return m_symbol_file; } |
| |
| TypeList *GetTypeList(); |
| |
| const ConstString &GetName(); |
| |
| uint64_t GetByteSize(); |
| |
| uint32_t GetNumChildren(bool omit_empty_base_classes); |
| |
| bool IsAggregateType(); |
| |
| bool IsValidType() { return m_encoding_uid_type != eEncodingInvalid; } |
| |
| bool IsTypedef() { return m_encoding_uid_type == eEncodingIsTypedefUID; } |
| |
| lldb::TypeSP GetTypedefType(); |
| |
| const ConstString &GetName() const { return m_name; } |
| |
| ConstString GetQualifiedName(); |
| |
| void DumpValue(ExecutionContext *exe_ctx, Stream *s, |
| const DataExtractor &data, uint32_t data_offset, |
| bool show_type, bool show_summary, bool verbose, |
| lldb::Format format = lldb::eFormatDefault); |
| |
| bool DumpValueInMemory(ExecutionContext *exe_ctx, Stream *s, |
| lldb::addr_t address, AddressType address_type, |
| bool show_types, bool show_summary, bool verbose); |
| |
| bool ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t address, |
| AddressType address_type, DataExtractor &data); |
| |
| bool WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t address, |
| AddressType address_type, DataExtractor &data); |
| |
| bool GetIsDeclaration() const; |
| |
| void SetIsDeclaration(bool b); |
| |
| bool GetIsExternal() const; |
| |
| void SetIsExternal(bool b); |
| |
| lldb::Format GetFormat(); |
| |
| lldb::Encoding GetEncoding(uint64_t &count); |
| |
| SymbolContextScope *GetSymbolContextScope() { return m_context; } |
| const SymbolContextScope *GetSymbolContextScope() const { return m_context; } |
| void SetSymbolContextScope(SymbolContextScope *context) { |
| m_context = context; |
| } |
| |
| const lldb_private::Declaration &GetDeclaration() const; |
| |
| // Get the clang type, and resolve definitions for any |
| // class/struct/union/enum types completely. |
| CompilerType GetFullCompilerType(); |
| |
| // Get the clang type, and resolve definitions enough so that the type could |
| // have layout performed. This allows ptrs and refs to |
| // class/struct/union/enum types remain forward declarations. |
| CompilerType GetLayoutCompilerType(); |
| |
| // Get the clang type and leave class/struct/union/enum types as forward |
| // declarations if they haven't already been fully defined. |
| CompilerType GetForwardCompilerType(); |
| |
| static int Compare(const Type &a, const Type &b); |
| |
| // From a fully qualified typename, split the type into the type basename and |
| // the remaining type scope (namespaces/classes). |
| static bool GetTypeScopeAndBasename(const llvm::StringRef& name, |
| llvm::StringRef &scope, |
| llvm::StringRef &basename, |
| lldb::TypeClass &type_class); |
| void SetEncodingType(Type *encoding_type) { m_encoding_type = encoding_type; } |
| |
| uint32_t GetEncodingMask(); |
| |
| bool IsCompleteObjCClass() { return m_flags.is_complete_objc_class; } |
| |
| void SetIsCompleteObjCClass(bool is_complete_objc_class) { |
| m_flags.is_complete_objc_class = is_complete_objc_class; |
| } |
| |
| protected: |
| ConstString m_name; |
| SymbolFile *m_symbol_file; |
| SymbolContextScope |
| *m_context; // The symbol context in which this type is defined |
| Type *m_encoding_type; |
| lldb::user_id_t m_encoding_uid; |
| EncodingDataType m_encoding_uid_type; |
| uint64_t m_byte_size; |
| Declaration m_decl; |
| CompilerType m_compiler_type; |
| |
| struct Flags { |
| #ifdef __GNUC__ |
| // using unsigned type here to work around a very noisy gcc warning |
| unsigned compiler_type_resolve_state : 2; |
| #else |
| ResolveState compiler_type_resolve_state : 2; |
| #endif |
| bool is_complete_objc_class : 1; |
| } m_flags; |
| |
| Type *GetEncodingType(); |
| |
| bool ResolveClangType(ResolveState compiler_type_resolve_state); |
| }; |
| |
| // these classes are used to back the SBType* objects |
| |
| class TypePair { |
| public: |
| TypePair() : compiler_type(), type_sp() {} |
| |
| TypePair(CompilerType type) : compiler_type(type), type_sp() {} |
| |
| TypePair(lldb::TypeSP type) : compiler_type(), type_sp(type) { |
| compiler_type = type_sp->GetForwardCompilerType(); |
| } |
| |
| bool IsValid() const { |
| return compiler_type.IsValid() || (type_sp.get() != nullptr); |
| } |
| |
| explicit operator bool() const { return IsValid(); } |
| |
| bool operator==(const TypePair &rhs) const { |
| return compiler_type == rhs.compiler_type && |
| type_sp.get() == rhs.type_sp.get(); |
| } |
| |
| bool operator!=(const TypePair &rhs) const { |
| return compiler_type != rhs.compiler_type || |
| type_sp.get() != rhs.type_sp.get(); |
| } |
| |
| void Clear() { |
| compiler_type.Clear(); |
| type_sp.reset(); |
| } |
| |
| ConstString GetName() const { |
| if (type_sp) |
| return type_sp->GetName(); |
| if (compiler_type) |
| return compiler_type.GetTypeName(); |
| return ConstString(); |
| } |
| |
| ConstString GetDisplayTypeName() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetDisplayTypeName(); |
| if (compiler_type) |
| return compiler_type.GetDisplayTypeName(); |
| return ConstString(); |
| } |
| |
| void SetType(CompilerType type) { |
| type_sp.reset(); |
| compiler_type = type; |
| } |
| |
| void SetType(lldb::TypeSP type) { |
| type_sp = type; |
| if (type_sp) |
| compiler_type = type_sp->GetForwardCompilerType(); |
| else |
| compiler_type.Clear(); |
| } |
| |
| lldb::TypeSP GetTypeSP() const { return type_sp; } |
| |
| CompilerType GetCompilerType() const { return compiler_type; } |
| |
| CompilerType GetPointerType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetPointerType(); |
| return compiler_type.GetPointerType(); |
| } |
| |
| CompilerType GetPointeeType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetPointeeType(); |
| return compiler_type.GetPointeeType(); |
| } |
| |
| CompilerType GetReferenceType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetLValueReferenceType(); |
| else |
| return compiler_type.GetLValueReferenceType(); |
| } |
| |
| CompilerType GetTypedefedType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetTypedefedType(); |
| else |
| return compiler_type.GetTypedefedType(); |
| } |
| |
| CompilerType GetDereferencedType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetNonReferenceType(); |
| else |
| return compiler_type.GetNonReferenceType(); |
| } |
| |
| CompilerType GetUnqualifiedType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetFullyUnqualifiedType(); |
| else |
| return compiler_type.GetFullyUnqualifiedType(); |
| } |
| |
| CompilerType GetCanonicalType() const { |
| if (type_sp) |
| return type_sp->GetForwardCompilerType().GetCanonicalType(); |
| return compiler_type.GetCanonicalType(); |
| } |
| |
| TypeSystem *GetTypeSystem() const { return compiler_type.GetTypeSystem(); } |
| |
| lldb::ModuleSP GetModule() const { |
| if (type_sp) |
| return type_sp->GetModule(); |
| return lldb::ModuleSP(); |
| } |
| |
| protected: |
| CompilerType compiler_type; |
| lldb::TypeSP type_sp; |
| }; |
| |
| // the two classes here are used by the public API as a backend to the SBType |
| // and SBTypeList classes |
| |
| class TypeImpl { |
| public: |
| TypeImpl(); |
| |
| ~TypeImpl() {} |
| |
| TypeImpl(const TypeImpl &rhs); |
| |
| TypeImpl(const lldb::TypeSP &type_sp); |
| |
| TypeImpl(const CompilerType &compiler_type); |
| |
| TypeImpl(const lldb::TypeSP &type_sp, const CompilerType &dynamic); |
| |
| TypeImpl(const CompilerType &compiler_type, const CompilerType &dynamic); |
| |
| TypeImpl(const TypePair &pair, const CompilerType &dynamic); |
| |
| void SetType(const lldb::TypeSP &type_sp); |
| |
| void SetType(const CompilerType &compiler_type); |
| |
| void SetType(const lldb::TypeSP &type_sp, const CompilerType &dynamic); |
| |
| void SetType(const CompilerType &compiler_type, const CompilerType &dynamic); |
| |
| void SetType(const TypePair &pair, const CompilerType &dynamic); |
| |
| TypeImpl &operator=(const TypeImpl &rhs); |
| |
| bool operator==(const TypeImpl &rhs) const; |
| |
| bool operator!=(const TypeImpl &rhs) const; |
| |
| bool IsValid() const; |
| |
| explicit operator bool() const; |
| |
| void Clear(); |
| |
| ConstString GetName() const; |
| |
| ConstString GetDisplayTypeName() const; |
| |
| TypeImpl GetPointerType() const; |
| |
| TypeImpl GetPointeeType() const; |
| |
| TypeImpl GetReferenceType() const; |
| |
| TypeImpl GetTypedefedType() const; |
| |
| TypeImpl GetDereferencedType() const; |
| |
| TypeImpl GetUnqualifiedType() const; |
| |
| TypeImpl GetCanonicalType() const; |
| |
| CompilerType GetCompilerType(bool prefer_dynamic); |
| |
| TypeSystem *GetTypeSystem(bool prefer_dynamic); |
| |
| bool GetDescription(lldb_private::Stream &strm, |
| lldb::DescriptionLevel description_level); |
| |
| private: |
| bool CheckModule(lldb::ModuleSP &module_sp) const; |
| |
| lldb::ModuleWP m_module_wp; |
| TypePair m_static_type; |
| CompilerType m_dynamic_type; |
| }; |
| |
| class TypeListImpl { |
| public: |
| TypeListImpl() : m_content() {} |
| |
| void Append(const lldb::TypeImplSP &type) { m_content.push_back(type); } |
| |
| class AppendVisitor { |
| public: |
| AppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {} |
| |
| void operator()(const lldb::TypeImplSP &type) { m_type_list.Append(type); } |
| |
| private: |
| TypeListImpl &m_type_list; |
| }; |
| |
| void Append(const lldb_private::TypeList &type_list); |
| |
| lldb::TypeImplSP GetTypeAtIndex(size_t idx) { |
| lldb::TypeImplSP type_sp; |
| if (idx < GetSize()) |
| type_sp = m_content[idx]; |
| return type_sp; |
| } |
| |
| size_t GetSize() { return m_content.size(); } |
| |
| private: |
| std::vector<lldb::TypeImplSP> m_content; |
| }; |
| |
| class TypeMemberImpl { |
| public: |
| TypeMemberImpl() |
| : m_type_impl_sp(), m_bit_offset(0), m_name(), m_bitfield_bit_size(0), |
| m_is_bitfield(false) |
| |
| {} |
| |
| TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset, |
| const ConstString &name, uint32_t bitfield_bit_size = 0, |
| bool is_bitfield = false) |
| : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_name(name), |
| m_bitfield_bit_size(bitfield_bit_size), m_is_bitfield(is_bitfield) {} |
| |
| TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset) |
| : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_name(), |
| m_bitfield_bit_size(0), m_is_bitfield(false) { |
| if (m_type_impl_sp) |
| m_name = m_type_impl_sp->GetName(); |
| } |
| |
| const lldb::TypeImplSP &GetTypeImpl() { return m_type_impl_sp; } |
| |
| const ConstString &GetName() const { return m_name; } |
| |
| uint64_t GetBitOffset() const { return m_bit_offset; } |
| |
| uint32_t GetBitfieldBitSize() const { return m_bitfield_bit_size; } |
| |
| void SetBitfieldBitSize(uint32_t bitfield_bit_size) { |
| m_bitfield_bit_size = bitfield_bit_size; |
| } |
| |
| bool GetIsBitfield() const { return m_is_bitfield; } |
| |
| void SetIsBitfield(bool is_bitfield) { m_is_bitfield = is_bitfield; } |
| |
| protected: |
| lldb::TypeImplSP m_type_impl_sp; |
| uint64_t m_bit_offset; |
| ConstString m_name; |
| uint32_t m_bitfield_bit_size; // Bit size for bitfield members only |
| bool m_is_bitfield; |
| }; |
| |
| /// |
| /// Sometimes you can find the name of the type corresponding to an object, but |
| /// we don't have debug |
| /// information for it. If that is the case, you can return one of these |
| /// objects, and then if it |
| /// has a full type, you can use that, but if not at least you can print the |
| /// name for informational |
| /// purposes. |
| /// |
| |
| class TypeAndOrName { |
| public: |
| TypeAndOrName(); |
| TypeAndOrName(lldb::TypeSP &type_sp); |
| TypeAndOrName(const CompilerType &compiler_type); |
| TypeAndOrName(const char *type_str); |
| TypeAndOrName(const TypeAndOrName &rhs); |
| TypeAndOrName(ConstString &type_const_string); |
| |
| TypeAndOrName &operator=(const TypeAndOrName &rhs); |
| |
| bool operator==(const TypeAndOrName &other) const; |
| |
| bool operator!=(const TypeAndOrName &other) const; |
| |
| ConstString GetName() const; |
| |
| lldb::TypeSP GetTypeSP() const { return m_type_pair.GetTypeSP(); } |
| |
| CompilerType GetCompilerType() const { return m_type_pair.GetCompilerType(); } |
| |
| void SetName(const ConstString &type_name); |
| |
| void SetName(const char *type_name_cstr); |
| |
| void SetTypeSP(lldb::TypeSP type_sp); |
| |
| void SetCompilerType(CompilerType compiler_type); |
| |
| bool IsEmpty() const; |
| |
| bool HasName() const; |
| |
| bool HasTypeSP() const; |
| |
| bool HasCompilerType() const; |
| |
| bool HasType() const { return HasTypeSP() || HasCompilerType(); } |
| |
| void Clear(); |
| |
| explicit operator bool() { return !IsEmpty(); } |
| |
| private: |
| TypePair m_type_pair; |
| ConstString m_type_name; |
| }; |
| |
| class TypeMemberFunctionImpl { |
| public: |
| TypeMemberFunctionImpl() |
| : m_type(), m_decl(), m_name(), m_kind(lldb::eMemberFunctionKindUnknown) { |
| } |
| |
| TypeMemberFunctionImpl(const CompilerType &type, const CompilerDecl &decl, |
| const std::string &name, |
| const lldb::MemberFunctionKind &kind) |
| : m_type(type), m_decl(decl), m_name(name), m_kind(kind) {} |
| |
| bool IsValid(); |
| |
| ConstString GetName() const; |
| |
| ConstString GetMangledName() const; |
| |
| CompilerType GetType() const; |
| |
| CompilerType GetReturnType() const; |
| |
| size_t GetNumArguments() const; |
| |
| CompilerType GetArgumentAtIndex(size_t idx) const; |
| |
| lldb::MemberFunctionKind GetKind() const; |
| |
| bool GetDescription(Stream &stream); |
| |
| protected: |
| std::string GetPrintableTypeName(); |
| |
| private: |
| CompilerType m_type; |
| CompilerDecl m_decl; |
| ConstString m_name; |
| lldb::MemberFunctionKind m_kind; |
| }; |
| |
| class TypeEnumMemberImpl { |
| public: |
| TypeEnumMemberImpl() |
| : m_integer_type_sp(), m_name("<invalid>"), m_value(), m_valid(false) {} |
| |
| TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, |
| const ConstString &name, const llvm::APSInt &value); |
| |
| TypeEnumMemberImpl(const TypeEnumMemberImpl &rhs) |
| : m_integer_type_sp(rhs.m_integer_type_sp), m_name(rhs.m_name), |
| m_value(rhs.m_value), m_valid(rhs.m_valid) {} |
| |
| TypeEnumMemberImpl &operator=(const TypeEnumMemberImpl &rhs); |
| |
| bool IsValid() { return m_valid; } |
| |
| const ConstString &GetName() const { return m_name; } |
| |
| const lldb::TypeImplSP &GetIntegerType() const { return m_integer_type_sp; } |
| |
| uint64_t GetValueAsUnsigned() const { return m_value.getZExtValue(); } |
| |
| int64_t GetValueAsSigned() const { return m_value.getSExtValue(); } |
| |
| protected: |
| lldb::TypeImplSP m_integer_type_sp; |
| ConstString m_name; |
| llvm::APSInt m_value; |
| bool m_valid; |
| }; |
| |
| class TypeEnumMemberListImpl { |
| public: |
| TypeEnumMemberListImpl() : m_content() {} |
| |
| void Append(const lldb::TypeEnumMemberImplSP &type) { |
| m_content.push_back(type); |
| } |
| |
| void Append(const lldb_private::TypeEnumMemberListImpl &type_list); |
| |
| lldb::TypeEnumMemberImplSP GetTypeEnumMemberAtIndex(size_t idx) { |
| lldb::TypeEnumMemberImplSP enum_member; |
| if (idx < GetSize()) |
| enum_member = m_content[idx]; |
| return enum_member; |
| } |
| |
| size_t GetSize() { return m_content.size(); } |
| |
| private: |
| std::vector<lldb::TypeEnumMemberImplSP> m_content; |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // liblldb_Type_h_ |