//===-- Type.cpp ------------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include #include "lldb/Core/Module.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/StreamString.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "llvm/ADT/StringRef.h" using namespace lldb; using namespace lldb_private; bool lldb_private::contextMatches(llvm::ArrayRef context_chain, llvm::ArrayRef pattern) { auto ctx = context_chain.begin(); auto ctx_end = context_chain.end(); for (const CompilerContext &pat : pattern) { // Early exit if the pattern is too long. if (ctx == ctx_end) return false; if (*ctx != pat) { // Skip any number of module matches. if (pat.kind == CompilerContextKind::AnyModule) { // Greedily match 0..n modules. ctx = std::find_if(ctx, ctx_end, [](const CompilerContext &ctx) { return ctx.kind != CompilerContextKind::Module; }); continue; } // See if there is a kind mismatch; they should have 1 bit in common. if (((uint16_t)ctx->kind & (uint16_t)pat.kind) == 0) return false; // The name is ignored for AnyModule, but not for AnyType. if (pat.kind != CompilerContextKind::AnyModule && ctx->name != pat.name) return false; } ++ctx; } return true; } void CompilerContext::Dump() const { switch (kind) { default: printf("Invalid"); break; case CompilerContextKind::TranslationUnit: printf("TranslationUnit"); break; case CompilerContextKind::Module: printf("Module"); break; case CompilerContextKind::Namespace: printf("Namespace"); break; case CompilerContextKind::Class: printf("Class"); break; case CompilerContextKind::Struct: printf("Structure"); break; case CompilerContextKind::Union: printf("Union"); break; case CompilerContextKind::Function: printf("Function"); break; case CompilerContextKind::Variable: printf("Variable"); break; case CompilerContextKind::Enum: printf("Enumeration"); break; case CompilerContextKind::Typedef: printf("Typedef"); break; case CompilerContextKind::AnyModule: printf("AnyModule"); break; case CompilerContextKind::AnyType: printf("AnyType"); break; } printf("(\"%s\")\n", name.GetCString()); } class TypeAppendVisitor { public: TypeAppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {} bool operator()(const lldb::TypeSP &type) { m_type_list.Append(TypeImplSP(new TypeImpl(type))); return true; } private: TypeListImpl &m_type_list; }; void TypeListImpl::Append(const lldb_private::TypeList &type_list) { TypeAppendVisitor cb(*this); type_list.ForEach(cb); } SymbolFileType::SymbolFileType(SymbolFile &symbol_file, const lldb::TypeSP &type_sp) : UserID(type_sp ? type_sp->GetID() : LLDB_INVALID_UID), m_symbol_file(symbol_file), m_type_sp(type_sp) {} Type *SymbolFileType::GetType() { if (!m_type_sp) { Type *resolved_type = m_symbol_file.ResolveTypeUID(GetID()); if (resolved_type) m_type_sp = resolved_type->shared_from_this(); } return m_type_sp.get(); } Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, llvm::Optional byte_size, SymbolContextScope *context, user_id_t encoding_uid, EncodingDataType encoding_uid_type, const Declaration &decl, const CompilerType &compiler_type, ResolveState compiler_type_resolve_state) : std::enable_shared_from_this(), UserID(uid), m_name(name), m_symbol_file(symbol_file), m_context(context), m_encoding_type(nullptr), m_encoding_uid(encoding_uid), m_encoding_uid_type(encoding_uid_type), m_decl(decl), m_compiler_type(compiler_type) { if (byte_size) { m_byte_size = *byte_size; m_byte_size_has_value = true; } else { m_byte_size = 0; m_byte_size_has_value = false; } m_flags.compiler_type_resolve_state = (compiler_type ? compiler_type_resolve_state : eResolveStateUnresolved); m_flags.is_complete_objc_class = false; } Type::Type() : std::enable_shared_from_this(), UserID(0), m_name(""), m_symbol_file(nullptr), m_context(nullptr), m_encoding_type(nullptr), m_encoding_uid(LLDB_INVALID_UID), m_encoding_uid_type(eEncodingInvalid), m_byte_size(0), m_byte_size_has_value(false), m_decl(), m_compiler_type() { m_flags.compiler_type_resolve_state = eResolveStateUnresolved; m_flags.is_complete_objc_class = false; } void Type::GetDescription(Stream *s, lldb::DescriptionLevel level, bool show_name) { *s << "id = " << (const UserID &)*this; // Call the name accessor to make sure we resolve the type name if (show_name) { ConstString type_name = GetName(); if (type_name) { *s << ", name = \"" << type_name << '"'; ConstString qualified_type_name(GetQualifiedName()); if (qualified_type_name != type_name) { *s << ", qualified = \"" << qualified_type_name << '"'; } } } // Call the get byte size accesor so we resolve our byte size if (GetByteSize()) s->Printf(", byte-size = %" PRIu64, m_byte_size); bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); m_decl.Dump(s, show_fullpaths); if (m_compiler_type.IsValid()) { *s << ", compiler_type = \""; GetForwardCompilerType().DumpTypeDescription(s); *s << '"'; } else if (m_encoding_uid != LLDB_INVALID_UID) { s->Printf(", type_uid = 0x%8.8" PRIx64, m_encoding_uid); switch (m_encoding_uid_type) { case eEncodingInvalid: break; case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; } } } void Type::Dump(Stream *s, bool show_context) { s->Printf("%p: ", static_cast(this)); s->Indent(); *s << "Type" << static_cast(*this) << ' '; if (m_name) *s << ", name = \"" << m_name << "\""; if (m_byte_size_has_value) s->Printf(", size = %" PRIu64, m_byte_size); if (show_context && m_context != nullptr) { s->PutCString(", context = ( "); m_context->DumpSymbolContext(s); s->PutCString(" )"); } bool show_fullpaths = false; m_decl.Dump(s, show_fullpaths); if (m_compiler_type.IsValid()) { *s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' '; GetForwardCompilerType().DumpTypeDescription(s); } else if (m_encoding_uid != LLDB_INVALID_UID) { *s << ", type_data = " << (uint64_t)m_encoding_uid; switch (m_encoding_uid_type) { case eEncodingInvalid: break; case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; } } // // if (m_access) // s->Printf(", access = %u", m_access); s->EOL(); } ConstString Type::GetName() { if (!m_name) m_name = GetForwardCompilerType().GetConstTypeName(); return m_name; } void Type::DumpTypeName(Stream *s) { GetName().Dump(s, ""); } void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data, uint32_t data_byte_offset, bool show_types, bool show_summary, bool verbose, lldb::Format format) { if (ResolveClangType(eResolveStateForward)) { if (show_types) { s->PutChar('('); if (verbose) s->Printf("Type{0x%8.8" PRIx64 "} ", GetID()); DumpTypeName(s); s->PutCString(") "); } GetForwardCompilerType().DumpValue( exe_ctx, s, format == lldb::eFormatDefault ? GetFormat() : format, data, data_byte_offset, GetByteSize().getValueOr(0), 0, // Bitfield bit size 0, // Bitfield bit offset show_types, show_summary, verbose, 0); } } Type *Type::GetEncodingType() { if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID) m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); return m_encoding_type; } llvm::Optional Type::GetByteSize() { if (m_byte_size_has_value) return m_byte_size; switch (m_encoding_uid_type) { case eEncodingInvalid: case eEncodingIsSyntheticUID: break; case eEncodingIsUID: case eEncodingIsConstUID: case eEncodingIsRestrictUID: case eEncodingIsVolatileUID: case eEncodingIsTypedefUID: { Type *encoding_type = GetEncodingType(); if (encoding_type) if (llvm::Optional size = encoding_type->GetByteSize()) { m_byte_size = *size; m_byte_size_has_value = true; return m_byte_size; } if (llvm::Optional size = GetLayoutCompilerType().GetByteSize(nullptr)) { m_byte_size = *size; m_byte_size_has_value = true; return m_byte_size; } } break; // If we are a pointer or reference, then this is just a pointer size; case eEncodingIsPointerUID: case eEncodingIsLValueReferenceUID: case eEncodingIsRValueReferenceUID: { if (ArchSpec arch = m_symbol_file->GetObjectFile()->GetArchitecture()) { m_byte_size = arch.GetAddressByteSize(); m_byte_size_has_value = true; } } break; } return {}; } uint32_t Type::GetNumChildren(bool omit_empty_base_classes) { return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes, nullptr); } bool Type::IsAggregateType() { return GetForwardCompilerType().IsAggregateType(); } lldb::TypeSP Type::GetTypedefType() { lldb::TypeSP type_sp; if (IsTypedef()) { Type *typedef_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); if (typedef_type) type_sp = typedef_type->shared_from_this(); } return type_sp; } lldb::Format Type::GetFormat() { return GetForwardCompilerType().GetFormat(); } lldb::Encoding Type::GetEncoding(uint64_t &count) { // Make sure we resolve our type if it already hasn't been. return GetForwardCompilerType().GetEncoding(count); } bool Type::DumpValueInMemory(ExecutionContext *exe_ctx, Stream *s, lldb::addr_t address, AddressType address_type, bool show_types, bool show_summary, bool verbose) { if (address != LLDB_INVALID_ADDRESS) { DataExtractor data; Target *target = nullptr; if (exe_ctx) target = exe_ctx->GetTargetPtr(); if (target) data.SetByteOrder(target->GetArchitecture().GetByteOrder()); if (ReadFromMemory(exe_ctx, address, address_type, data)) { DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose); return true; } } return false; } bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) { if (address_type == eAddressTypeFile) { // Can't convert a file address to anything valid without more context // (which Module it came from) return false; } const uint64_t byte_size = GetByteSize().getValueOr(0); if (data.GetByteSize() < byte_size) { lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); data.SetData(data_sp); } uint8_t *dst = const_cast(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it if (addr == 0) return false; memcpy(dst, reinterpret_cast(addr), byte_size); return true; } else { if (exe_ctx) { Process *process = exe_ctx->GetProcessPtr(); if (process) { Status error; return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, error) == byte_size; } } } } return false; } bool Type::WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) { return false; } const Declaration &Type::GetDeclaration() const { return m_decl; } bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) { // TODO: This needs to consider the correct type system to use. Type *encoding_type = nullptr; if (!m_compiler_type.IsValid()) { encoding_type = GetEncodingType(); if (encoding_type) { switch (m_encoding_uid_type) { case eEncodingIsUID: { CompilerType encoding_compiler_type = encoding_type->GetForwardCompilerType(); if (encoding_compiler_type.IsValid()) { m_compiler_type = encoding_compiler_type; m_flags.compiler_type_resolve_state = encoding_type->m_flags.compiler_type_resolve_state; } } break; case eEncodingIsConstUID: m_compiler_type = encoding_type->GetForwardCompilerType().AddConstModifier(); break; case eEncodingIsRestrictUID: m_compiler_type = encoding_type->GetForwardCompilerType().AddRestrictModifier(); break; case eEncodingIsVolatileUID: m_compiler_type = encoding_type->GetForwardCompilerType().AddVolatileModifier(); break; case eEncodingIsTypedefUID: m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef( m_name.AsCString("__lldb_invalid_typedef_name"), GetSymbolFile()->GetDeclContextContainingUID(GetID())); m_name.Clear(); break; case eEncodingIsPointerUID: m_compiler_type = encoding_type->GetForwardCompilerType().GetPointerType(); break; case eEncodingIsLValueReferenceUID: m_compiler_type = encoding_type->GetForwardCompilerType().GetLValueReferenceType(); break; case eEncodingIsRValueReferenceUID: m_compiler_type = encoding_type->GetForwardCompilerType().GetRValueReferenceType(); break; default: llvm_unreachable("Unhandled encoding_data_type."); } } else { // We have no encoding type, return void? auto type_system_or_err = m_symbol_file->GetTypeSystemForLanguage(eLanguageTypeC); if (auto err = type_system_or_err.takeError()) { LLDB_LOG_ERROR( lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), std::move(err), "Unable to construct void type from ClangASTContext"); } else { CompilerType void_compiler_type = type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid); switch (m_encoding_uid_type) { case eEncodingIsUID: m_compiler_type = void_compiler_type; break; case eEncodingIsConstUID: m_compiler_type = void_compiler_type.AddConstModifier(); break; case eEncodingIsRestrictUID: m_compiler_type = void_compiler_type.AddRestrictModifier(); break; case eEncodingIsVolatileUID: m_compiler_type = void_compiler_type.AddVolatileModifier(); break; case eEncodingIsTypedefUID: m_compiler_type = void_compiler_type.CreateTypedef( m_name.AsCString("__lldb_invalid_typedef_name"), GetSymbolFile()->GetDeclContextContainingUID(GetID())); break; case eEncodingIsPointerUID: m_compiler_type = void_compiler_type.GetPointerType(); break; case eEncodingIsLValueReferenceUID: m_compiler_type = void_compiler_type.GetLValueReferenceType(); break; case eEncodingIsRValueReferenceUID: m_compiler_type = void_compiler_type.GetRValueReferenceType(); break; default: llvm_unreachable("Unhandled encoding_data_type."); } } } // When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is // set to eResolveStateUnresolved so we need to update it to say that we // now have a forward declaration since that is what we created above. if (m_compiler_type.IsValid()) m_flags.compiler_type_resolve_state = eResolveStateForward; } // Check if we have a forward reference to a class/struct/union/enum? if (compiler_type_resolve_state == eResolveStateLayout || compiler_type_resolve_state == eResolveStateFull) { // Check if we have a forward reference to a class/struct/union/enum? if (m_compiler_type.IsValid() && m_flags.compiler_type_resolve_state < compiler_type_resolve_state) { m_flags.compiler_type_resolve_state = eResolveStateFull; if (!m_compiler_type.IsDefined()) { // We have a forward declaration, we need to resolve it to a complete // definition. m_symbol_file->CompleteType(m_compiler_type); } } } // If we have an encoding type, then we need to make sure it is resolved // appropriately. if (m_encoding_uid != LLDB_INVALID_UID) { if (encoding_type == nullptr) encoding_type = GetEncodingType(); if (encoding_type) { ResolveState encoding_compiler_type_resolve_state = compiler_type_resolve_state; if (compiler_type_resolve_state == eResolveStateLayout) { switch (m_encoding_uid_type) { case eEncodingIsPointerUID: case eEncodingIsLValueReferenceUID: case eEncodingIsRValueReferenceUID: encoding_compiler_type_resolve_state = eResolveStateForward; break; default: break; } } encoding_type->ResolveClangType(encoding_compiler_type_resolve_state); } } return m_compiler_type.IsValid(); } uint32_t Type::GetEncodingMask() { uint32_t encoding_mask = 1u << m_encoding_uid_type; Type *encoding_type = GetEncodingType(); assert(encoding_type != this); if (encoding_type) encoding_mask |= encoding_type->GetEncodingMask(); return encoding_mask; } CompilerType Type::GetFullCompilerType() { ResolveClangType(eResolveStateFull); return m_compiler_type; } CompilerType Type::GetLayoutCompilerType() { ResolveClangType(eResolveStateLayout); return m_compiler_type; } CompilerType Type::GetForwardCompilerType() { ResolveClangType(eResolveStateForward); return m_compiler_type; } int Type::Compare(const Type &a, const Type &b) { // Just compare the UID values for now... lldb::user_id_t a_uid = a.GetID(); lldb::user_id_t b_uid = b.GetID(); if (a_uid < b_uid) return -1; if (a_uid > b_uid) return 1; return 0; } ConstString Type::GetQualifiedName() { return GetForwardCompilerType().GetConstTypeName(); } bool Type::GetTypeScopeAndBasename(const llvm::StringRef& name, llvm::StringRef &scope, llvm::StringRef &basename, TypeClass &type_class) { type_class = eTypeClassAny; if (name.empty()) return false; basename = name; if (basename.consume_front("struct ")) type_class = eTypeClassStruct; else if (basename.consume_front("class ")) type_class = eTypeClassClass; else if (basename.consume_front("union ")) type_class = eTypeClassUnion; else if (basename.consume_front("enum ")) type_class = eTypeClassEnumeration; else if (basename.consume_front("typedef ")) type_class = eTypeClassTypedef; size_t namespace_separator = basename.find("::"); if (namespace_separator == llvm::StringRef::npos) return false; size_t template_begin = basename.find('<'); while (namespace_separator != llvm::StringRef::npos) { if (template_begin != llvm::StringRef::npos && namespace_separator > template_begin) { size_t template_depth = 1; llvm::StringRef template_arg = basename.drop_front(template_begin + 1); while (template_depth > 0 && !template_arg.empty()) { if (template_arg.front() == '<') template_depth++; else if (template_arg.front() == '>') template_depth--; template_arg = template_arg.drop_front(1); } if (template_depth != 0) return false; // We have an invalid type name. Bail out. if (template_arg.empty()) break; // The template ends at the end of the full name. basename = template_arg; } else { basename = basename.drop_front(namespace_separator + 2); } template_begin = basename.find('<'); namespace_separator = basename.find("::"); } if (basename.size() < name.size()) { scope = name.take_front(name.size() - basename.size()); return true; } return false; } ModuleSP Type::GetModule() { if (m_symbol_file) return m_symbol_file->GetObjectFile()->GetModule(); return ModuleSP(); } TypeAndOrName::TypeAndOrName(TypeSP &in_type_sp) { if (in_type_sp) { m_compiler_type = in_type_sp->GetForwardCompilerType(); m_type_name = in_type_sp->GetName(); } } TypeAndOrName::TypeAndOrName(const char *in_type_str) : m_type_name(in_type_str) {} TypeAndOrName::TypeAndOrName(ConstString &in_type_const_string) : m_type_name(in_type_const_string) {} bool TypeAndOrName::operator==(const TypeAndOrName &other) const { if (m_compiler_type != other.m_compiler_type) return false; if (m_type_name != other.m_type_name) return false; return true; } bool TypeAndOrName::operator!=(const TypeAndOrName &other) const { return !(*this == other); } ConstString TypeAndOrName::GetName() const { if (m_type_name) return m_type_name; if (m_compiler_type) return m_compiler_type.GetTypeName(); return ConstString(""); } void TypeAndOrName::SetName(ConstString type_name) { m_type_name = type_name; } void TypeAndOrName::SetName(const char *type_name_cstr) { m_type_name.SetCString(type_name_cstr); } void TypeAndOrName::SetTypeSP(lldb::TypeSP type_sp) { if (type_sp) { m_compiler_type = type_sp->GetForwardCompilerType(); m_type_name = type_sp->GetName(); } else Clear(); } void TypeAndOrName::SetCompilerType(CompilerType compiler_type) { m_compiler_type = compiler_type; if (m_compiler_type) m_type_name = m_compiler_type.GetTypeName(); } bool TypeAndOrName::IsEmpty() const { return !((bool)m_type_name || (bool)m_compiler_type); } void TypeAndOrName::Clear() { m_type_name.Clear(); m_compiler_type.Clear(); } bool TypeAndOrName::HasName() const { return (bool)m_type_name; } bool TypeAndOrName::HasCompilerType() const { return m_compiler_type.IsValid(); } TypeImpl::TypeImpl(const lldb::TypeSP &type_sp) : m_module_wp(), m_static_type(), m_dynamic_type() { SetType(type_sp); } TypeImpl::TypeImpl(const CompilerType &compiler_type) : m_module_wp(), m_static_type(), m_dynamic_type() { SetType(compiler_type); } TypeImpl::TypeImpl(const lldb::TypeSP &type_sp, const CompilerType &dynamic) : m_module_wp(), m_static_type(), m_dynamic_type(dynamic) { SetType(type_sp, dynamic); } TypeImpl::TypeImpl(const CompilerType &static_type, const CompilerType &dynamic_type) : m_module_wp(), m_static_type(), m_dynamic_type() { SetType(static_type, dynamic_type); } void TypeImpl::SetType(const lldb::TypeSP &type_sp) { if (type_sp) { m_static_type = type_sp->GetForwardCompilerType(); m_module_wp = type_sp->GetModule(); } else { m_static_type.Clear(); m_module_wp = lldb::ModuleWP(); } } void TypeImpl::SetType(const CompilerType &compiler_type) { m_module_wp = lldb::ModuleWP(); m_static_type = compiler_type; } void TypeImpl::SetType(const lldb::TypeSP &type_sp, const CompilerType &dynamic) { SetType(type_sp); m_dynamic_type = dynamic; } void TypeImpl::SetType(const CompilerType &compiler_type, const CompilerType &dynamic) { m_module_wp = lldb::ModuleWP(); m_static_type = compiler_type; m_dynamic_type = dynamic; } bool TypeImpl::CheckModule(lldb::ModuleSP &module_sp) const { // Check if we have a module for this type. If we do and the shared pointer // is can be successfully initialized with m_module_wp, return true. Else // return false if we didn't have a module, or if we had a module and it has // been deleted. Any functions doing anything with a TypeSP in this TypeImpl // class should call this function and only do anything with the ivars if // this function returns true. If we have a module, the "module_sp" will be // filled in with a strong reference to the module so that the module will at // least stay around long enough for the type query to succeed. module_sp = m_module_wp.lock(); if (!module_sp) { lldb::ModuleWP empty_module_wp; // If either call to "std::weak_ptr::owner_before(...) value returns true, // this indicates that m_module_wp once contained (possibly still does) a // reference to a valid shared pointer. This helps us know if we had a // valid reference to a section which is now invalid because the module it // was in was deleted if (empty_module_wp.owner_before(m_module_wp) || m_module_wp.owner_before(empty_module_wp)) { // m_module_wp had a valid reference to a module, but all strong // references have been released and the module has been deleted return false; } } // We either successfully locked the module, or didn't have one to begin with return true; } bool TypeImpl::operator==(const TypeImpl &rhs) const { return m_static_type == rhs.m_static_type && m_dynamic_type == rhs.m_dynamic_type; } bool TypeImpl::operator!=(const TypeImpl &rhs) const { return !(*this == rhs); } bool TypeImpl::IsValid() const { // just a name is not valid ModuleSP module_sp; if (CheckModule(module_sp)) return m_static_type.IsValid() || m_dynamic_type.IsValid(); return false; } TypeImpl::operator bool() const { return IsValid(); } void TypeImpl::Clear() { m_module_wp = lldb::ModuleWP(); m_static_type.Clear(); m_dynamic_type.Clear(); } ConstString TypeImpl::GetName() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type) return m_dynamic_type.GetTypeName(); return m_static_type.GetTypeName(); } return ConstString(); } ConstString TypeImpl::GetDisplayTypeName() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type) return m_dynamic_type.GetDisplayTypeName(); return m_static_type.GetDisplayTypeName(); } return ConstString(); } TypeImpl TypeImpl::GetPointerType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetPointerType(), m_dynamic_type.GetPointerType()); } return TypeImpl(m_static_type.GetPointerType()); } return TypeImpl(); } TypeImpl TypeImpl::GetPointeeType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetPointeeType(), m_dynamic_type.GetPointeeType()); } return TypeImpl(m_static_type.GetPointeeType()); } return TypeImpl(); } TypeImpl TypeImpl::GetReferenceType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetLValueReferenceType(), m_dynamic_type.GetLValueReferenceType()); } return TypeImpl(m_static_type.GetLValueReferenceType()); } return TypeImpl(); } TypeImpl TypeImpl::GetTypedefedType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetTypedefedType(), m_dynamic_type.GetTypedefedType()); } return TypeImpl(m_static_type.GetTypedefedType()); } return TypeImpl(); } TypeImpl TypeImpl::GetDereferencedType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetNonReferenceType(), m_dynamic_type.GetNonReferenceType()); } return TypeImpl(m_static_type.GetNonReferenceType()); } return TypeImpl(); } TypeImpl TypeImpl::GetUnqualifiedType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetFullyUnqualifiedType(), m_dynamic_type.GetFullyUnqualifiedType()); } return TypeImpl(m_static_type.GetFullyUnqualifiedType()); } return TypeImpl(); } TypeImpl TypeImpl::GetCanonicalType() const { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { return TypeImpl(m_static_type.GetCanonicalType(), m_dynamic_type.GetCanonicalType()); } return TypeImpl(m_static_type.GetCanonicalType()); } return TypeImpl(); } CompilerType TypeImpl::GetCompilerType(bool prefer_dynamic) { ModuleSP module_sp; if (CheckModule(module_sp)) { if (prefer_dynamic) { if (m_dynamic_type.IsValid()) return m_dynamic_type; } return m_static_type; } return CompilerType(); } TypeSystem *TypeImpl::GetTypeSystem(bool prefer_dynamic) { ModuleSP module_sp; if (CheckModule(module_sp)) { if (prefer_dynamic) { if (m_dynamic_type.IsValid()) return m_dynamic_type.GetTypeSystem(); } return m_static_type.GetTypeSystem(); } return nullptr; } bool TypeImpl::GetDescription(lldb_private::Stream &strm, lldb::DescriptionLevel description_level) { ModuleSP module_sp; if (CheckModule(module_sp)) { if (m_dynamic_type.IsValid()) { strm.Printf("Dynamic:\n"); m_dynamic_type.DumpTypeDescription(&strm); strm.Printf("\nStatic:\n"); } m_static_type.DumpTypeDescription(&strm); } else { strm.PutCString("Invalid TypeImpl module for type has been deleted\n"); } return true; } bool TypeMemberFunctionImpl::IsValid() { return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; } ConstString TypeMemberFunctionImpl::GetName() const { return m_name; } ConstString TypeMemberFunctionImpl::GetMangledName() const { return m_decl.GetMangledName(); } CompilerType TypeMemberFunctionImpl::GetType() const { return m_type; } lldb::MemberFunctionKind TypeMemberFunctionImpl::GetKind() const { return m_kind; } bool TypeMemberFunctionImpl::GetDescription(Stream &stream) { switch (m_kind) { case lldb::eMemberFunctionKindUnknown: return false; case lldb::eMemberFunctionKindConstructor: stream.Printf("constructor for %s", m_type.GetTypeName().AsCString("")); break; case lldb::eMemberFunctionKindDestructor: stream.Printf("destructor for %s", m_type.GetTypeName().AsCString("")); break; case lldb::eMemberFunctionKindInstanceMethod: stream.Printf("instance method %s of type %s", m_name.AsCString(), m_decl.GetDeclContext().GetName().AsCString()); break; case lldb::eMemberFunctionKindStaticMethod: stream.Printf("static method %s of type %s", m_name.AsCString(), m_decl.GetDeclContext().GetName().AsCString()); break; } return true; } CompilerType TypeMemberFunctionImpl::GetReturnType() const { if (m_type) return m_type.GetFunctionReturnType(); return m_decl.GetFunctionReturnType(); } size_t TypeMemberFunctionImpl::GetNumArguments() const { if (m_type) return m_type.GetNumberOfFunctionArguments(); else return m_decl.GetNumFunctionArguments(); } CompilerType TypeMemberFunctionImpl::GetArgumentAtIndex(size_t idx) const { if (m_type) return m_type.GetFunctionArgumentAtIndex(idx); else return m_decl.GetFunctionArgumentType(idx); } TypeEnumMemberImpl::TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, ConstString name, const llvm::APSInt &value) : m_integer_type_sp(integer_type_sp), m_name(name), m_value(value), m_valid((bool)name && (bool)integer_type_sp) {}