llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.59k stars 11.82k forks source link

error: calling 'f' with incomplete return type 'string' (aka 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >') #30959

Open safinaskar opened 7 years ago

safinaskar commented 7 years ago
Bugzilla Link 31611
Version 3.9
OS Linux
CC @jimingham,@labath

Extended Description

/o.cpp:

#include <string>

std::string
f (void)
{
  return "abc";
}

int
main (void)
{
  f ();
}
root@ideal-os:~# clang++-3.9 -g -o /o /o.cpp
root@ideal-os:~# lldb-3.9 /o
(lldb) target create "/o"
Current executable set to '/o' (x86_64).
(lldb) b main
Breakpoint 1: where = o`main + 12 at o.cpp:12, address = 0x000000000040084c
(lldb) r
Process 146 launched: '/o' (x86_64)
Process 146 stopped
* thread #1: tid = 146, 0x000000000040084c o`main + 12 at o.cpp:12, name = 'o', stop reason = breakpoint 1.1
    frame #0: 0x000000000040084c o`main + 12 at o.cpp:12
(lldb) p f ()
error: calling 'f' with incomplete return type 'string' (aka 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >')
'f' declared here
forward declaration of 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >'
(lldb) root@ideal-os:~# 
root@ideal-os:~# dpkg -l lldb-3.9 clang-3.9
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                   Version          Architecture     Description
+++-======================-================-================-=================================================
ii  clang-3.9              1:3.9.1-2        amd64            C, C++ and Objective-C compiler (LLVM based)
ii  lldb-3.9               1:3.9.1-2        amd64            Next generation, high-performance debugger
root@ideal-os:~# lldb-3.9 --version
lldb version 3.9.1 ( revision )
root@ideal-os:~# clang-3.9 -v
clang version 3.9.1-2 (tags/RELEASE_391/rc2)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/5
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.1
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/6
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.4.1
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.3.0
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
root@ideal-os:~#

debian gnu/linux sid. clang and lldb from debian repo. amd64

safinaskar commented 7 years ago

That "p f ()" example with "log enable lldb formatters": https://zerobin.net/?96b23e1b816cd6de#CAfJwXIMITirMkG5jT84K8Yylywgfujv1KnraRta7/o= . With clang and lldb from trunk

jimingham commented 7 years ago

So far as I can tell, there are two problems here.

One is that for complex C++ programs (and pretty much anything that uses STL is a complex C++ program...) you have to use -fno-limit-debug-info. There are other bugs on this, so I don't think that's the crucial issue for this report.

The other issue is the difference between printing for a static string and a function that returns a string.

In the former case, you show:

(lldb) p s (std::__cxx11::string) $0 = "gggg"

That is the correct, expected behavior. If you wanted to see the fields you would either turn of the C++ data formatters, or use "expr -R --".

But for a function returning a string, you show:

(lldb) p f () (std::__cxx11::string) $0 = { _M_dataplus = (_M_p = "abc") _M_string_length = 3 = (_M_local_buf = char [16] @ 0x000055d1848ae960, _M_allocated_capacity = 6513249) }

That is the unexpected behavior, you should have seen the results of the data formatter. If you turn on the formatter log, you might get more information on why this is failing:

(lldb) log enable lldb formatters

safinaskar commented 7 years ago

In this case, installing the debug info for libstdc++ should fix the problem, but there are situations where that would not help, and -fno-limit-debug-info is the recommended compiler option when debugging with lldb (it's the default on osx, as there lldb is the default system debugger). I use libstdc++. Seems to be related: https://llvm.org/bugs/show_bug.cgi?format=multiple&id=23385 .

Thanks. I've tried the same commands with trunk lldb and they work as expected (the summary is shown instead of the normal object content). Could you try out compiling lldb trunk and trying to reproduce it there?

I build current llvm, clang and lldb trunk and got the same. Both sources require -fno-limit-debug-info. And the sources give different representations of std::string. Log: https://zerobin.net/?702c8fda82f04533#Jcu656tXwtSyMga8UoSpUeqesgKRwX3cTNOInlXArkU= . I use normal current debian sid. With libstdc++. I can send you this linux container.

[begin of note] There is some libedit issue here, so I have to use this "cat | lldb" trick. This bug already reported here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=846616 . Please don't start discussing it here, this bug report already full of unrelated bugs. If you want me to create separate bug report for this, please say me so. [end of note]

labath commented 7 years ago

First, the very first code example I showed in this bug report cannot be properly debugged without -fno-limit-debug-info. "p f ()" simply doesn't work. Is this bug and using -fno-limit-debug-info is just temporary workaround? Or this is not bug and using -fno-limit-debug-info is recommended solution?

In this case, installing the debug info for libstdc++ should fix the problem, but there are situations where that would not help, and -fno-limit-debug-info is the recommended compiler option when debugging with lldb (it's the default on osx, as there lldb is the default system debugger).

I put files into /root. And I still see all bugs. I. e. debugging is still broken without -fno-limit-debug-info (with both sources). And std::string is still printed differently. Log is here: https://zerobin.net/?98b10a5640ab224d#JSk9fir+WaXR53DMe/ LeIXDePmutFiecbyTnXGd64P8=

Thanks. I've tried the same commands with trunk lldb and they work as expected (the summary is shown instead of the normal object content). Could you try out compiling lldb trunk and trying to reproduce it there?

safinaskar commented 7 years ago

First, the very first code example I showed in this bug report cannot be properly debugged without -fno-limit-debug-info. "p f ()" simply doesn't work. Is this bug and using -fno-limit-debug-info is just temporary workaround? Or this is not bug and using -fno-limit-debug-info is recommended solution?

I put files into /root. And I still see all bugs. I. e. debugging is still broken without -fno-limit-debug-info (with both sources). And std::string is still printed differently. Log is here: https://zerobin.net/?98b10a5640ab224d#JSk9fir+WaXR53DMe/LeIXDePmutFiecbyTnXGd64P8=

labath commented 7 years ago

There are two issues here: a) lldb is bad at working with files which are located directly in the root directory b) inconsistent printing of std::string values

(a) should be fixed by https://reviews.llvm.org/D28677. It's possible this will fix the other issue as well, as it can happen that this interferes with our ability to parse dwarf. To verify whether (b) is still an issue (I can't seem to reproduce it, but I am not sure if I am doing it right), could you do one of the following: i) Recompile lldb with the patch I linked to above. ii) Make sure the source file and executable are not in the root directory. E.g. put them in /tmp.

jimingham commented 7 years ago

Since lldb does not suppress any fields based on accessibility at present, if fields are missing from the printing of an object they are most likely missing or incomplete in the DWARF as well, which would be a clang not an lldb bug.

I can't reproduce this problem on OS X - I always see all the fields - so I can't verify this contention. But if you can dump the dwarf for your examples you could probably do so pretty easily.

safinaskar commented 7 years ago

I try to repeat.

In the first code example lldb shows private fields (with -fno-limit-debug-info with default settings) and in the second code - does not (with -fno-limit-debug-info with default settings).

And this is bug.

lldb should in both cases show private fields (with default settings!). Or in both cases hide them. And, of course, it should provide some way to change default behavior

jimingham commented 7 years ago

The debugger has to be able to show the private fields of classes or it would be useless to developers of the library vending those classes.

It would be fine to add a setting somewhere directing lldb to hide private fields. You'd probably want some way to specify which classes you need to see all of Even if you are using a lot of STL and don't want to see those classes private fields, you've probably still got your own classes and you'll need to see all of them.

Feel free to file an enhancement request to add that, or try adding it yourself.

safinaskar commented 7 years ago

Okey, but that example with f () shows private fields. So, this is a bug. It should not show this fields, too

jimingham commented 7 years ago

The omission of the actual std::string fields is by design. Most people don't care about the internal details of std::string, they just want to see the string, so by default, lldb just shows the result of the summary data format provider. If you want to see the internal details instead, do:

(lldb) expr -R -- s

safinaskar commented 7 years ago

My second example works with -fno-limit-debug-info, too. But now I see just string itself, without private fields.

root@ideal-os:/# lldb-3.9 ./o
(lldb) target create "./o"
Current executable set to './o' (x86_64).
(lldb) b main
Breakpoint 1: where = o`main + 6 at //o.cpp:8, address = 0x00000000004008d6
(lldb) r
Process 64 launched: './o' (x86_64)
Process 64 stopped
* thread #1: tid = 64, 0x00000000004008d6 o`main + 6 at //o.cpp:8, name = 'o', stop reason = breakpoint 1.1
    frame #0: 0x00000000004008d6 o`main + 6 at //o.cpp:8
   5    int
   6    main (void)
   7    {
-> 8    }
(lldb) p s
(std::__cxx11::string) $0 = "gggg"
safinaskar commented 7 years ago

The result is still strange. I see internal representation of std::string. But in other cases I see just (std::__cxx11::string) $0 = "abc"

safinaskar commented 7 years ago

With -fno-limit-debug-info it works.

Also, I will not keep this Linux container forever. I will delete it. This is just normal debian sid created using debootstrap and spawned using systemd-nspawn. If you want, I can send this container to you.

root@ideal-os:/# clang++-3.9 -fno-limit-debug-info -g -o o o.cpp
root@ideal-os:/# lldb-3.9 ./o
(lldb) target create "./o"
Current executable set to './o' (x86_64).
(lldb) b main
Breakpoint 1: where = o`main + 12 at //o.cpp:12, address = 0x000000000040084c
(lldb) r
Process 109 launched: './o' (x86_64)
Process 109 stopped
* thread #1: tid = 109, 0x000000000040084c o`main + 12 at //o.cpp:12, name = 'o', stop reason = breakpoint 1.1
    frame #0: 0x000000000040084c o`main + 12 at //o.cpp:12
   9    int
   10   main (void)
   11   {
-> 12     f ();
   13   }
(lldb) p f ()
(std::__cxx11::string) $0 = {
  _M_dataplus = (_M_p = "abc")
  _M_string_length = 3
   = (_M_local_buf = char [16] @ 0x000055cd134b1ce0, _M_allocated_capacity = 6513249)
}
(lldb)
labath commented 7 years ago

Could you try recompiling the test binary with -fno-limit-debug-info?

safinaskar commented 7 years ago

Here I occasionally specified absolute path for /o.cpp and so lldb was unable to find sources. But if I replace this:

clang++-3.9 -g -o /o /o.cpp; lldb-3.9 /o

with this:

cd /; clang++-3.9 -g -o o o.cpp; lldb-3.9 ./o

then lldb will find the source and the bug will still persist

jimingham commented 7 years ago

Same example works correctly on OS X using TOT lldb & clang.

safinaskar commented 7 years ago

Also (in the same environment):

root@ideal-os:~# cat /o.cpp
#include <string>

std::string s = "gggg";

int
main (void)
{
}
root@ideal-os:~# clang++-3.9 -std=c++11 -g -o /o /o.cpp
root@ideal-os:~# lldb-3.9 /o
(lldb) target create "/o"
Current executable set to '/o' (x86_64).
(lldb) r
Process 484 launched: '/o' (x86_64)
Process 484 exited with status = 0 (0x00000000) 
(lldb) b main
Breakpoint 1: where = o`main + 6 at o.cpp:8, address = 0x00000000004008d6
(lldb) r
Process 502 launched: '/o' (x86_64)
Process 502 stopped
* thread #1: tid = 502, 0x00000000004008d6 o`main + 6 at o.cpp:8, name = 'o', stop reason = breakpoint 1.1
    frame #0: 0x00000000004008d6 o`main + 6 at o.cpp:8
(lldb) p s 
error: incomplete type 'string' (aka 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >') where a complete type is required
forward declaration of 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >'
(lldb)