Skip to content

LLDB: reference to std::deque<> incorrectly shows size zero #62153

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexolog opened this issue Apr 15, 2023 · 9 comments
Closed

LLDB: reference to std::deque<> incorrectly shows size zero #62153

alexolog opened this issue Apr 15, 2023 · 9 comments
Labels

Comments

@alexolog
Copy link

Tested on an M1 Mac running OS X 13.3 under VSCode
Reproduced on an Intel Mac under CLion

image

@llvmbot
Copy link
Member

llvmbot commented Apr 15, 2023

@llvm/issue-subscribers-lldb

@Michael137
Copy link
Member

Michael137 commented Apr 15, 2023

Does this only happen in the IDE for you? Can you try using command-line LLDB and see if it makes a difference?

EDIT:
Ah nvm, I wasn't printing the reference. This does repro for me on top-of-tree but only for frame var interestingly:

$ cat dequeue.cpp 
#include <deque>

int main() {
    std::deque<int> q{10};
    auto& ref = q;
    return 0;
}

$ ./bin/lldb a.out -b -o version -o "br se -p return" -o run -o "frame var ref" -o "expr ref"

(lldb) br se -p return
Breakpoint 1: where = a.out`main + 72 at deque.cpp:6:5, address = 0x00000001000037f4
(lldb) run
Process 48032 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001000037f4 a.out`main at dequeue.cpp:6:5
   3    int main() {
   4        std::deque<int> q{10};
   5        auto& ref = q;
-> 6        return 0;
   7    }
Process 48032 launched: '/Users/michaelbuch/a.out' (arm64)
(lldb) frame var ref
(std::deque<int> &) ref = size=0 {}
(lldb) expr ref
(std::deque<int>) $0 = size=1 {
  [0] = 10
}

@alexolog
Copy link
Author

I am not using the command-line LLDB, so even if there is a way to coerce it to display the correct value, but it is not available to the IDE, it is still a problem.

@Michael137
Copy link
Member

Sure, was curious because I wanted to narrow down which part of lldb this problem occurs in. Definitely needs attention either way

@Michael137
Copy link
Member

Michael137 commented Apr 17, 2023

So looks like the std::deque formatter is a bit special in that it uses a python implementation instead of C++

cpp_category_sp->AddTypeSynthetic(                                     
    "^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$", eFormatterMatchRegex,
    SyntheticChildrenSP(new ScriptedSyntheticChildren(                 
        stl_synth_flags,                                               
        "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));        

Having stepped through the python implementation looks like the failure occurs in the following location:

def find_block_size(self):                                                                                     
    # in order to use the deque we must have the block size, or else                                           
    # it's impossible to know what memory addresses are valid                                                                                                  
    self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)                                       
    self.element_size = self.element_type.GetByteSize()                                                        
    # The code says this, but there must be a better way:                                                      
    # template <class _Tp, class _Allocator>                                                                   
    # class __deque_base {                                                                                     
    #    static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
    # }                                                                                                        
    if self.element_size < 256:                                                                                
        self.block_size = 4096 // self.element_size                 <<<< Throw division by zero exception                                                                                                

When we have a reference type we fail to GetTemplateArgumentType so the element_size is 0 and the whole thing just fails.

Looking at other places where we use GetTemplateArgumentType, they're guarded by a block like:

if list_type.IsReferenceType():                 
    list_type = list_type.GetDereferencedType() 

Adding this to the failing block in the deque summary provider fixes the issue for me. Will submit a patch shortly

@Michael137
Copy link
Member

@jimingham
Copy link
Collaborator

jimingham commented Apr 17, 2023 via email

@Michael137
Copy link
Member

You would expect this example to fail, right? You're stopped before the variable is initialized. It looks like someone nicely 0-initialized your locals, but this doesn't have a value yet...

Jim

On Apr 14, 2023, at 6:25 PM, Michael Buch @.***> wrote:

can repro on top-of-tree

$ cat dequeue.cpp
#include

int main() {
std::deque q{10};
auto& ref = q;
return 0;
}

$ ./bin/lldb a.out -b -o version -o "b main" -o run -o "expr q"
(lldb) b main
Breakpoint 1: where = a.out`main + 20 at dequeue.cpp:4:22, address = 0x00000001000037c0
(lldb) run
Process 46394 stopped

Yup I realised shortly after posting that original comment. The edited comment shows the actual reproducer

@Michael137
Copy link
Member

Michael137 commented Apr 17, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants