Hi,

When the inferior is built with GCC 4.7.2, the DWARF contains duplicate
DW_AT_template_type_param DIEs for std::vector (and others). There is a
reported GCC bug about it (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54410).
Because of this, lldb parses the type
"std::vector<bool, std::allocator<bool> >" as
"std::vector<bool, std::allocator<bool, bool>, bool, std::allocator<bool,
bool> >".
Later, the FormatManager fails to match this type with the appropriate
SyntheticChildrenFrontEnd for std::vector<bool>. The printable
representation produced is then the incorrect:
(lldb) frame variable vBool
(std::vector<bool, std::allocator<bool, bool>, bool, std::allocator<bool,
bool> >) vBool = size=0 {}

I've attached 3 patches (against r181819) for review:
- An attempt at a workaround for the GCC bug
- A change in the FormatManager to allow "std::vector<bool,
  std:allocator<bool> >" to be matched to the vector<bool> Synthetic.
- The re-enabling of the test case

Thanks,
Yacine

> http://llvm.org/bugs/show_bug.cgi?id=15301
> 
>             Bug ID: 15301
>            Summary: LLDB prints incorrect size of libstdc++ vector<bool>
>                     containers (when inferior built with GCC on Linux)
>            Product: lldb
>            Version: unspecified
>           Hardware: PC
>                 OS: Linux
>             Status: NEW
>           Severity: enhancement
>           Priority: P
>          Component: All Bugs
>           Assignee: lldb-dev at cs.uiuc.edu
>           Reporter: daniel.malea at intel.com
>     Classification: Unclassified
> 
> In the TestDataFormatterStdVBool, instead of printing the correct size
> (49) lldb prints -1 for the size of the std::vector<bool> container
> (libstdc++).
> 
> To reproduce, run:
> 
> python dotest.py
> functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool -C gcc
> 
> -- 
> You are receiving this mail because:
> You are the assignee for the bug.
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: 
> <http://lists.cs.uiuc.edu/pipermail/lldb-dev/attachments/20130219/8ff9c75c/attachment-0001.html>




>From 378aa04846a502dca2ad003ba13d14d51974f226 Mon Sep 17 00:00:00 2001
From: Yacine Belkadi <[email protected]>
Date: Wed, 15 May 2013 21:52:00 +0200
Subject: [PATCH 1/3] SymbolFile/DWARF: Ignore duplicate template parameters

DWARF produced by some versions of GCC (e.g. 4.7.2) may contain duplicate
DW_TAG_template_value_param or DW_TAG_template_type_param entries. This results
in incorrect parsing of types. For example:
"std::vector<bool, std::allocator<bool, bool>, bool, std::allocator<bool, bool> >"
instead of "std::vector<bool, std::allocator<bool> >".

Fix that by ignoring duplicate template parameter DIE for DWARF produced by GCC.
---
 .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp  |    9 ++++++
 source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h |    3 ++
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp   |   33 ++++++++++++++------
 3 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index ed615c4..ff4ce1b 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -942,6 +942,15 @@ DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid()
     return GetProducer() == eProducerLLVMGCC;
 }
 
