<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Sep 1, 2014 at 2:28 PM, Yaron Keren <span dir="ltr"><<a href="mailto:yaron.keren@gmail.com" target="_blank">yaron.keren@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl"><div dir="ltr">There is no debug variant of libstdc++, just release DLL, import lib for this DLL and a static lib. You can see all the files (even without actually running Windows) in the install 7z file:</div>


<div dir="ltr"><br></div><div dir="ltr"> <a href="http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.1/threads-posix/dwarf/" target="_blank">http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.1/threads-posix/dwarf/</a><br>


</div><div dir="ltr"><br></div><div dir="ltr">Anyhow, for your example,</div><div dir="ltr"><br></div><div dir="ltr">mingw (gcc 4.9.1)</div><div dir="ltr">------------------------</div><div dir="ltr"><br></div><div dir="ltr">


<div dir="ltr">0x00000072:   DW_TAG_structure_type [2] *</div><div dir="ltr">                DW_AT_name [DW_FORM_string]<span style="white-space:pre-wrap">      </span>("foo")</div><div dir="ltr">                DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div>


<div dir="ltr">                DW_AT_sibling [DW_FORM_ref4]<span style="white-space:pre-wrap">  </span>(cu + 0x008b => {0x0000008b})</div><div dir="ltr"><br></div><div dir="ltr">0x0000007b:     DW_TAG_subprogram [3] *</div>


<div dir="ltr">                  DW_AT_external [DW_FORM_flag_present]<span style="white-space:pre-wrap">      </span>(true)</div><div dir="ltr">                  DW_AT_name [DW_FORM_string]<span style="white-space:pre-wrap"> </span>("foo")</div>


<div dir="ltr">                  DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div><div dir="ltr">                  DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div>


<div dir="ltr">                  DW_AT_object_pointer [DW_FORM_ref4]<span style="white-space:pre-wrap">        </span>(cu + 0x0084 => {0x00000084})</div><div dir="ltr"><br></div><div dir="ltr">0x00000084:       DW_TAG_formal_parameter [4]  </div>


<div dir="ltr">                    DW_AT_type [DW_FORM_ref4]<span style="white-space:pre-wrap">       </span>(cu + 0x008b => {0x0000008b})</div><div dir="ltr">                    DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">        </span>(true)</div>


<div dir="ltr"><br></div><div dir="ltr">0x00000089:       NULL</div><div dir="ltr"><br></div><div dir="ltr">0x0000008a:     NULL</div><div><br></div></div><div dir="ltr"><br></div><div dir="ltr">clang trunk<br></div><div dir="ltr">


--------------</div><div dir="ltr"><br></div><div dir="ltr"><div dir="ltr">0x00000037:   DW_TAG_structure_type [3] *</div><div dir="ltr">                DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap">  </span>( .debug_str[0x00000048] = "foo")</div>


<div dir="ltr">                DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">      </span>(true)</div><div dir="ltr"><br></div><div dir="ltr">0x0000003c:     DW_TAG_subprogram [4] *</div><div dir="ltr">


                  DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap"> </span>( .debug_str[0x00000048] = "foo")</div><div dir="ltr">                  DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">       </span>(true)</div>


<div dir="ltr">                  DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div><div dir="ltr">                  DW_AT_external [DW_FORM_flag_present]<span style="white-space:pre-wrap">       </span>(true)</div>


<div dir="ltr">                  DW_AT_accessibility [DW_FORM_data1]<span style="white-space:pre-wrap">        </span>(0x01)</div><div dir="ltr"><br></div><div dir="ltr">0x00000042:       DW_TAG_formal_parameter [5]  </div>
<div dir="ltr">
                    DW_AT_type [DW_FORM_ref4]<span style="white-space:pre-wrap">      </span>(cu + 0x005b => {0x0000005b})</div><div dir="ltr">                    DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">        </span>(true)</div>


<div dir="ltr"><br></div><div dir="ltr">0x00000047:       NULL</div><div dir="ltr"><br></div><div dir="ltr">0x00000048:     NULL</div><div dir="ltr"><br></div><div>clang -fstandalone-debug</div><div>----------------------------------</div>


