aprantl created this revision.
aprantl added reviewers: jingham, clayborg.
aprantl added a project: LLDB.
Herald added a subscriber: JDevlieghere.

Clang recently improved its DWARF support for C VLA types. The DWARF now looks 
like this:

  0x00000051:         DW_TAG_variable [4]  
                       DW_AT_location( fbreg -32 )
                       DW_AT_name( "__vla_expr" )
                       DW_AT_type( {0x000000d3} ( long unsigned int ) )
                       DW_AT_artificial( true )
  ...
  0x000000da:     DW_TAG_array_type [10] *
                   DW_AT_type( {0x000000cc} ( int ) )
  
  0x000000df:         DW_TAG_subrange_type [11]  
                       DW_AT_type( {0x000000e9} ( __ARRAY_SIZE_TYPE__ ) )
                       DW_AT_count( {0x00000051} )

Without this patch LLDB will naively interpret the DIE offset 0x51 as the 
static size of the array, which is clearly wrong.
This patch uses LLDB's dynamic type mechanism to re-parse VLA types with an 
optional execution context, to dynamically resolve the size of the array 
correctly. These dynamic types are not being cached, since they are only valid 
in a single execution context.

See the testcase for an example:

     4          int foo(int a) {
     5             int vla[a];
     6            for (int i = 0; i < a; ++i)
     7              vla[i] = i;
     8          
  -> 9            pause(); // break here
     10           return vla[a-1];
     11         }
     12         
  
  (lldb) fr v vla
  (int [4]) vla = ([0] = 0, [1] = 1, [2] = 2, [3] = 3)
  (lldb) quit


https://reviews.llvm.org/D53530

Files:
  include/lldb/Symbol/SymbolFile.h
  include/lldb/Symbol/Variable.h
  packages/Python/lldbsuite/test/lang/c/vla/Makefile
  packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py
  packages/Python/lldbsuite/test/lang/c/vla/main.c
  
source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
  source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
  source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
  source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
  source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
  source/Symbol/ClangASTContext.cpp

Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -3696,6 +3696,9 @@
       return IsPossibleDynamicType(
           llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
           dynamic_pointee_type, check_cplusplus, check_objc);
+
+    case clang::Type::IncompleteArray:
+      return true;
     default:
       break;
     }
Index: source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
===================================================================
--- source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -79,7 +79,9 @@
   size_t
   ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
 
-  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+  lldb_private::Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef 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
@@ -235,7 +235,8 @@
   return 0;
 }
 
-Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) {
+Type *SymbolFileSymtab::ResolveTypeUID(
+    lldb::user_id_t type_uid, const lldb_private::ExecutionContextRef exe_ctx) {
   return NULL;
 }
 
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -84,7 +84,9 @@
   size_t
   ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
 
-  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+  lldb_private::Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef 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
@@ -558,7 +558,9 @@
   return num_added;
 }
 
-lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
+lldb_private::Type *
+SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid,
+                              const lldb_private::ExecutionContextRef exe_ctx) {
   auto find_result = m_types.find(type_uid);
   if (find_result != m_types.end())
     return find_result->second.get();
Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -116,7 +116,9 @@
   ParseVariablesForContext(const lldb_private::SymbolContext &sc) override {
     return 0;
   }
-  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override {
+  lldb_private::Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef exe_ctx) override {
     return nullptr;
   }
   bool CompleteType(lldb_private::CompilerType &compiler_type) override {
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -76,7 +76,9 @@
   size_t
   ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
 
-  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+  lldb_private::Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef 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
@@ -694,11 +694,12 @@
   return 0;
 }
 
-Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
+Type *SymbolFileDWARFDebugMap::ResolveTypeUID(
+    lldb::user_id_t type_uid, const lldb_private::ExecutionContextRef exe_ctx) {
   const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
   SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
   if (oso_dwarf)
-    return oso_dwarf->ResolveTypeUID(type_uid);
+    return oso_dwarf->ResolveTypeUID(type_uid, exe_ctx);
   return NULL;
 }
 
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -144,13 +144,16 @@
   size_t
   ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
 
-  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+  lldb_private::Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef exe_ctx = {}) override;
 
   bool CompleteType(lldb_private::CompilerType &compiler_type) override;
 
-  lldb_private::Type *ResolveType(const DWARFDIE &die,
-                                  bool assert_not_being_parsed = true,
-                                  bool resolve_function_context = false);
+  lldb_private::Type *
+  ResolveType(const DWARFDIE &die, bool assert_not_being_parsed = true,
+              bool resolve_function_context = false,
+              const lldb_private::ExecutionContextRef exe_ctx = {});
 
   SymbolFileDWARF *GetDWARFForUID(lldb::user_id_t uid);
 
