2

My class has operator const char*() const { return "foo"; }.

I have gdb 7.12.1-48.el7 stopped where a variable q is of this class.

I type p q. and when I hit the key I see a completion list of all its methods and members, including operator char const*.

However, I get this response to these commands.

(gdb) p q.operator char const*()
Couldn't find method MyClass::operatorconst char *

(gdb) p q.operator char const*
There is no member or method named operatorconst char *.

(gdb) p q.(operator char const*)
A syntax error in expression, near `(operator char const*)'.

(gdb) p q.(operator char const*)()
A syntax error in expression, near `(operator char const*)()'.

Any ideas on how I can call this method?

Swiss Frank
  • 1,985
  • 15
  • 33
  • 5
    Even gdb 9.1 struggles with this. I do not believe there is a way to do it. gdb, historically, had always only a bare minimum of understanding of C++. Can't really blame this poor beast. C++'s grammar is pretty much unparsable by anything except a full-blown C++ compiler. – Sam Varshavchik Sep 29 '20 at 12:28
  • 1
    Does this answer your question? [calling operator<< in gdb](https://stackoverflow.com/questions/3832964/calling-operator-in-gdb) The single quotes seem to be the key. – Botje Sep 29 '20 at 12:37

2 Answers2

3

You can just use implicit conversion. For me p (const char*)q works in gdb 8.2.1:

(gdb) p (const char*)q
$2 = 0x7ffffffedaf0 "qwer"
(gdb)
rustyx
  • 80,671
  • 25
  • 200
  • 267
3

Update to a simpler way thanks to Botje's comment above:

Given this code:

#include <cstdio>

class MyClass
{
    const char* const _name;
public:
    explicit MyClass( const char* const name ) : _name{name} {}
    operator const char*() const { return _name; }
    operator const char*()       { return _name + 1; } // Will omit the first char
};

int main()
{
    auto        c  = MyClass{"My name"};
    const auto& cc = c;
    std::puts(c);  // Prints 'y name'  since c is not const
    std::puts(cc); // Prints 'My name' since cc is const
}

Then in gdb, you can put a breakpoint on the puts() statement and do your print:

(gdb) p c.'operator char const*'()
$1 = 0x555555556005 "y name"
(gdb) p cc.'operator char const*'()
$2 = 0x555555556004 "My name"

This shows how to choose between the const and non-const versions of the function -- make the calling object const. (I think distinguishing between const-ness this may require a recent version of gdb. Version 9.1 shows the above. Version 7.11, as you can see on Coliru, always calls the const version.)


Old answer, kept for posterity:

You can call it (or other special or overloaded functions) using the mangled name. For instance:

#include <cstdio>

class MyClass
{
    const char* const _name;
public:
    explicit MyClass( const char* const name ) : _name{name} {}
    operator const char*() const { return _name; }
};

int main()
{
    auto c = MyClass{"My name"};
    std::puts(c);
}

Building that with gcc -ggdb -o test test.cpp, then running nm twice (once mangled and once demangled) will reveal the mangled name:

> nm test
...
00000000000011c6 W _ZN7MyClassC2EPKc
00000000000011e4 W _ZNK7MyClasscvPKcEv

> nm --demangle test
...
00000000000011c6 W MyClass::MyClass(char const*)
00000000000011e4 W MyClass::operator char const*() const

Special functions like constructors and operators are particularly obscure when mangled, but you can use other clues to find your target. Here, note the address of the function you want to call should match up in the mangled and demangled versions (also the order is probably the same).

Then in gdb, you can put a breakpoint on the puts() statement and do your print:

(gdb) p _ZNK7MyClasscvPKcEv(&c)
$2 = 0x555555556004 "My name"

Note that you need to pass in a this pointer as the first parameter, which in my case is the address of my object c.

metal
  • 6,202
  • 1
  • 34
  • 49