Bug 83906 - Random FAIL: libstdc++-prettyprinters/80276.cc whatis p4
Summary: Random FAIL: libstdc++-prettyprinters/80276.cc whatis p4
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: testsuite-fail
Depends on:
Blocks:
 
Reported: 2018-01-16 20:15 UTC by H.J. Lu
Modified: 2021-12-19 01:08 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-01-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2018-01-16 20:15:27 UTC
On i686 and x86-64, I am getting random:

FAIL: libstdc++-prettyprinters/80276.cc whatis p4
Comment 1 Jonathan Wakely 2018-01-19 11:16:51 UTC
What is shown in the libstdc++.log file before the FAIL line?
Comment 2 H.J. Lu 2018-01-19 11:51:54 UTC
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
Comment 3 Jonathan Wakely 2018-01-19 12:16:50 UTC
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.
Comment 4 Jonathan Wakely 2018-01-19 12:21:02 UTC
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;
Comment 5 H.J. Lu 2018-01-19 13:41:31 UTC
(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.
Comment 6 Jakub Jelinek 2018-01-23 12:00:45 UTC
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?
Comment 7 Jakub Jelinek 2018-01-23 12:59:40 UTC
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.
Comment 8 Jonathan Wakely 2018-01-23 13:36:59 UTC
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.
Comment 9 Jakub Jelinek 2018-01-23 15:09:44 UTC
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.
Comment 10 Pedro Alves 2018-01-23 15:19:10 UTC
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.
Comment 11 Pedro Alves 2018-01-23 17:15:44 UTC
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.)
Comment 12 Pedro Alves 2018-01-24 17:28:28 UTC
GDB fix posted here:
 https://sourceware.org/ml/gdb-patches/2018-01/msg00482.html
Comment 13 Pedro Alves 2018-01-24 19:30:43 UTC
Fix is now in GDB's master, 8.1, and 8.0 branches.
Comment 14 H.J. Lu 2018-01-27 19:03:05 UTC
Fixed by gdb.
Comment 15 Jonathan Wakely 2018-01-27 22:33:35 UTC
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 :-)
Comment 16 Jakub Jelinek 2018-03-13 08:19:39 UTC
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?
Comment 17 Jonathan Wakely 2018-03-13 09:23:14 UTC
Ideally I want the printer to still work for users with older versions of gdb.
Comment 18 Jonathan Wakely 2018-03-13 09:24:13 UTC
But we can remove the [8 Regression] marker if it's messing with reports.
Comment 19 Jakub Jelinek 2018-03-13 09:27:48 UTC
Ok, let's do it.
Comment 20 Jakub Jelinek 2018-05-02 10:05:33 UTC
GCC 8.1 has been released.
Comment 21 Jakub Jelinek 2018-07-26 11:19:32 UTC
GCC 8.2 has been released.
Comment 22 Jonathan Wakely 2019-01-22 14:49:50 UTC
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).
Comment 23 Jonathan Wakely 2019-01-22 15:10:00 UTC
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>.