diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py --- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py +++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.py @@ -45,7 +45,6 @@ # Ignore the convenience variable name and newline value = value_str[value_str.find("= ") + 2:-1] gdb.newest_frame().select() - expectation_val = compare_frame.read_var("expectation") check_literal = expectation_val.string(encoding="utf-8") if "PrettyPrintToRegex" in compare_frame.name(): diff --git a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp --- a/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp +++ b/libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp @@ -608,25 +608,27 @@ // due to which there is one more count for the pointer. Hence, all the // following tests are testing with expected count plus 1. std::shared_ptr test0 = std::make_shared(5); + // The python regular expression matcher treats newlines as significant, so + // these regular expressions should be on one line. ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 2, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [2\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); std::shared_ptr test1(test0); ComparePrettyPrintToRegex( test1, - R"(std::shared_ptr count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); { std::weak_ptr test2 = test1; ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 3, weak 1 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [1\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); } ComparePrettyPrintToRegex( test0, - R"(std::shared_ptr count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})"); + R"(std::shared_ptr count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})"); std::shared_ptr test3; ComparePrettyPrintToChars(test3, "std::shared_ptr is nullptr"); diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py --- a/libcxx/utils/gdb/libcxx/printers.py +++ b/libcxx/utils/gdb/libcxx/printers.py @@ -312,12 +312,21 @@ return "%s is nullptr" % typename refcount = self.val["__cntrl_"] if refcount != 0: - usecount = refcount["__shared_owners_"] + 1 - weakcount = refcount["__shared_weak_owners_"] - if usecount == 0: - state = "expired, weak %d" % weakcount - else: - state = "count %d, weak %d" % (usecount, weakcount) + try: + usecount = refcount["__shared_owners_"] + 1 + weakcount = refcount["__shared_weak_owners_"] + if usecount == 0: + state = "expired, weak %d" % weakcount + else: + state = "count %d, weak %d" % (usecount, weakcount) + except: + # Debug info for a class with virtual functions is emitted + # in the same place as its key function. That means that + # for std::shared_ptr, __shared_owners_ is emitted into + # into libcxx.[so|a] itself, rather than into the shared_ptr + # instantiation point. So if libcxx.so was built without + # debug info, these fields will be missing. + state = "count ?, weak ? (libc++ missing debug info)" return "%s<%s> %s containing" % (typename, pointee_type, state) def __iter__(self):