diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBModule.cpp | 35 | ||||
-rw-r--r-- | lldb/source/API/SBTarget.cpp | 47 | ||||
-rw-r--r-- | lldb/source/API/SBValueList.cpp | 44 | ||||
-rw-r--r-- | lldb/source/Core/Value.cpp | 78 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 190 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectList.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectVariable.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 144 |
8 files changed, 418 insertions, 132 deletions
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index 0c4eba43e56..53172f349ca 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -15,6 +15,10 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -307,3 +311,34 @@ SBModule::FindFunctions (const char *name, return 0; } + +SBValueList +SBModule::FindGlobalVariables (SBTarget &target, const char *name, uint32_t max_matches) +{ + SBValueList sb_value_list; + if (m_opaque_sp) + { + VariableList variable_list; + const uint32_t match_count = m_opaque_sp->FindGlobalVariables (ConstString (name), + false, + max_matches, + variable_list); + + if (match_count > 0) + { + ValueObjectList &value_object_list = sb_value_list.ref(); + for (uint32_t i=0; i<match_count; ++i) + { + lldb::ValueObjectSP valobj_sp; + if (target.IsValid()) + valobj_sp = ValueObjectVariable::Create (target.get(), variable_list.GetVariableAtIndex(i)); + else + valobj_sp = ValueObjectVariable::Create (NULL, variable_list.GetVariableAtIndex(i)); + if (valobj_sp) + value_object_list.Append(valobj_sp); + } + } + } + + return sb_value_list; +} diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 7098604b0ef..6a17bb4cc69 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -11,8 +11,12 @@ #include "lldb/lldb-public.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBListener.h" #include "lldb/API/SBModule.h" +#include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBSymbolContextList.h" #include "lldb/Breakpoint/BreakpointID.h" @@ -22,16 +26,19 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressResolver.h" #include "lldb/Core/AddressResolverName.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/STLUtils.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" @@ -39,10 +46,6 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "../source/Commands/CommandObjectBreakpoint.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBProcess.h" -#include "lldb/API/SBListener.h" -#include "lldb/API/SBBreakpoint.h" using namespace lldb; using namespace lldb_private; @@ -872,3 +875,35 @@ SBTarget::FindFunctions (const char *name, return 0; } +SBValueList +SBTarget::FindGlobalVariables (const char *name, uint32_t max_matches) +{ + SBValueList sb_value_list; + + if (m_opaque_sp) + { + VariableList variable_list; + const bool append = true; + const uint32_t match_count = m_opaque_sp->GetImages().FindGlobalVariables (ConstString (name), + append, + max_matches, + variable_list); + + if (match_count > 0) + { + ExecutionContextScope *exe_scope = m_opaque_sp->GetProcessSP().get(); + if (exe_scope == NULL) + exe_scope = m_opaque_sp.get(); + ValueObjectList &value_object_list = sb_value_list.ref(); + for (uint32_t i=0; i<match_count; ++i) + { + lldb::ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_scope, variable_list.GetVariableAtIndex(i))); + if (valobj_sp) + value_object_list.Append(valobj_sp); + } + } + } + + return sb_value_list; +} + diff --git a/lldb/source/API/SBValueList.cpp b/lldb/source/API/SBValueList.cpp index bcddedfaf83..4e0fea5688c 100644 --- a/lldb/source/API/SBValueList.cpp +++ b/lldb/source/API/SBValueList.cpp @@ -25,10 +25,10 @@ SBValueList::SBValueList () : SBValueList::SBValueList (const SBValueList &rhs) : m_opaque_ap () { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (rhs.IsValid()) - m_opaque_ap.reset (new lldb_private::ValueObjectList (*rhs)); + m_opaque_ap.reset (new ValueObjectList (*rhs)); if (log) { @@ -38,13 +38,13 @@ SBValueList::SBValueList (const SBValueList &rhs) : } } -SBValueList::SBValueList (const lldb_private::ValueObjectList *lldb_object_ptr) : +SBValueList::SBValueList (const ValueObjectList *lldb_object_ptr) : m_opaque_ap () { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (lldb_object_ptr) - m_opaque_ap.reset (new lldb_private::ValueObjectList (*lldb_object_ptr)); + m_opaque_ap.reset (new ValueObjectList (*lldb_object_ptr)); if (log) { @@ -70,32 +70,32 @@ SBValueList::operator = (const SBValueList &rhs) if (this != &rhs) { if (rhs.IsValid()) - m_opaque_ap.reset (new lldb_private::ValueObjectList (*rhs)); + m_opaque_ap.reset (new ValueObjectList (*rhs)); else m_opaque_ap.reset (); } return *this; } -lldb_private::ValueObjectList * +ValueObjectList * SBValueList::operator->() { return m_opaque_ap.get(); } -lldb_private::ValueObjectList & +ValueObjectList & SBValueList::operator*() { return *m_opaque_ap; } -const lldb_private::ValueObjectList * +const ValueObjectList * SBValueList::operator->() const { return m_opaque_ap.get(); } -const lldb_private::ValueObjectList & +const ValueObjectList & SBValueList::operator*() const { return *m_opaque_ap; @@ -121,11 +121,21 @@ SBValueList::Append (lldb::ValueObjectSP& val_obj_sp) } } +void +SBValueList::Append (const lldb::SBValueList& value_list) +{ + if (value_list.IsValid()) + { + CreateIfNeeded (); + m_opaque_ap->Append (*value_list); + } +} + SBValue SBValueList::GetValueAtIndex (uint32_t idx) const { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); //if (log) // log->Printf ("SBValueList::GetValueAtIndex (uint32_t idx) idx = %d", idx); @@ -148,7 +158,7 @@ SBValueList::GetValueAtIndex (uint32_t idx) const uint32_t SBValueList::GetSize () const { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); //if (log) // log->Printf ("SBValueList::GetSize ()"); @@ -180,9 +190,17 @@ SBValueList::FindValueObjectByUID (lldb::user_id_t uid) return sb_value; } -lldb_private::ValueObjectList * +ValueObjectList * SBValueList::get () { return m_opaque_ap.get(); } +ValueObjectList & +SBValueList::ref () +{ + CreateIfNeeded(); + return *m_opaque_ap.get(); +} + + diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index 2d8ac9147ce..2ba490ebb0a 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -516,6 +516,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context Error error; lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; + Address file_so_addr; switch (m_value_type) { default: @@ -541,11 +542,11 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context case eValueTypeLoadAddress: if (exe_ctx == NULL) { - error.SetErrorString ("can't read memory (no execution context)"); + error.SetErrorString ("can't read load address (no execution context)"); } else if (exe_ctx->process == NULL) { - error.SetErrorString ("can't read memory (invalid process)"); + error.SetErrorString ("can't read load address (invalid process)"); } else { @@ -557,6 +558,15 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context break; case eValueTypeFileAddress: + if (exe_ctx == NULL) + { + error.SetErrorString ("can't read file address (no execution context)"); + } + else if (exe_ctx->target == NULL) + { + error.SetErrorString ("can't read file address (invalid target)"); + } + else { // The only thing we can currently lock down to a module so that // we can resolve a file address, is a variable. @@ -564,9 +574,10 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context if (GetVariable()) { - lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - if (file_addr != LLDB_INVALID_ADDRESS) + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + if (address != LLDB_INVALID_ADDRESS) { + bool resolved = false; SymbolContext var_sc; variable->CalculateSymbolContext(&var_sc); if (var_sc.module_sp) @@ -574,31 +585,46 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); if (objfile) { - Address so_addr(file_addr, objfile->GetSectionList()); - address = so_addr.GetLoadAddress (exe_ctx->target); - if (address != LLDB_INVALID_ADDRESS) + Address so_addr(address, objfile->GetSectionList()); + addr_t load_address = so_addr.GetLoadAddress (exe_ctx->target); + if (load_address != LLDB_INVALID_ADDRESS) { + resolved = true; + address = load_address; address_type = eAddressTypeLoad; data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize()); } else { - data.SetByteOrder(objfile->GetByteOrder()); - data.SetAddressByteSize(objfile->GetAddressByteSize()); + if (so_addr.IsSectionOffset()) + { + resolved = true; + file_so_addr = so_addr; + data.SetByteOrder(objfile->GetByteOrder()); + data.SetAddressByteSize(objfile->GetAddressByteSize()); + } } } - if (address_type == eAddressTypeFile) - error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString()); } - else + if (!resolved) { - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", file_addr, variable->GetName().AsCString("")); + if (var_sc.module_sp) + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", + address, + variable->GetName().AsCString(""), + var_sc.module_sp->GetFileSpec().GetDirectory().GetCString(), + var_sc.module_sp->GetFileSpec().GetDirectory() ? "/" : "", + var_sc.module_sp->GetFileSpec().GetFilename().GetCString()); + else + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", + address, + variable->GetName().AsCString("")); } } else { - error.SetErrorString ("Invalid file address."); + error.SetErrorString ("invalid file address"); } } else @@ -651,14 +677,28 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context // The address is an address in this process, so just copy it memcpy (dst, (uint8_t*)NULL + address, byte_size); } - else if (address_type == eAddressTypeLoad) + else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { - if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size) + if (file_so_addr.IsValid()) { - if (error.Success()) - error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size); - else + // We have a file address that we were able to translate into a + // section offset address so we might be able to read this from + // the object files if we don't have a live process. Lets always + // try and read from the process if we have one though since we + // want to read the actual value by setting "prefer_file_cache" + // to false. + const bool prefer_file_cache = false; + if (exe_ctx->target->ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) + { + error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); + } + } + else + { + if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size) + { error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); + } } } else diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 6471972ad99..c4bfc3c126c 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -285,21 +285,21 @@ ValueObjectSP ValueObject::GetChildAtIndex (uint32_t idx, bool can_create) { ValueObjectSP child_sp; - if (UpdateValueIfNeeded()) + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType ()) + UpdateValueIfNeeded(); + if (idx < GetNumChildren()) { - if (idx < GetNumChildren()) + // Check if we have already made the child value object? + if (can_create && m_children[idx] == NULL) { - // Check if we have already made the child value object? - if (can_create && m_children[idx] == NULL) - { - // No we haven't created the child at this index, so lets have our - // subclass do it and cache the result for quick future access. - m_children[idx] = CreateChildAtIndex (idx, false, 0); - } - - if (m_children[idx] != NULL) - return m_children[idx]->GetSP(); + // No we haven't created the child at this index, so lets have our + // subclass do it and cache the result for quick future access. + m_children[idx] = CreateChildAtIndex (idx, false, 0); } + + if (m_children[idx] != NULL) + return m_children[idx]->GetSP(); } return child_sp; } @@ -322,36 +322,37 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) // need a vector of indexes that can get us down to the correct child ValueObjectSP child_sp; - if (UpdateValueIfNeeded()) + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType ()) + UpdateValueIfNeeded(); + + std::vector<uint32_t> child_indexes; + clang::ASTContext *clang_ast = GetClangAST(); + void *clang_type = GetClangType(); + bool omit_empty_base_classes = true; + const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, + clang_type, + name.GetCString(), + omit_empty_base_classes, + child_indexes); + if (num_child_indexes > 0) { - std::vector<uint32_t> child_indexes; - clang::ASTContext *clang_ast = GetClangAST(); - void *clang_type = GetClangType(); - bool omit_empty_base_classes = true; - const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, - clang_type, - name.GetCString(), - omit_empty_base_classes, - child_indexes); - if (num_child_indexes > 0) - { - std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); - std::vector<uint32_t>::const_iterator end = child_indexes.end (); + std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); + std::vector<uint32_t>::const_iterator end = child_indexes.end (); - child_sp = GetChildAtIndex(*pos, can_create); - for (++pos; pos != end; ++pos) + child_sp = GetChildAtIndex(*pos, can_create); + for (++pos; pos != end; ++pos) + { + if (child_sp) { - if (child_sp) - { - ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); - child_sp = new_child_sp; - } - else - { - child_sp.reset(); - } - + ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); + child_sp = new_child_sp; } + else + { + child_sp.reset(); + } + } } return child_sp; @@ -391,62 +392,59 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 { ValueObject *valobj = NULL; - if (UpdateValueIfNeeded()) - { - bool omit_empty_base_classes = true; - - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - - const bool transparent_pointers = synthetic_array_member == false; - clang::ASTContext *clang_ast = GetClangAST(); - clang_type_t clang_type = GetClangType(); - clang_type_t child_clang_type; - - ExecutionContext exe_ctx; - GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); - - child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, - clang_ast, - GetName().GetCString(), - clang_type, - idx, - transparent_pointers, - omit_empty_base_classes, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - if (child_clang_type && child_byte_size) - { - if (synthetic_index) - child_byte_offset += child_byte_size * synthetic_index; - - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); + bool omit_empty_base_classes = true; - valobj = new ValueObjectChild (*this, - clang_ast, - child_clang_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - if (m_pointers_point_to_load_addrs) - valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); - } + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + + const bool transparent_pointers = synthetic_array_member == false; + clang::ASTContext *clang_ast = GetClangAST(); + clang_type_t clang_type = GetClangType(); + clang_type_t child_clang_type; + + ExecutionContext exe_ctx; + GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); + + child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, + clang_ast, + GetName().GetCString(), + clang_type, + idx, + transparent_pointers, + omit_empty_base_classes, + child_name_str, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (child_clang_type && child_byte_size) + { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString (child_name_str.c_str()); + + valobj = new ValueObjectChild (*this, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (m_pointers_point_to_load_addrs) + valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); } return valobj; @@ -994,6 +992,12 @@ ValueObject::IsPossibleCPlusPlusDynamicType () return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType()); } +bool +ValueObject::IsPossibleDynamicType () +{ + return ClangASTContext::IsPossibleDynamicType (GetClangAST (), GetClangType()); +} + ValueObjectSP ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create) { diff --git a/lldb/source/Core/ValueObjectList.cpp b/lldb/source/Core/ValueObjectList.cpp index 8913d4da18d..f732a698ee5 100644 --- a/lldb/source/Core/ValueObjectList.cpp +++ b/lldb/source/Core/ValueObjectList.cpp @@ -51,6 +51,16 @@ ValueObjectList::Append (const ValueObjectSP &val_obj_sp) m_value_objects.push_back(val_obj_sp); } +void +ValueObjectList::Append (const ValueObjectList &valobj_list) +{ + std::copy(valobj_list.m_value_objects.begin(), // source begin + valobj_list.m_value_objects.end(), // source end + back_inserter(m_value_objects)); // destination + +} + + uint32_t ValueObjectList::GetSize() const { diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index e2a281b7f95..79692a023a8 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -169,7 +169,7 @@ ValueObjectVariable::UpdateValue () // Make sure this type has a value before we try and read it // If we have a file address, convert it to a load address if we can. - if (value_type == Value::eValueTypeFileAddress && exe_ctx.process) + if (value_type == Value::eValueTypeFileAddress && exe_ctx.process && exe_ctx.process->IsAlive()) { lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); if (file_addr != LLDB_INVALID_ADDRESS) diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index b692ae507c5..fb55a51344f 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -4046,6 +4046,150 @@ ClangASTContext::GetPointerBitSize () } bool +ClangASTContext::IsPossibleDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type) +{ + QualType pointee_qual_type; + if (clang_type) + { + QualType qual_type (QualType::getFromOpaquePtr(clang_type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + bool success = false; + switch (type_class) + { + case clang::Type::Builtin: + if (cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId) + { + if (dynamic_pointee_type) + *dynamic_pointee_type = clang_type; + return true; + } + break; + + case clang::Type::ObjCObjectPointer: + if (dynamic_pointee_type) + *dynamic_pointee_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); + return true; + + case clang::Type::Pointer: + pointee_qual_type = cast<PointerType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + pointee_qual_type = cast<ReferenceType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::Typedef: + return ClangASTContext::IsPossibleCPlusPlusDynamicType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); + + default: + break; + } + + if (success) + { + // Check to make sure what we are pointing too is a possible dynamic C++ type + // We currently accept any "void *" (in case we have a class that has been + // watered down to an opaque pointer) and virtual C++ classes. + const clang::Type::TypeClass pointee_type_class = pointee_qual_type->getTypeClass(); + switch (pointee_type_class) + { + case clang::Type::Builtin: + switch (cast<clang::BuiltinType>(pointee_qual_type)->getKind()) + { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + if (dynamic_pointee_type) + *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); + return true; + + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::BoundMember: + break; + } + break; + + case clang::Type::Record: + { + CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + if (GetCompleteQualType (ast, pointee_qual_type)) + { + success = cxx_record_decl->isDynamicClass(); + } + else + { + // We failed to get the complete type, so we have to + // treat this as a void * which we might possibly be + // able to complete + success = true; + } + if (success) + { + if (dynamic_pointee_type) + *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); + return true; + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + const clang::ObjCObjectType *objc_class_type = pointee_qual_type->getAsObjCQualifiedInterfaceType(); + if (objc_class_type) + { + GetCompleteQualType (ast, pointee_qual_type); + if (dynamic_pointee_type) + *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); + return true; + } + } + break; + + default: + break; + } + } + } + if (dynamic_pointee_type) + *dynamic_pointee_type = NULL; + return false; +} + + +bool ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type) { QualType pointee_qual_type; |