Can't convert char* to string in LLDB?

Here’s a trivial program. I stop in the main, and try calling foo("hi"). It fails. Apparently it can’t convert a char* to a std::string the way you can in normal C++ code. Is that expected?

#include <iostream>
#include <string>

using namespace std;

void foo(const string &s) { cout << "foo: " << s << endl; }

int main(int argc, char *argv[]) {    
    cout << "test\n";   // break here
}

LLDB console:

(lldb) p foo("hi")
error: <user expression 0>:1:1: no matching function for call to 'foo'
    1 | foo("hi")
      | ^~~
note: candidate function not viable: no known conversion from 'const char[3]' to 'const std::string' (aka 'const std::basic_string<char>') for 1st argument

It doesn’t recognize the using std:

(lldb) p foo(string("hi"))
error: <user expression 6>:1:5: use of undeclared identifier 'string'
    1 | foo(string("hi"))

If I use std::, it still fails. Any ideas?

(lldb) p foo(std::string("hi"))
error: <user expression 7>:1:5: no matching conversion for functional-style cast from 'const char[3]' to 'std::string' (aka 'std::basic_string<char>')
    1 | foo(std::string("hi"))
      |     ^~~~~~~~~~~~~~~~
note: candidate constructor not viable: no known conversion from 'const char[3]' to 'std::initializer_list<char>' for 1st argument

note: candidate constructor not viable: no known conversion from 'const char[3]' to 'nullptr_t' (aka 'std::nullptr_t') for 1st argument

note: candidate constructor not viable: no known conversion from 'const char[3]' to 'std::basic_string<char>' for 1st argument

note: candidate constructor not viable: no known conversion from 'const char[3]' to 'const std::basic_string<char>' for 1st argument

note: candidate constructor not viable: no known conversion from 'const char[3]' to 'const std::basic_string<char>::allocator_type' (aka 'const std::allocator<char>') for 1st argument

note: candidate constructor not viable: requires 0 arguments, but 1 was provided
... and on and on ...

Another try:

(lldb) p foo((const char*)"hi")
error: <user expression 8>:1:1: no matching function for call to 'foo'
    1 | foo((const char*)"hi")
      | ^~~
note: candidate function not viable: no known conversion from 'const char *' to 'const std::string' (aka 'const std::basic_string<char>') for 1st argument

Looks like you ran into a couple of subtleties of the expression evaluator:

Your call to foo("hi") is failing because you don’t have debug-info for the basic_string(char const*) constructor, so LLDB can’t provide the embedded Clang instance with the correct CXXConstructorDecl. So we need up claiming there is no conversion from const char[3] to std::string.

That being said, even if we instantiate the std::string constructor explicitly in the source, we still don’t get the debug-info we need for expression evaluation. I’ll have to look into why that’s happening. You could work around it for now by running settings set target.import-std-module true before running the expression (which means we will get the decls we need from the std module instead of debug-info).

using namespace declarations aren’t honoured by LLDB’s expression evaluator at the moment. So you have to fully qualify the namespace.

Calling std::string("hi") won’t work because the expression evaluator currently doesn’t support leaving out default function parameters. Even if it did, the rest of the errors still point at missing debug-info.

This is the same “lack of debug-info” issue

Ok when pointing clang to a local libc++ build and making sure to use that constructor in the program, I see the expected corresponding DWARF entry:

DW_TAG_subprogram
  DW_AT_low_pc    (0x00000000000000c8)
  DW_AT_high_pc   (0x00000000000000fc)
  DW_AT_frame_base        (DW_OP_reg29 W29)
  DW_AT_object_pointer    (0x00003250)
  DW_AT_linkage_name      ("_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1B7v170000ILi0EEEPKc")
  DW_AT_specification     (0x000016ba "basic_string")
  DW_TAG_formal_parameter
    DW_AT_location        (DW_OP_fbreg -8)
    DW_AT_name    ("this")
    DW_AT_type    (0x0000559b "string *")
    DW_AT_artificial      (true)
  DW_TAG_formal_parameter
    DW_AT_location        (DW_OP_breg31 WSP+16)
    DW_AT_name    ("__s")
    DW_AT_decl_file       ("./bin/../include/c++/v1/string")
    DW_AT_decl_line       (900)
    DW_AT_type    (0x000030e2 "const char *")
  DW_TAG_template_value_parameter
    DW_AT_type    (0x000030a1 "int")
    DW_AT_const_value     (0)

But turns out LLDB doesn’t actually construct a CXXConstructorDecl from it. There is a comment in DWARFASTParserClang::ParseSubroutine that explains why:

// Check for templatized class member functions. If we had any         
// DW_TAG_template_type_parameter or DW_TAG_template_value_parameter   
// the DW_TAG_subprogram DIE, then we can't let this become a method in
// a class. Why? Because templatized functions are only emitted if one 
// of the templatized methods is used in the current compile unit and  
// we will end up with classes that may or may not include these member
// functions and this means one class won't match another class        
// definition and it affects our ability to use a class in the clang   
// expression parser. So for the greater good, we currently must not   
// allow any template member functions in a class definition.          
if (is_cxx_method && has_template_params) {                            
  ignore_containing_context = true;                                    
  is_cxx_method = false;                                                
}                                                                      

Even if we did create such decl, there’s the issue of ABI-tagged constructors not being callable from LLDB (see ⚙ D144181 [clang][DebugInfo] Add abi-tags on constructors/destructors as LLVM annotations for details, but it’s been on hold)