<div><br></div><div><div>0x00000037:   DW_TAG_structure_type [3] *</div><div>                DW_AT_containing_type [DW_FORM_ref4]<span style="white-space:pre-wrap"> </span>(cu + 0x0037 => {0x00000037})</div><div>                DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap">        </span>( .debug_str[0x0000007a] = "foo")</div>


<div>                DW_AT_byte_size [DW_FORM_data1]<span style="white-space:pre-wrap">   </span>(0x04)</div><div>                DW_AT_decl_file [DW_FORM_data1]<span style="white-space:pre-wrap">    </span>(0x01)</div>

<div>                DW_AT_decl_line [DW_FORM_data1]<span style="white-space:pre-wrap">   </span>(0x01)</div><div><br></div><div>0x00000043:     DW_TAG_member [4]  </div><div>                  DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap"> </span>( .debug_str[0x00000048] = "_vptr$foo")</div>


<div>                  DW_AT_type [DW_FORM_ref4]<span style="white-space:pre-wrap">      </span>(cu + 0x0075 => {0x00000075})</div><div>                  DW_AT_data_member_location [DW_FORM_data1]<span style="white-space:pre-wrap">    </span>(0x00)</div>


<div>                  DW_AT_accessibility [DW_FORM_data1]<span style="white-space:pre-wrap">    </span>(0x01)</div><div>                  DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap"> </span>(true)</div>


<div><br></div><div>0x0000004e:     DW_TAG_subprogram [5] *</div><div>                  DW_AT_MIPS_linkage_name [DW_FORM_strp]<span style="white-space:pre-wrap">        </span>( .debug_str[0x00000066] = "_ZN3foo4funcEv")</div>


<div>                  DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap">      </span>( .debug_str[0x00000075] = "func")</div><div>                  DW_AT_decl_file [DW_FORM_data1]<span style="white-space:pre-wrap">   </span>(0x01)</div>


<div>                  DW_AT_decl_line [DW_FORM_data1]<span style="white-space:pre-wrap">        </span>(0x01)</div><div>                  DW_AT_virtuality [DW_FORM_data1]<span style="white-space:pre-wrap">        </span>(0x01)</div>

<div>                  DW_AT_vtable_elem_location [DW_FORM_exprloc]<span style="white-space:pre-wrap">   </span>(<0x2> 10 00 )</div><div>                  DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">  </span>(true)</div>


<div>                  DW_AT_external [DW_FORM_flag_present]<span style="white-space:pre-wrap">  </span>(true)</div><div>                  DW_AT_accessibility [DW_FORM_data1]<span style="white-space:pre-wrap">     </span>(0x01)</div>


<div>                  DW_AT_containing_type [DW_FORM_ref4]<span style="white-space:pre-wrap">   </span>(cu + 0x0037 => {0x00000037})</div><div><br></div><div>0x00000062:       DW_TAG_formal_parameter [6]  </div><div>

                    DW_AT_type [DW_FORM_ref4]<span style="white-space:pre-wrap">      </span>(cu + 0x008f => {0x0000008f})</div><div>                    DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div>


<div><br></div><div>0x00000067:       NULL</div><div><br></div><div>0x00000068:     DW_TAG_subprogram [7] *</div><div>                  DW_AT_name [DW_FORM_strp]<span style="white-space:pre-wrap">    </span>( .debug_str[0x0000007a] = "foo")</div>


<div>                  DW_AT_declaration [DW_FORM_flag_present]<span style="white-space:pre-wrap">       </span>(true)</div><div>                  DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap"> </span>(true)</div>


<div>                  DW_AT_external [DW_FORM_flag_present]<span style="white-space:pre-wrap">  </span>(true)</div><div>                  DW_AT_accessibility [DW_FORM_data1]<span style="white-space:pre-wrap">     </span>(0x01)</div>


<div><br></div><div>0x0000006e:       DW_TAG_formal_parameter [6]  </div><div>                    DW_AT_type [DW_FORM_ref4]<span style="white-space:pre-wrap">        </span>(cu + 0x008f => {0x0000008f})</div><div>                    DW_AT_artificial [DW_FORM_flag_present]<span style="white-space:pre-wrap">    </span>(true)</div>


