On i686 and x86-64, I am getting random: FAIL: libstdc++-prettyprinters/80276.cc whatis p4
What is shown in the libstdc++.log file before the FAIL line?
type = std::unique_ptr<std::vector<std::unique_ptr<std::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >>[]>>[99]>^M got: type = std::unique_ptr<std::vector<std::unique_ptr<std::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >>[]>>[99]>^M FAIL: libstdc++-prettyprinters/80276.cc whatis p4
That suggests the type printer for std::__cxx11::string is not being used, so maybe it's conflicting with another printer, and so the result depends which gets found first.
Ah, or maybe the typedef std::__cxx11::string is not in the debug info, so the type printer doesn't know that std::__cxx11::basic_string<char> is the same type as std::__cxx11::string. In testsuite/libstdc++-prettyprinters/whatis.cc we have a relevant comment: // This test is written in a somewhat funny way. // Each type under test is used twice: first, to form a pointer type, // and second, as a template parameter. This is done to work around // apparent GCC oddities. The pointer type is needed to ensure that // the typedef in question ends up in the debuginfo; while the // template type is used to ensure that a typedef-less variant is // presented to gdb. Does this patch help? --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc @@ -36,6 +36,7 @@ placeholder(const T *s) int main() { + std::string *string_ptr; using namespace std; unique_ptr<vector<unique_ptr<vector<int>*>>> p1; unique_ptr<vector<unique_ptr<set<int>*>>[]> p2; @@ -50,6 +51,7 @@ main() placeholder(&p2); placeholder(&p3); placeholder(&p4); + placeholder(&string_ptr); std::cout << "\n"; return 0;
(In reply to Jonathan Wakely from comment #4) > Ah, or maybe the typedef std::__cxx11::string is not in the debug info, so > the type printer doesn't know that std::__cxx11::basic_string<char> is the > same type as std::__cxx11::string. > > In testsuite/libstdc++-prettyprinters/whatis.cc we have a relevant comment: > > // This test is written in a somewhat funny way. > // Each type under test is used twice: first, to form a pointer type, > // and second, as a template parameter. This is done to work around > // apparent GCC oddities. The pointer type is needed to ensure that > // the typedef in question ends up in the debuginfo; while the > // template type is used to ensure that a typedef-less variant is > // presented to gdb. > > > Does this patch help? > > --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc > +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc > @@ -36,6 +36,7 @@ placeholder(const T *s) > int > main() > { > + std::string *string_ptr; > using namespace std; > unique_ptr<vector<unique_ptr<vector<int>*>>> p1; > unique_ptr<vector<unique_ptr<set<int>*>>[]> p2; > @@ -50,6 +51,7 @@ main() > placeholder(&p2); > placeholder(&p3); > placeholder(&p4); > + placeholder(&string_ptr); > > std::cout << "\n"; > return 0; This doesn't explain why does it fail at random.
I've even seen in one recent regtest: FAIL: libstdc++-prettyprinters/80276.cc whatis p4 FAIL: libstdc++-prettyprinters/80276.cc whatis p4 where both normal15 and normal16 directories contained the FAILs. Perhaps the parallelization of libstdc++ tests got out of sync?
Actually, the bug seems to FAIL at random, as shown by: while :; do echo -n .; make check RUNTESTFLAGS=prettyprinters.exp=80276.cc > /dev/null 2>/dev/null; grep -q ^FAIL testsuite/libstdc++.log && break; done Got one FAIL after printing 3 dots, another time after 5 dots, then 1 dot, 1 dot again. With patched 80276.cc with your patch, I get one FAIL after printing 2 dots, then 1 dot, 1 dot, 5 dots. So no, this patch doesn't help. This was i686-linux build, gdb-8.0.1-33.fc27.x86_64.
The bug is here: if self.type_obj == type_obj: return strip_inline_namespaces(self.name) This assumes the two types resolve to the same gdb.Type but that isn't guaranteed.
If I retry this while :; do echo -n .; make check RUNTESTFLAGS=prettyprinters.exp=80276.cc > /dev/null 2>/dev/null; grep -q ^FAIL testsuite/libstdc++.log && break; done under setarch x86_64 -R /bin/sh shell, I see no random failures, 20 PASSes in a row, then I've Ctrl-Ced it. The question is if this is because of ASLR of the gdb process, or ASLR of the debugger process.
GDB starts inferiors with ASLR disabled by default: (gdb) show disable-randomization Disabling randomization of debuggee's virtual address space is on. so if this is ASLR, it's going to be ASLR of the gdb process. Which sounds consistent with Jonathan's finding.
Running the testcase under valgrind and current gdb master I see: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ==6118== Conditional jump or move depends on uninitialised value(s) ==6118== at 0x4C35CB0: bcmp (vg_replace_strmem.c:1100) ==6118== by 0x6F773A: check_types_equal(type*, type*, VEC_type_equality_entry_d**) (gdbtypes.c:3515) ==6118== by 0x6F7B00: check_types_worklist(VEC_type_equality_entry_d**, bcache*) (gdbtypes.c:3618) ==6118== by 0x6F7C03: types_deeply_equal(type*, type*) (gdbtypes.c:3655) ==6118== by 0x4D5B06: typy_richcompare(_object*, _object*, int) (py-type.c:1007) ==6118== by 0x63D7E6C: PyObject_RichCompare (object.c:961) ==6118== by 0x646EAEC: PyEval_EvalFrameEx (ceval.c:4960) ==6118== by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519) ==6118== by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519) ==6118== by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519) ==6118== by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519) ==6118== by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AFAICT so far, looks like gdb is memcmp'ing two objects that only differ in padding. Looks like objects of this type range_bounds are always memset when allocated, so I'm not sure that is going on. (The type is trivial.)
GDB fix posted here: https://sourceware.org/ml/gdb-patches/2018-01/msg00482.html
Fix is now in GDB's master, 8.1, and 8.0 branches.
Fixed by gdb.
I'd like to add a workaround so it works with older GDB versions. There's more to life than ensuring our testsuite has no FAILs :-)
So just add a gdb >= 8.1 version test in libstdc++-v3/testsuite/lib/gdb-test.exp and guard this test on effective target gdb_8_1?
Ideally I want the printer to still work for users with older versions of gdb.
But we can remove the [8 Regression] marker if it's messing with reports.
Ok, let's do it.
GCC 8.1 has been released.
GCC 8.2 has been released.
Pedro, I'm seeing this again with GDB 8.2 (specifically gdb-8.2-6.fc29.x86_64). Is it likely to be something different, or a GDB regression? (I still want a libstdc++ fix that works for older GDB anyway).
Actually, I wonder if it's caused by r264958 because 'std::string' is no longer unambiguous in libstdc++.so In some translation units it is a typedef for std::basic_string<char> and in other translation units it is a typedef for std::__cxx11::basic_string<char>.