@@ -371,7 +374,8 @@
                     bool parse_siblings, bool parse_children);
 
   lldb::TypeSP ParseType(const lldb_private::SymbolContext &sc,
-                         const DWARFDIE &die, bool *type_is_new);
+                         const DWARFDIE &die, bool *type_is_new,
+                         const lldb_private::ExecutionContextRef exe_ctx = {});
 
   lldb_private::Type *ResolveTypeUID(const DWARFDIE &die,
                                      bool assert_not_being_parsed);
@@ -404,8 +408,10 @@
   lldb_private::Symbol *
   GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name);
 
-  lldb::TypeSP GetTypeForDIE(const DWARFDIE &die,
-                             bool resolve_function_context = false);
+  /// If exe_ctx is non-null, the type may only be valid within that context.
+  lldb::TypeSP
+  GetTypeForDIE(const DWARFDIE &die, bool resolve_function_context = false,
+                const lldb_private::ExecutionContextRef exe_ctx = {});
 
   void SetDebugMapModule(const lldb::ModuleSP &module_sp) {
     m_debug_map_module_wp = module_sp;
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1362,23 +1362,23 @@
   return CompilerDeclContext();
 }
 
-Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
+Type *SymbolFileDWARF::ResolveTypeUID(
+    lldb::user_id_t type_uid, const lldb_private::ExecutionContextRef exe_ctx) {
   // Anytime we have a lldb::user_id_t, we must get the DIE by calling
   // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
   // SymbolFileDWARF::GetDIEFromUID() for details.
   DWARFDIE type_die = GetDIEFromUID(type_uid);
   if (type_die)
-    return type_die.ResolveType();
-  else
-    return nullptr;
+    return ResolveType(type_die, true, false, exe_ctx);
+  return nullptr;
 }
 
 Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) {
   return ResolveType(GetDIE(die_ref), true);
 }
 
-Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
-                                      bool assert_not_being_parsed) {
+Type *SymbolFileDWARF::ResolveTypeUID(
+    const DWARFDIE &die, bool assert_not_being_parsed) {
   if (die) {
     Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
     if (log)
@@ -1486,11 +1486,12 @@
   return false;
 }
 
-Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
-                                   bool assert_not_being_parsed,
-                                   bool resolve_function_context) {
+Type *
+SymbolFileDWARF::ResolveType(const DWARFDIE &die, bool assert_not_being_parsed,
+                             bool resolve_function_context,
+                             const lldb_private::ExecutionContextRef exe_ctx) {
   if (die) {
-    Type *type = GetTypeForDIE(die, resolve_function_context).get();
+    Type *type = GetTypeForDIE(die, resolve_function_context, exe_ctx).get();
 
     if (assert_not_being_parsed) {
       if (type != DIE_IS_BEING_PARSED)
@@ -2592,33 +2593,37 @@
   return namespace_decl_ctx;
 }
 
-TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die,
-                                      bool resolve_function_context) {
-  TypeSP type_sp;
-  if (die) {
-    Type *type_ptr = GetDIEToType().lookup(die.GetDIE());
-    if (type_ptr == NULL) {
-      CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());
-      assert(lldb_cu);
-      SymbolContext sc(lldb_cu);
-      const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE();
-      while (parent_die != nullptr) {
-        if (parent_die->Tag() == DW_TAG_subprogram)
-          break;
-        parent_die = parent_die->GetParent();
-      }
-      SymbolContext sc_backup = sc;
-      if (resolve_function_context && parent_die != nullptr &&
-          !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc))
-        sc = sc_backup;
-
-      type_sp = ParseType(sc, die, NULL);
-    } else if (type_ptr != DIE_IS_BEING_PARSED) {
-      // Grab the existing type from the master types lists
-      type_sp = type_ptr->shared_from_this();
-    }
+TypeSP SymbolFileDWARF::GetTypeForDIE(
+    const DWARFDIE &die, bool resolve_function_context,
+    const lldb_private::ExecutionContextRef exe_ctx) {
+  if (!die)
+    return {};
+  Type *type_ptr = GetDIEToType().lookup(die.GetDIE());
+  if (type_ptr == DIE_IS_BEING_PARSED)
+    return {};
+
+  // If an execution context is present, re-parse the type.
+  if (type_ptr && !exe_ctx.GetFrameSP()) {
+    // Grab the existing type from the master types lists
+    return type_ptr->shared_from_this();
   }
-  return type_sp;
+
+  // Parse the type.
+  CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());
+  assert(lldb_cu);
+  SymbolContext sc(lldb_cu);
+  const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE();
+  while (parent_die) {
+    if (parent_die->Tag() == DW_TAG_subprogram)
+      break;
+    parent_die = parent_die->GetParent();
+  }
+  SymbolContext sc_backup = sc;
+  if (resolve_function_context && parent_die &&
+      !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc))
+    sc = sc_backup;
+
+  return ParseType(sc, die, NULL, exe_ctx);
 }
 
 DWARFDIE
@@ -3000,8 +3005,10 @@
   return type_sp;
 }
 
-TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
-                                  bool *type_is_new_ptr) {
+TypeSP
+SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
+                           bool *type_is_new_ptr,
+                           const lldb_private::ExecutionContextRef exe_ctx) {
   TypeSP type_sp;
 
   if (die) {
@@ -3012,10 +3019,11 @@
       DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
       if (dwarf_ast) {
         Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
-        type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr);
+        type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr,
+                                                exe_ctx);
         if (type_sp) {
           TypeList *type_list = GetTypeList();
-          if (type_list)
+          if (type_list && !exe_ctx.GetFrameSP())
             type_list->Insert(type_sp);
 
           if (die.Tag() == DW_TAG_subprogram) {
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
@@ -22,9 +22,10 @@
 
   lldb::TypeSP ParseBaseTypeFromDIE(const DWARFDIE &die);
 
-  lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                  const DWARFDIE &die, lldb_private::Log *log,
-                                  bool *type_is_new_ptr) override;
+  lldb::TypeSP ParseTypeFromDWARF(
+    const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+    lldb_private::Log *log, bool *type_is_new_ptr,
+    const lldb_private::ExecutionContextRef exe_ctx = {}) override;
 
   lldb_private::Function *
   ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
@@ -53,10 +53,9 @@
                                 decl, compiler_type, Type::eResolveStateFull);
 }
 
-lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(const SymbolContext &sc,
-                                                     const DWARFDIE &die,
-                                                     Log *log,
-                                                     bool *type_is_new_ptr) {
+lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(
+    const SymbolContext &sc, const DWARFDIE &die, Log *log,
+    bool *type_is_new_ptr, const lldb_private::ExecutionContextRef exe_ctx) {
   if (type_is_new_ptr)
     *type_is_new_ptr = false;
 
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
@@ -32,9 +32,10 @@
   DWARFASTParserJava(lldb_private::JavaASTContext &ast);
   ~DWARFASTParserJava() override;
 
-  lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                  const DWARFDIE &die, lldb_private::Log *log,
-                                  bool *type_is_new_ptr) override;
+  lldb::TypeSP ParseTypeFromDWARF(
+     const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+     lldb_private::Log *log, bool *type_is_new_ptr,
+     const lldb_private::ExecutionContextRef exe_ctx = {}) override;
 
   lldb_private::Function *
   ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
@@ -276,7 +276,8 @@
 
 lldb::TypeSP DWARFASTParserJava::ParseTypeFromDWARF(
     const lldb_private::SymbolContext &sc, const DWARFDIE &die,
-    lldb_private::Log *log, bool *type_is_new_ptr) {
+    lldb_private::Log *log, bool *type_is_new_ptr,
+    const lldb_private::ExecutionContextRef exe_ctx) {
   if (type_is_new_ptr)
     *type_is_new_ptr = false;
 
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
@@ -33,9 +33,10 @@
 
   ~DWARFASTParserGo() override;
 
-  lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                  const DWARFDIE &die, lldb_private::Log *log,
-                                  bool *type_is_new_ptr) override;
+  lldb::TypeSP ParseTypeFromDWARF(
+    const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+    lldb_private::Log *log, bool *type_is_new_ptr,
+    const lldb_private::ExecutionContextRef exe_ctx = {}) override;
 
   lldb_private::Function *
   ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -49,7 +49,8 @@
 
 TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
     const lldb_private::SymbolContext &sc, const DWARFDIE &die,
-    lldb_private::Log *log, bool *type_is_new_ptr) {
+    lldb_private::Log *log, bool *type_is_new_ptr,
+    const lldb_private::ExecutionContextRef exe_ctx) {
   TypeSP type_sp;
 
   if (type_is_new_ptr)
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -36,9 +36,10 @@
   ~DWARFASTParserClang() override;
 
   // DWARFASTParser interface.
-  lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                  const DWARFDIE &die, lldb_private::Log *log,
-                                  bool *type_is_new_ptr) override;
+  lldb::TypeSP ParseTypeFromDWARF(
+      const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+      lldb_private::Log *log, bool *type_is_new_ptr,
+      const lldb_private::ExecutionContextRef exe_ctx = {}) override;
 
   lldb_private::Function *
   ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