+bool
+DWARFCompileUnit::MayContainDuplicateTemplateParameterDIE()
+{
+    // Some versions of GCC may produce duplicate DW_TAG_template_type_param or
+    // DW_TAG_template_value_param in the DWARF.
+    // GCC bug #54410
+    return GetProducer() == eProducerGCC;
+}
+
 void
 DWARFCompileUnit::ParseProducerInfo ()
 {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 9fee0a2..459f78d 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -147,6 +147,9 @@ public:
     bool
     Supports_unnamed_objc_bitfields ();
 
+    bool
+    MayContainDuplicateTemplateParameterDIE();
+
 //    void
 //    AddGlobalDIEByIndex (uint32_t die_idx);
 //
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9dd1dd4..5319b0a 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1280,12 +1280,11 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
 
                 if (clang_type)
                 {
+                    if (!(name && name[0]))
+                        name = NULL;
+
+                    clang::TemplateArgument arg;
                     bool is_signed = false;
-                    if (name && name[0])
-                        template_param_infos.names.push_back(name);
-                    else
-                        template_param_infos.names.push_back(NULL);
-    
                     clang::QualType clang_qual_type (clang::QualType::getFromOpaquePtr (clang_type));
                     if (tag == DW_TAG_template_value_parameter &&
                         lldb_type != NULL &&
@@ -1293,14 +1292,30 @@ SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
                         uval64_valid)
                     {
                         llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
-                        template_param_infos.args.push_back (clang::TemplateArgument (*ast,
-                                                                                      llvm::APSInt(apint),
-                                                                                      clang_qual_type));
+                        arg = clang::TemplateArgument(*ast, llvm::APSInt(apint), clang_qual_type);
                     }
                     else
                     {
-                        template_param_infos.args.push_back (clang::TemplateArgument (clang_qual_type));
+                        arg = clang::TemplateArgument(clang_qual_type);
                     }
+
+                    if (dwarf_cu->MayContainDuplicateTemplateParameterDIE() && name)
+                    {
+                        // Ignore already seen template parameters.
+                        size_t num_template_params = template_param_infos.GetSize();
+                        for (size_t i = 0; i < num_template_params; ++i)
+                        {
+                            if (template_param_infos.names[i] &&
+                                (::strcmp(name, template_param_infos.names[i]) == 0) &&
+                                arg.structurallyEquals(template_param_infos.args[i]))
+                            {
+                                return false;
+                            }
+                        }
+                    }
+
+                    template_param_infos.names.push_back(name);
+                    template_param_infos.args.push_back(arg);
                 }
                 else
                 {
-- 
1.7.10.4


>From a815d851c1dc15225f2efd86726aa590adf64023 Mon Sep 17 00:00:00 2001
From: Yacine Belkadi <[email protected]>
Date: Wed, 15 May 2013 21:56:57 +0200
Subject: [PATCH 2/3] FormatManager: Match "std::vector<bool,
 std:allocator<bool> >" to the "vector<bool>" Synth

The type "std::vector<bool, std:allocator<bool> >" wasn't matched to the
appropriate SyntheticChildrenFrontEnd for std::vector<bool>.

Add a regular expression to match both:
"std::vector<bool, std:allocator<bool> >" (produced by GCC)
and
"std::vector<std:allocator<bool> >" (produced by Clang)

Remove the vector<bool> specific Summary, as it's the same as the one for
other vectors.
---
 source/DataFormatters/FormatManager.cpp |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index a6a5416..6102003 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -554,7 +554,10 @@ FormatManager::LoadLibStdcppFormatters()
     
     SyntheticChildren::Flags stl_synth_flags;
     stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
-    
+
+    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::vector<(bool,( )?)?std::allocator<bool> >$")),
+                                                       SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags, "libstdc++ std::vector<bool> synthetic children",
+                                                                                                    lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator)));
     gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
                                                        SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
                                                                                                  "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
@@ -579,12 +582,6 @@ FormatManager::LoadLibStdcppFormatters()
     AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
     
     AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
-    
-    gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::vector<std::allocator<bool> >"),
-                                                   TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
-    
-    gnu_category_sp->GetSyntheticNavigator()->Add(ConstString("std::vector<std::allocator<bool> >"),
-                                                     SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector<bool> synthetic children",lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator)));
 
 #endif
 }
-- 
1.7.10.4


>From 3d6c0438e657fadb5e3e95e2b1b3fab3366d457a Mon Sep 17 00:00:00 2001
From: Yacine Belkadi <[email protected]>
Date: Wed, 15 May 2013 22:03:07 +0200
Subject: [PATCH 3/3] Tests: Re-enable TestDataFormatterStdVBool.py

---
 .../data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py   |    1 -
 1 file changed, 1 deletion(-)

diff --git a/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py b/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
index 8de8be7..e035418 100644
--- a/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
+++ b/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
@@ -31,7 +31,6 @@ class StdVBoolDataFormatterTestCase(TestBase):
         # Find the line number to break at.
         self.line = line_number('main.cpp', '// Set break point at this line.')
 
-    @expectedFailureGcc # PR-15301: lldb does not print the correct sizes of STL containers when building with GCC
     def data_formatter_commands(self):
         """Test that that file and class static variables display correctly."""
         self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
-- 
1.7.10.4


_______________________________________________
lldb-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to