<div><br></div><div>0x00000073:       NULL</div><div><br></div><div>0x00000074:     NULL</div></div><div><br></div><div><br></div><div>That's consistent.</div><div><br></div><div>What's odd is for std::string gcc produces a definition while clang produce a declaration only unless -fstandalone-debug. That what causes the debug pretty printer problem.</div>
</div></div></blockquote><div><br></div><div>Yep - that's because Clang has another similar, bit different, optimization that's founded on the same principle (the idea that you will compile your whole program/libraries with debug info), using explicit template instantiations as a hint that the debug info will be available elsewhere anyway. GCC doesn't implement that particular optimization, but my point in the above example is that it implements similar things that are just as problematic for a user without debug libraries.<br>
<br>A specific STL example would be:<br><br>  #include <fstream><div><br></div><div>  int main() {</div><div>    std::ofstream f("foo.txt");</div><div>  }</div><br>Both Clang and GCC produce:<br><div><br></div>
<div>  DW_TAG_class_type [5]  </div><div>    DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000c7] = "basic_ofstream<char, std::char_traits<char> >")</div><div>    DW_AT_declaration [DW_FORM_flag_present]      (true)</div>
</div><div> <br>Because the vtable for basic_ofstream<char> is compiled into libstdc++.<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="rtl"><div dir="ltr">

<div><br></div><div><div>#include <string></div><div>int main() {</div><div>  std::string s("hello");</div><div>}<br></div></div><div><br></div><div>Since both gcc and clang share the same header files, library files and linker, it would seem that the decision rule when to produce a debug class definition is different between gcc and clang at least for std::string.</div>
</div></div></blockquote><div><br></div><div>Yep - the explicit template instantiation being the trigger clang is using for that. My vtable example was to demonstrate that GCC uses similar reasoning for other things (where GCC and Clang overlap more closely).<br>
<br>That said, I know next to nothing about MinGW distribution and "GCC does this" isn't itself an argument for Clang to do something, so I'm not exactly going to block this patch.<br><br>Do you have any idea if someone's filed a similar bug on GCC (do you care about GCC behavior, or only Clang?)? Any idea what their response was? (I imagine people in the GCC community might have more familiarity with MinGW/libstdc++ distribution practices than I do, and might have some other ideas about whether it's the right direction)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl"><div dir="ltr">


<div><br></div><div>Yaron</div><div><br></div></div><div dir="ltr"><br></div></div><div class="gmail_extra"><div dir="ltr"><br><br><div class="gmail_quote">2014-09-01 22:25 GMT+03:00 David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span>:<div>
<div><br>

<blockquote class="gmail_quote" style="margin:0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;border-right-width:1px;border-right-color:rgb(204,204,204);border-right-style:solid;padding-left:1ex;padding-right:1ex">
<br><div class="gmail_extra"><br><br><div class="gmail_quote"><div>
On Mon, Sep 1, 2014 at 11:38 AM, Yaron Keren <span dir="ltr"><<a href="mailto:yaron.keren@gmail.com" target="_blank">yaron.keren@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl"><div dir="ltr"><a href="http://llvm.org/bugs/show_bug.cgi?id=20741" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=20741</a><br>



<br>With the current default, a programmer compiling his program with clang -g will not get debug info for std::string members and thus the gdb pretty printer for std::string will fail. That's how I noticed the problem in the first place. Given that libstdc++ is used in every C++ program and that std::string is quite popular, this isn't a good result.</div>



</div></blockquote><div><br></div></div><div>On most linux distributions, there's a -dbg variant of libstdc++ that users can install to get the library's debug information (GCC relies on this for various parts of its debug output, for example - I'd be curious to know if their default is any different on MinGW). Is there no such thing on MinGW? (do you know if GCC does the same thing? try compiling this source file to an object file with gcc: "struct foo { virtual void func(); } foo f;" and see if GCC emits the definition of 'foo', or just a declaration - on Linux it'll only produce a declaration)</div>


<div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl">

<div dir="ltr"><br></div><div dir="ltr">This patch makes  -fstandalone-debug default on mingw.</div><div dir="ltr"><br></div></div>
</blockquote></div></div><br></div></blockquote></div></div></div></div></div>
</blockquote></div><br></div></div>