@@ -104,7 +105,8 @@
   void ParseChildArrayInfo(const lldb_private::SymbolContext &sc,
                            const DWARFDIE &parent_die, int64_t &first_index,
                            std::vector<uint64_t> &element_orders,
-                           uint32_t &byte_stride, uint32_t &bit_stride);
+                           uint32_t &byte_stride, uint32_t &bit_stride,
+                           const lldb_private::ExecutionContextRef exe_ctx);
 
   size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc,
                                lldb_private::CompilerType &compiler_type,
@@ -131,7 +133,9 @@
 
   void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die);
 
-  lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
+  lldb::TypeSP
+  ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log,
+                   const lldb_private::ExecutionContextRef exe_ctx = {});
 
   //----------------------------------------------------------------------
   // Return true if this type is a declaration to a type in an external
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -15,6 +15,7 @@
 #include "DWARFDebugInfo.h"
 #include "DWARFDeclContext.h"
 #include "DWARFDefines.h"
+#include "LogChannelDWARF.h"
 #include "SymbolFileDWARF.h"
 #include "SymbolFileDWARFDwo.h"
 #include "SymbolFileDWARFDebugMap.h"
@@ -137,7 +138,9 @@
   return false;
 }
 
-TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
+TypeSP DWARFASTParserClang::ParseTypeFromDWO(
+    const DWARFDIE &die, Log *log,
+    const lldb_private::ExecutionContextRef exe_ctx) {
   ModuleSP dwo_module_sp = die.GetContainingDWOModule();
   if (!dwo_module_sp)
     return TypeSP();
@@ -168,7 +171,7 @@
   if (num_dwo_types != 1)
     return TypeSP();
 
-  // We found a real definition for this type in the Clang module, so lets use
+  // We found a real definition for this type in the Clang module, so let's use
   // it and cache the fact that we found a complete type for this die.
   TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
   if (!dwo_type_sp)
@@ -188,8 +191,16 @@
       NULL, LLDB_INVALID_UID, Type::eEncodingInvalid,
       &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));
 
+  // We are ready to put this type into the uniqued list up at the module
+  // level.
   dwarf->GetTypeList()->Insert(type_sp);
-  dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+  // Cache the type if it isn't context-specific.
+  auto &cache = dwarf->GetDIEToType();
+  if (exe_ctx.GetFrameSP())
+    cache.erase(die.GetDIE());
+  else
+    cache[die.GetDIE()] = type_sp.get();
+
   clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
   if (tag_decl)
     LinkDeclContextToDIE(tag_decl, die);
@@ -228,9 +239,9 @@
   }
 }
 
-TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
-                                               const DWARFDIE &die, Log *log,
-                                               bool *type_is_new_ptr) {
+TypeSP DWARFASTParserClang::ParseTypeFromDWARF(
+    const SymbolContext &sc, const DWARFDIE &die, Log *log,
+    bool *type_is_new_ptr, const lldb_private::ExecutionContextRef exe_ctx) {
   TypeSP type_sp;
 
   if (type_is_new_ptr)
@@ -251,8 +262,8 @@
           context_die.GetOffset(), die.GetTagAsCString(), die.GetName());
     }
     Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
-    TypeList *type_list = dwarf->GetTypeList();
-    if (type_ptr == NULL) {
+    // If an execution context is present, re-parse the type.
+    if (type_ptr == NULL || exe_ctx.GetFrameSP()) {
       if (type_is_new_ptr)
         *type_is_new_ptr = true;
 
@@ -1736,7 +1747,7 @@
           if (element_type) {
             std::vector<uint64_t> element_orders;
             ParseChildArrayInfo(sc, die, first_index, element_orders,
-                                byte_stride, bit_stride);
+                                byte_stride, bit_stride, exe_ctx);
             if (byte_stride == 0 && bit_stride == 0)
               byte_stride = element_type->GetByteSize();
             CompilerType array_element_type =
@@ -1886,10 +1897,14 @@
         }
 
         // We are ready to put this type into the uniqued list up at the module
-        // level
-        type_list->Insert(type_sp);
-
-        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+        // level.
+        dwarf->GetTypeList()->Insert(type_sp);
+        // Cache the type if it isn't context-specific.
+        auto &cache = dwarf->GetDIEToType();
+        if (exe_ctx.GetFrameSP())
+          cache.erase(die.GetDIE());
+        else
+          cache[die.GetDIE()] = type_sp.get();
       }
     } else if (type_ptr != DIE_IS_BEING_PARSED) {
       type_sp = type_ptr->shared_from_this();
@@ -3442,7 +3457,7 @@
 void DWARFASTParserClang::ParseChildArrayInfo(
     const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
     std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
-    uint32_t &bit_stride) {
+    uint32_t &bit_stride, const lldb_private::ExecutionContextRef exe_ctx) {
   if (!parent_die)
     return;
 
@@ -3468,7 +3483,25 @@
               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 (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);
+                      if (auto log = LogChannelDWARF::GetLogIfAll(
+                              DWARF_LOG_DEBUG_INFO))
+                        log->Printf("Reparsing array type; dynamic size=%lld",
+                                    num_elements);
+
+                      break;
+                    }
+                  }
+              } else
+                num_elements = form_value.Unsigned();
               break;
 
             case DW_AT_bit_stride:
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -14,17 +14,18 @@
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Target/ExecutionContext.h"
 
 class DWARFDIE;
 
 class DWARFASTParser {
 public:
   virtual ~DWARFASTParser() {}
 
-  virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                          const DWARFDIE &die,
-                                          lldb_private::Log *log,
-                                          bool *type_is_new_ptr) = 0;
+  virtual lldb::TypeSP
+  ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+                     lldb_private::Log *log, bool *type_is_new_ptr,
+                     const lldb_private::ExecutionContextRef exe_ctx = {}) = 0;
 
   virtual lldb_private::Function *
   ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
