Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -744,7 +744,8 @@ size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override; uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) override; + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) override; CompilerType GetBuiltinTypeByName(const ConstString &name) override; Index: include/lldb/Symbol/CompilerType.h =================================================================== --- include/lldb/Symbol/CompilerType.h +++ include/lldb/Symbol/CompilerType.h @@ -301,7 +301,8 @@ size_t GetTypeBitAlign() const; - uint32_t GetNumChildren(bool omit_empty_base_classes) const; + uint32_t GetNumChildren(bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) const; lldb::BasicType GetBasicTypeEnumeration() const; Index: include/lldb/Symbol/GoASTContext.h =================================================================== --- include/lldb/Symbol/GoASTContext.h +++ include/lldb/Symbol/GoASTContext.h @@ -248,7 +248,8 @@ lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override; uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) override; + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) override; lldb::BasicType GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override; Index: include/lldb/Symbol/JavaASTContext.h =================================================================== --- include/lldb/Symbol/JavaASTContext.h +++ include/lldb/Symbol/JavaASTContext.h @@ -223,7 +223,8 @@ bool *is_bitfield_ptr) override; uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) override; + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) override; uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override; Index: include/lldb/Symbol/OCamlASTContext.h =================================================================== --- include/lldb/Symbol/OCamlASTContext.h +++ include/lldb/Symbol/OCamlASTContext.h @@ -173,7 +173,8 @@ lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override; uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) override; + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) override; lldb::BasicType GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override; Index: include/lldb/Symbol/SymbolFile.h =================================================================== --- include/lldb/Symbol/SymbolFile.h +++ include/lldb/Symbol/SymbolFile.h @@ -143,6 +143,23 @@ virtual size_t ParseTypes(const SymbolContext &sc) = 0; virtual size_t ParseVariablesForContext(const SymbolContext &sc) = 0; virtual Type *ResolveTypeUID(lldb::user_id_t type_uid) = 0; + + + /// The characteristics of an array type. + struct ArrayInfo { + int64_t first_index; + llvm::SmallVector element_orders; + uint32_t byte_stride; + uint32_t bit_stride; + }; + /// If \c type_uid points to an array type, return its characteristics. + /// To support variable-length array types, this function takes an + /// optional \p ExtecutionContext. If \c exe_ctx is non-null, the + /// dynamic characteristics for that context are returned. + virtual llvm::Optional + GetDynamicArrayInfoForUID(lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) = 0; + virtual bool CompleteType(CompilerType &compiler_type) = 0; virtual void ParseDeclsForContext(CompilerDeclContext decl_ctx) {} virtual CompilerDecl GetDeclForUID(lldb::user_id_t uid) { Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- include/lldb/Symbol/TypeSystem.h +++ include/lldb/Symbol/TypeSystem.h @@ -286,7 +286,8 @@ virtual lldb::Format GetFormat(lldb::opaque_compiler_type_t type) = 0; virtual uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) = 0; + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) = 0; virtual CompilerType GetBuiltinTypeByName(const ConstString &name); Index: packages/Python/lldbsuite/test/lang/c/vla/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/lang/c/vla/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py @@ -0,0 +1,26 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestVLA(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_vla(self): + self.build() + _, process, _, _ = lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec('main.c')) + + def test(a): + for i in range(a): + self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)]) + self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)]) + array = ["int []", "2", "1"] + self.expect("frame var vla", substrs=array) + self.expect("expr vla", error=True, substrs=["incomplete"]) + + test(2) + process.Continue() + test(4) + Index: packages/Python/lldbsuite/test/lang/c/vla/main.c =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/lang/c/vla/main.c @@ -0,0 +1,15 @@ +void pause() {} + +int foo(int a) { + int vla[a]; + + for (int i = 0; i < a; ++i) + vla[i] = a-i; + + pause(); // break here + return vla[a-1]; +} + +int main (void) { + return foo(2) + foo(4); +} Index: source/Core/ValueObjectCast.cpp =================================================================== --- source/Core/ValueObjectCast.cpp +++ source/Core/ValueObjectCast.cpp @@ -44,7 +44,9 @@ CompilerType ValueObjectCast::GetCompilerTypeImpl() { return m_cast_type; } size_t ValueObjectCast::CalculateNumChildren(uint32_t max) { - auto children_count = GetCompilerType().GetNumChildren(true); + ExecutionContext exe_ctx(GetExecutionContextRef()); + auto children_count = GetCompilerType().GetNumChildren( + true, &exe_ctx); return children_count <= max ? children_count : max; } Index: source/Core/ValueObjectChild.cpp =================================================================== --- source/Core/ValueObjectChild.cpp +++ source/Core/ValueObjectChild.cpp @@ -51,7 +51,8 @@ } size_t ValueObjectChild::CalculateNumChildren(uint32_t max) { - auto children_count = GetCompilerType().GetNumChildren(true); + ExecutionContext exe_ctx(GetExecutionContextRef()); + auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); return children_count <= max ? children_count : max; } Index: source/Core/ValueObjectConstResult.cpp =================================================================== --- source/Core/ValueObjectConstResult.cpp +++ source/Core/ValueObjectConstResult.cpp @@ -208,7 +208,8 @@ void ValueObjectConstResult::SetByteSize(size_t size) { m_byte_size = size; } size_t ValueObjectConstResult::CalculateNumChildren(uint32_t max) { - auto children_count = GetCompilerType().GetNumChildren(true); + ExecutionContext exe_ctx(GetExecutionContextRef()); + auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); return children_count <= max ? children_count : max; } Index: source/Core/ValueObjectDynamicValue.cpp =================================================================== --- source/Core/ValueObjectDynamicValue.cpp +++ source/Core/ValueObjectDynamicValue.cpp @@ -92,7 +92,8 @@ size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) { - auto children_count = GetCompilerType().GetNumChildren(true); + ExecutionContext exe_ctx(GetExecutionContextRef()); + auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); return children_count <= max ? children_count : max; } else return m_parent->GetNumChildren(max); Index: source/Core/ValueObjectMemory.cpp =================================================================== --- source/Core/ValueObjectMemory.cpp +++ source/Core/ValueObjectMemory.cpp @@ -128,8 +128,10 @@ return child_count <= max ? child_count : max; } + ExecutionContext exe_ctx(GetExecutionContextRef()); const bool omit_empty_base_classes = true; - auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes); + auto child_count = + m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx); return child_count <= max ? child_count : max; } Index: source/Core/ValueObjectRegister.cpp =================================================================== --- source/Core/ValueObjectRegister.cpp +++ source/Core/ValueObjectRegister.cpp @@ -279,7 +279,8 @@ } size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) { - auto children_count = GetCompilerType().GetNumChildren(true); + ExecutionContext exe_ctx(GetExecutionContextRef()); + auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); return children_count <= max ? children_count : max; } Index: source/Core/ValueObjectVariable.cpp =================================================================== --- source/Core/ValueObjectVariable.cpp +++ source/Core/ValueObjectVariable.cpp @@ -98,8 +98,9 @@ if (!type.IsValid()) return 0; + ExecutionContext exe_ctx(GetExecutionContextRef()); const bool omit_empty_base_classes = true; - auto child_count = type.GetNumChildren(omit_empty_base_classes); + auto child_count = type.GetNumChildren(omit_empty_base_classes, &exe_ctx); return child_count <= max ? child_count : max; } Index: source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp =================================================================== --- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -773,7 +773,7 @@ // get number of children const bool omit_empty_base_classes = true; - uint32_t n = m_type.GetNumChildren(omit_empty_base_classes); + uint32_t n = m_type.GetNumChildren(omit_empty_base_classes, nullptr); if (!n) { LLDB_LOG(m_log, LOG_PREFIX "No children found in struct"); return ValueObjectSP(); Index: source/Plugins/Language/CPlusPlus/BlockPointer.cpp =================================================================== --- source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -89,7 +89,7 @@ size_t CalculateNumChildren() override { const bool omit_empty_base_classes = false; - return m_block_struct_type.GetNumChildren(omit_empty_base_classes); + return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr); } lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { Index: source/Plugins/SymbolFile/DWARF/DWARFASTParser.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -12,10 +12,15 @@ #include "DWARFDefines.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" class DWARFDIE; +namespace lldb_private { +class ExecutionContext; +} +class SymbolFileDWARF; class DWARFASTParser { public: @@ -45,6 +50,10 @@ virtual std::vector GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) = 0; + + static llvm::Optional + ParseChildArrayInfo(const DWARFDIE &parent_die, + const lldb_private::ExecutionContext *exe_ctx = nullptr); }; #endif // SymbolFileDWARF_DWARFASTParser_h_ Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -28,6 +28,7 @@ class DWARFDebugInfoEntry; class DWARFDIECollection; +class SymbolFileDWARF; class DWARFASTParserClang : public DWARFASTParser { public: @@ -101,11 +102,6 @@ std::vector &function_param_decls, unsigned &type_quals); - void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, - const DWARFDIE &parent_die, int64_t &first_index, - std::vector &element_orders, - uint32_t &byte_stride, uint32_t &bit_stride); - size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc, lldb_private::CompilerType &compiler_type, bool is_signed, uint32_t enumerator_byte_size, Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1734,9 +1734,12 @@ Type *element_type = dwarf->ResolveTypeUID(type_die_ref); if (element_type) { - std::vector element_orders; - ParseChildArrayInfo(sc, die, first_index, element_orders, - byte_stride, bit_stride); + auto array_info = ParseChildArrayInfo(die); + if (array_info) { + first_index = array_info->first_index; + byte_stride = array_info->byte_stride; + bit_stride = array_info->bit_stride; + } if (byte_stride == 0 && bit_stride == 0) byte_stride = element_type->GetByteSize(); CompilerType array_element_type = @@ -1786,12 +1789,11 @@ } uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - if (element_orders.size() > 0) { + if (array_info && array_info->element_orders.size() > 0) { uint64_t num_elements = 0; - std::vector::const_reverse_iterator pos; - std::vector::const_reverse_iterator end = - element_orders.rend(); - for (pos = element_orders.rbegin(); pos != end; ++pos) { + auto end = array_info->element_orders.rend(); + for (auto pos = array_info->element_orders.rbegin(); pos != end; + ++pos) { num_elements = *pos; clang_type = m_ast.CreateArrayType(array_element_type, num_elements, is_vector); @@ -1810,6 +1812,8 @@ NULL, DIERef(type_die_form).GetUID(dwarf), Type::eEncodingIsUID, &decl, clang_type, Type::eResolveStateFull)); type_sp->SetEncodingType(element_type); + m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), + die.GetID()); } } } break; @@ -3439,12 +3443,12 @@ return arg_idx; } -void DWARFASTParserClang::ParseChildArrayInfo( - const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, - std::vector &element_orders, uint32_t &byte_stride, - uint32_t &bit_stride) { +llvm::Optional +DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, + const ExecutionContext *exe_ctx) { + SymbolFile::ArrayInfo array_info; if (!parent_die) - return; + return llvm::None; for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) { @@ -3468,15 +3472,31 @@ break; case DW_AT_count: - num_elements = form_value.Unsigned(); + if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) { + if (var_die.Tag() == DW_TAG_variable) + if (exe_ctx) { + if (auto frame = exe_ctx->GetFrameSP()) { + Status error; + lldb::VariableSP var_sp; + auto valobj_sp = frame->GetValueForVariableExpressionPath( + var_die.GetName(), eNoDynamicValues, 0, var_sp, + error); + if (valobj_sp) { + num_elements = valobj_sp->GetValueAsUnsigned(0); + break; + } + } + } + } else + num_elements = form_value.Unsigned(); break; case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); + array_info.bit_stride = form_value.Unsigned(); break; case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); + array_info.byte_stride = form_value.Unsigned(); break; case DW_AT_lower_bound: @@ -3510,11 +3530,12 @@ num_elements = upper_bound - lower_bound + 1; } - element_orders.push_back(num_elements); + array_info.element_orders.push_back(num_elements); } } break; } } + return array_info; } Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) { Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -144,6 +144,9 @@ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; bool CompleteType(lldb_private::CompilerType &compiler_type) override; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1416,6 +1416,17 @@ return nullptr; } +llvm::Optional +SymbolFileDWARF::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + std::lock_guard guard(GetModuleMutex()); + DWARFDIE type_die = GetDIEFromUID(type_uid); + if (type_die) + return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx); + else + return llvm::None; +} + Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) { return ResolveType(GetDIE(die_ref), true); } Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -77,6 +77,10 @@ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; + lldb_private::CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; lldb_private::CompilerDeclContext Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -518,7 +518,8 @@ SymbolFileDWARF * SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) { - if (oso_idx < m_compile_unit_infos.size()) + unsigned size = m_compile_unit_infos.size(); + if (oso_idx < size) return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]); return NULL; } @@ -702,6 +703,16 @@ return NULL; } +llvm::Optional +SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); + SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); + if (oso_dwarf) + return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx); + return llvm::None; +} + bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) { bool success = false; if (compiler_type) { Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h =================================================================== --- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -113,6 +113,10 @@ return 0; } Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; + bool CompleteType(CompilerType &compiler_type) override; uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1433,6 +1433,13 @@ return &*type_sp; } +llvm::Optional +SymbolFileNativePDB::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + return llvm::None; +} + + bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { // If this is not in our map, it's an error. clang::TagDecl *tag_decl = m_clang->GetAsTagDecl(compiler_type); Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -85,6 +85,9 @@ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; bool CompleteType(lldb_private::CompilerType &compiler_type) override; Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -587,6 +587,11 @@ return result.get(); } +llvm::Optional SymbolFilePDB::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + return llvm::None; +} + bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { std::lock_guard guard( GetObjectFile()->GetModule()->GetMutex()); Index: source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h =================================================================== --- source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -80,6 +80,9 @@ ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; bool CompleteType(lldb_private::CompilerType &compiler_type) override; Index: source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp =================================================================== --- source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -239,6 +239,12 @@ return NULL; } +llvm::Optional +SymbolFileSymtab::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + return llvm::None; +} + bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { return false; } Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -5400,8 +5400,21 @@ return false; } +static llvm::Optional +GetDynamicArrayInfo(ClangASTContext &ast, SymbolFile *sym_file, + clang::QualType qual_type, + const ExecutionContext *exe_ctx) { + if (qual_type->isIncompleteArrayType()) + if (auto *metadata = ast.GetMetadata(qual_type.getAsOpaquePtr())) + if (auto *dwarf_parser = ast.GetDWARFParser()) + return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(), + exe_ctx); + return llvm::None; +} + uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) { + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) { if (!type) return 0; @@ -5423,7 +5436,6 @@ case clang::Type::Complex: return 0; - case clang::Type::Record: if (GetCompleteQualType(getASTContext(), qual_type)) { const clang::RecordType *record_type = @@ -5501,7 +5513,7 @@ clang::QualType pointee_type = pointer_type->getPointeeType(); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) num_children = 1; @@ -5520,6 +5532,14 @@ ->getSize() .getLimitedValue(); break; + case clang::Type::IncompleteArray: + if (auto array_info = + GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx)) + // Only 1-dimensional arrays are supported. + num_children = array_info->element_orders.size() + ? array_info->element_orders.back() + : 0; + break; case clang::Type::Pointer: { const clang::PointerType *pointer_type = @@ -5527,7 +5547,7 @@ clang::QualType pointee_type(pointer_type->getPointeeType()); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); if (num_pointee_children == 0) { // We have a pointer to a pointee type that claims it has no children. We // will want to look at @@ -5543,7 +5563,7 @@ clang::QualType pointee_type = reference_type->getPointeeType(); uint32_t num_pointee_children = CompilerType(getASTContext(), pointee_type) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) num_children = 1; @@ -5556,14 +5576,14 @@ CompilerType(getASTContext(), llvm::cast(qual_type) ->getDecl() ->getUnderlyingType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Auto: num_children = CompilerType(getASTContext(), llvm::cast(qual_type)->getDeducedType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Elaborated: @@ -5571,14 +5591,14 @@ CompilerType( getASTContext(), llvm::cast(qual_type)->getNamedType()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Paren: num_children = CompilerType(getASTContext(), llvm::cast(qual_type)->desugar()) - .GetNumChildren(omit_empty_base_classes); + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; default: break; @@ -6455,7 +6475,8 @@ child_is_base_class = false; language_flags = 0; - const bool idx_is_valid = idx < GetNumChildren(type, omit_empty_base_classes); + const bool idx_is_valid = + idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx); int32_t bit_offset; switch (parent_type_class) { case clang::Type::Builtin: @@ -6677,8 +6698,8 @@ CompilerType base_class_clang_type( getASTContext(), getASTContext()->getObjCInterfaceType( superclass_interface_decl)); - if (base_class_clang_type.GetNumChildren( - omit_empty_base_classes) > 0) { + if (base_class_clang_type.GetNumChildren(omit_empty_base_classes, + exe_ctx) > 0) { if (idx == 0) { clang::QualType ivar_qual_type( getASTContext()->getObjCInterfaceType( Index: source/Symbol/CompilerType.cpp =================================================================== --- source/Symbol/CompilerType.cpp +++ source/Symbol/CompilerType.cpp @@ -535,10 +535,12 @@ return m_type_system->GetFormat(m_type); } -uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes) const { +uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) const { if (!IsValid()) return 0; - return m_type_system->GetNumChildren(m_type, omit_empty_base_classes); + return m_type_system->GetNumChildren(m_type, omit_empty_base_classes, + exe_ctx); } lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { Index: source/Symbol/GoASTContext.cpp =================================================================== --- source/Symbol/GoASTContext.cpp +++ source/Symbol/GoASTContext.cpp @@ -864,19 +864,20 @@ } uint32_t GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) { + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) { if (!type || !GetCompleteType(type)) return 0; GoType *t = static_cast(type); if (t->GetGoKind() == GoType::KIND_PTR) { CompilerType elem = t->GetElementType(); if (elem.IsAggregateType()) - return elem.GetNumChildren(omit_empty_base_classes); + return elem.GetNumChildren(omit_empty_base_classes, exe_ctx); return 1; } else if (GoArray *array = t->GetArray()) { return array->GetLength(); } else if (t->IsTypedef()) { - return t->GetElementType().GetNumChildren(omit_empty_base_classes); + return t->GetElementType().GetNumChildren(omit_empty_base_classes, exe_ctx); } return GetNumFields(type); Index: source/Symbol/JavaASTContext.cpp =================================================================== --- source/Symbol/JavaASTContext.cpp +++ source/Symbol/JavaASTContext.cpp @@ -915,12 +915,14 @@ } uint32_t JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) { + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) { GetCompleteType(type); if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) - return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes); + return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes, + exe_ctx); if (llvm::isa(static_cast(type))) return GetNumFields(type) + GetNumDirectBaseClasses(type); Index: source/Symbol/OCamlASTContext.cpp =================================================================== --- source/Symbol/OCamlASTContext.cpp +++ source/Symbol/OCamlASTContext.cpp @@ -509,7 +509,8 @@ } uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, - bool omit_empty_base_classes) { + bool omit_empty_base_classes, + const ExecutionContext *exe_ctx) { if (!type || !GetCompleteType(type)) return 0; Index: source/Symbol/Type.cpp =================================================================== --- source/Symbol/Type.cpp +++ source/Symbol/Type.cpp @@ -342,7 +342,7 @@ } uint32_t Type::GetNumChildren(bool omit_empty_base_classes) { - return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes); + return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes, nullptr); } bool Type::IsAggregateType() { Index: source/Symbol/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -603,7 +603,7 @@ case eTypeClassObjCObjectPointer: case eTypeClassPointer: { bool omit_empty_base_classes = true; - if (compiler_type.GetNumChildren(omit_empty_base_classes) > 0) + if (compiler_type.GetNumChildren(omit_empty_base_classes, nullptr) > 0) matches.AppendString((prefix_path + "->").str()); else { matches.AppendString(prefix_path.str());