//===-- SBType.cpp ----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include "clang/AST/ASTContext.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBType.h" #include "lldb/API/SBStream.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/Type.h" using namespace lldb; using namespace lldb_private; using namespace clang; SBType::SBType() : m_opaque_sp() { } SBType::SBType (const ClangASTType &type) : m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(), type.GetOpaqueQualType()))) { } SBType::SBType (const lldb::TypeSP &type_sp) : m_opaque_sp(new TypeImpl(type_sp)) { } SBType::SBType (const lldb::TypeImplSP &type_impl_sp) : m_opaque_sp(type_impl_sp) { } SBType::SBType (const SBType &rhs) : m_opaque_sp() { if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } } //SBType::SBType (TypeImpl* impl) : // m_opaque_ap(impl) //{} // bool SBType::operator == (SBType &rhs) { if (IsValid() == false) return !rhs.IsValid(); return (rhs.m_opaque_sp->GetASTContext() == m_opaque_sp->GetASTContext()) && (rhs.m_opaque_sp->GetOpaqueQualType() == m_opaque_sp->GetOpaqueQualType()); } bool SBType::operator != (SBType &rhs) { if (IsValid() == false) return rhs.IsValid(); return (rhs.m_opaque_sp->GetASTContext() != m_opaque_sp->GetASTContext()) || (rhs.m_opaque_sp->GetOpaqueQualType() != m_opaque_sp->GetOpaqueQualType()); } lldb::TypeImplSP SBType::GetSP () { return m_opaque_sp; } void SBType::SetSP (const lldb::TypeImplSP &type_impl_sp) { m_opaque_sp = type_impl_sp; } SBType & SBType::operator = (const SBType &rhs) { if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } return *this; } SBType::~SBType () {} TypeImpl & SBType::ref () { if (m_opaque_sp.get() == NULL) m_opaque_sp.reset (new TypeImpl()); return *m_opaque_sp; } const TypeImpl & SBType::ref () const { // "const SBAddress &addr" should already have checked "addr.IsValid()" // prior to calling this function. In case you didn't we will assert // and die to let you know. assert (m_opaque_sp.get()); return *m_opaque_sp; } bool SBType::IsValid() const { if (m_opaque_sp.get() == NULL) return false; return m_opaque_sp->IsValid(); } uint64_t SBType::GetByteSize() { if (!IsValid()) return 0; return m_opaque_sp->GetClangASTType().GetByteSize(); } bool SBType::IsPointerType() { if (!IsValid()) return false; return m_opaque_sp->GetClangASTType().IsPointerType(); } bool SBType::IsReferenceType() { if (!IsValid()) return false; return m_opaque_sp->GetClangASTType().IsReferenceType(); } SBType SBType::GetPointerType() { if (!IsValid()) return SBType(); return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointerType())); } SBType SBType::GetPointeeType() { if (!IsValid()) return SBType(); return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointeeType())); } SBType SBType::GetReferenceType() { if (!IsValid()) return SBType(); return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetLValueReferenceType())); } SBType SBType::GetDereferencedType() { if (!IsValid()) return SBType(); return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetNonReferenceType())); } bool SBType::IsFunctionType () { if (!IsValid()) return false; return m_opaque_sp->GetClangASTType().IsFunctionType(); } bool SBType::IsPolymorphicClass () { if (!IsValid()) return false; return m_opaque_sp->GetClangASTType().IsPolymorphicClass(); } lldb::SBType SBType::GetFunctionReturnType () { if (IsValid()) { ClangASTType return_clang_type (m_opaque_sp->GetClangASTType().GetFunctionReturnType()); if (return_clang_type.IsValid()) return SBType(return_clang_type); } return lldb::SBType(); } lldb::SBTypeList SBType::GetFunctionArgumentTypes () { SBTypeList sb_type_list; if (IsValid()) { QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType())); const FunctionProtoType* func = dyn_cast(qual_type.getTypePtr()); if (func) { const uint32_t num_args = func->getNumArgs(); for (uint32_t i=0; iGetASTContext(), func->getArgType(i).getAsOpaquePtr()))); } } return sb_type_list; } lldb::SBType SBType::GetUnqualifiedType() { if (!IsValid()) return SBType(); return SBType(m_opaque_sp->GetClangASTType().GetFullyUnqualifiedType()); } lldb::SBType SBType::GetCanonicalType() { if (IsValid()) return SBType(m_opaque_sp->GetClangASTType().GetCanonicalType()); return SBType(); } lldb::BasicType SBType::GetBasicType() { if (IsValid()) return m_opaque_sp->GetClangASTType().GetBasicTypeEnumeration (); return eBasicTypeInvalid; } SBType SBType::GetBasicType(lldb::BasicType basic_type) { if (IsValid()) return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetASTContext(), basic_type)); return SBType(); } uint32_t SBType::GetNumberOfDirectBaseClasses () { if (IsValid()) return m_opaque_sp->GetClangASTType().GetNumDirectBaseClasses(); return 0; } uint32_t SBType::GetNumberOfVirtualBaseClasses () { if (IsValid()) return m_opaque_sp->GetClangASTType().GetNumVirtualBaseClasses(); return 0; } uint32_t SBType::GetNumberOfFields () { if (IsValid()) return m_opaque_sp->GetClangASTType().GetNumFields(); return 0; } bool SBType::GetDescription (SBStream &description, lldb::DescriptionLevel description_level) { Stream &strm = description.ref(); if (m_opaque_sp) { m_opaque_sp->GetDescription (strm, description_level); } else strm.PutCString ("No value"); return true; } SBTypeMember SBType::GetDirectBaseClassAtIndex (uint32_t idx) { SBTypeMember sb_type_member; if (IsValid()) { ClangASTType this_type (m_opaque_sp->GetClangASTType ()); if (this_type.IsValid()) { uint32_t bit_offset = 0; ClangASTType base_class_type (this_type.GetDirectBaseClassAtIndex(idx, &bit_offset)); if (base_class_type.IsValid()) { sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); } } } return sb_type_member; } SBTypeMember SBType::GetVirtualBaseClassAtIndex (uint32_t idx) { SBTypeMember sb_type_member; if (IsValid()) { ClangASTType this_type (m_opaque_sp->GetClangASTType ()); if (this_type.IsValid()) { uint32_t bit_offset = 0; ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset)); if (base_class_type.IsValid()) { sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); } } } return sb_type_member; } SBTypeMember SBType::GetFieldAtIndex (uint32_t idx) { SBTypeMember sb_type_member; if (IsValid()) { ClangASTType this_type (m_opaque_sp->GetClangASTType ()); if (this_type.IsValid()) { uint64_t bit_offset = 0; uint32_t bitfield_bit_size = 0; bool is_bitfield = false; std::string name_sstr; ClangASTType field_type (this_type.GetFieldAtIndex (idx, name_sstr, &bit_offset, &bitfield_bit_size, &is_bitfield)); if (field_type.IsValid()) { ConstString name; if (!name_sstr.empty()) name.SetCString(name_sstr.c_str()); sb_type_member.reset (new TypeMemberImpl (TypeImplSP (new TypeImpl(field_type)), bit_offset, name, bitfield_bit_size, is_bitfield)); } } } return sb_type_member; } bool SBType::IsTypeComplete() { if (!IsValid()) return false; return m_opaque_sp->GetClangASTType().IsCompleteType(); } const char* SBType::GetName() { if (!IsValid()) return ""; return m_opaque_sp->GetClangASTType().GetConstTypeName().GetCString(); } lldb::TypeClass SBType::GetTypeClass () { if (IsValid()) return m_opaque_sp->GetClangASTType().GetTypeClass(); return lldb::eTypeClassInvalid; } uint32_t SBType::GetNumberOfTemplateArguments () { if (IsValid()) return m_opaque_sp->GetClangASTType().GetNumTemplateArguments(); return 0; } lldb::SBType SBType::GetTemplateArgumentType (uint32_t idx) { if (IsValid()) { TemplateArgumentKind kind = eTemplateArgumentKindNull; ClangASTType template_arg_type = m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); if (template_arg_type.IsValid()) return SBType(template_arg_type); } return SBType(); } lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind (uint32_t idx) { TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); return kind; } SBTypeList::SBTypeList() : m_opaque_ap(new TypeListImpl()) { } SBTypeList::SBTypeList(const SBTypeList& rhs) : m_opaque_ap(new TypeListImpl()) { for (uint32_t i = 0, rhs_size = const_cast(rhs).GetSize(); i < rhs_size; i++) Append(const_cast(rhs).GetTypeAtIndex(i)); } bool SBTypeList::IsValid () { return (m_opaque_ap.get() != NULL); } SBTypeList& SBTypeList::operator = (const SBTypeList& rhs) { if (this != &rhs) { m_opaque_ap.reset (new TypeListImpl()); for (uint32_t i = 0, rhs_size = const_cast(rhs).GetSize(); i < rhs_size; i++) Append(const_cast(rhs).GetTypeAtIndex(i)); } return *this; } void SBTypeList::Append (SBType type) { if (type.IsValid()) m_opaque_ap->Append (type.m_opaque_sp); } SBType SBTypeList::GetTypeAtIndex(uint32_t index) { if (m_opaque_ap.get()) return SBType(m_opaque_ap->GetTypeAtIndex(index)); return SBType(); } uint32_t SBTypeList::GetSize() { return m_opaque_ap->GetSize(); } SBTypeList::~SBTypeList() { } SBTypeMember::SBTypeMember() : m_opaque_ap() { } SBTypeMember::~SBTypeMember() { } SBTypeMember::SBTypeMember (const SBTypeMember& rhs) : m_opaque_ap() { if (this != &rhs) { if (rhs.IsValid()) m_opaque_ap.reset(new TypeMemberImpl(rhs.ref())); } } lldb::SBTypeMember& SBTypeMember::operator = (const lldb::SBTypeMember& rhs) { if (this != &rhs) { if (rhs.IsValid()) m_opaque_ap.reset(new TypeMemberImpl(rhs.ref())); } return *this; } bool SBTypeMember::IsValid() const { return m_opaque_ap.get(); } const char * SBTypeMember::GetName () { if (m_opaque_ap.get()) return m_opaque_ap->GetName().GetCString(); return NULL; } SBType SBTypeMember::GetType () { SBType sb_type; if (m_opaque_ap.get()) { sb_type.SetSP (m_opaque_ap->GetTypeImpl()); } return sb_type; } uint64_t SBTypeMember::GetOffsetInBytes() { if (m_opaque_ap.get()) return m_opaque_ap->GetBitOffset() / 8u; return 0; } uint64_t SBTypeMember::GetOffsetInBits() { if (m_opaque_ap.get()) return m_opaque_ap->GetBitOffset(); return 0; } bool SBTypeMember::IsBitfield() { if (m_opaque_ap.get()) return m_opaque_ap->GetIsBitfield(); return false; } uint32_t SBTypeMember::GetBitfieldSizeInBits() { if (m_opaque_ap.get()) return m_opaque_ap->GetBitfieldBitSize(); return 0; } bool SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level) { Stream &strm = description.ref(); if (m_opaque_ap.get()) { const uint32_t bit_offset = m_opaque_ap->GetBitOffset(); const uint32_t byte_offset = bit_offset / 8u; const uint32_t byte_bit_offset = bit_offset % 8u; const char *name = m_opaque_ap->GetName().GetCString(); if (byte_bit_offset) strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset); else strm.Printf ("+%u: (", byte_offset); TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl()); if (type_impl_sp) type_impl_sp->GetDescription(strm, description_level); strm.Printf (") %s", name); if (m_opaque_ap->GetIsBitfield()) { const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize(); strm.Printf (" : %u", bitfield_bit_size); } } else { strm.PutCString ("No value"); } return true; } void SBTypeMember::reset(TypeMemberImpl *type_member_impl) { m_opaque_ap.reset(type_member_impl); } TypeMemberImpl & SBTypeMember::ref () { if (m_opaque_ap.get() == NULL) m_opaque_ap.reset (new TypeMemberImpl()); return *m_opaque_ap.get(); } const TypeMemberImpl & SBTypeMember::ref () const { return *m_opaque_ap.get(); }