Index: source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
===================================================================
--- source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/Variable.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/SectionLoadList.h"
@@ -207,16 +208,32 @@
   if (!CouldHaveDynamicValue(in_value))
     return false;
 
+  ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+  
+  // Handle variables with incomplete array types.
+  auto *type = in_value.GetCompilerType().GetOpaqueQualType();
+  auto qual_type = clang::QualType::getFromOpaquePtr(type).getCanonicalType();
+  if (qual_type->getTypeClass() == clang::Type::IncompleteArray) {
+    if (auto variable = in_value.GetVariable()) {
+      auto *lldb_type = variable->GetType();
+      auto *symbol_file = lldb_type->GetSymbolFile();
+      auto uid = lldb_type->GetID();
+      if (auto dyn_type = symbol_file->ResolveTypeUID(uid, exe_ctx)) {
+        class_type_or_name.SetCompilerType(dyn_type->GetFullCompilerType());
+        value_type = Value::ValueType::eValueTypeLoadAddress;
+        dynamic_address = in_value.GetAddressOf();
+        return true;
+      }
+    }
+  }
+
   // First job, pull out the address at 0 offset from the object.
   AddressType address_type;
   lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
   if (original_ptr == LLDB_INVALID_ADDRESS)
     return false;
 
-  ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
-
   Process *process = exe_ctx.GetProcessPtr();
-
   if (process == nullptr)
     return false;
 
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] = i;
+
+  pause(); // break here
+  return vla[a-1];
+}
+
+int main (void) {
+  return foo(2) + foo(4);
+}
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'))
+
+        for i in range(2):
+            self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%i])
+            self.expect("expr vla[%d]"%i, substrs=["int", "%d"%i])
+        array = ["int [2]", "1", "2"]
+        self.expect("fr v -d run-target -- vla", substrs=array)
+
+        process.Continue()
+        for i in range(4):
+            self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%i])
+            self.expect("expr vla[%d]"%i, substrs=["int", "%d"%i])
+        array = ["int [4]", "1", "2", "3", "4"]
+        self.expect("fr v -d run-target -- vla", substrs=array)
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: include/lldb/Symbol/Variable.h
===================================================================
--- include/lldb/Symbol/Variable.h
+++ include/lldb/Symbol/Variable.h
@@ -64,7 +64,7 @@
   bool NameMatches(const RegularExpression &regex) const;
 
   Type *GetType();
-
+ 
   lldb::LanguageType GetLanguage() const;
 
   lldb::ValueType GetScope() const { return m_scope; }
Index: include/lldb/Symbol/SymbolFile.h
===================================================================
--- include/lldb/Symbol/SymbolFile.h
+++ include/lldb/Symbol/SymbolFile.h
@@ -128,7 +128,9 @@
   virtual size_t ParseFunctionBlocks(const SymbolContext &sc) = 0;
   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;
+  virtual Type *
+  ResolveTypeUID(lldb::user_id_t type_uid,
+                 const lldb_private::ExecutionContextRef exe_ctx = {}) = 0;
   virtual bool CompleteType(CompilerType &compiler_type) = 0;
   virtual void ParseDeclsForContext(CompilerDeclContext decl_ctx) {}
   virtual CompilerDecl GetDeclForUID(lldb::user_id_t uid) {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to