forked from OSchip/llvm-project
<rdar://problem/12055586>
Enable data formatters to see-through pointers/references to typedefs For instance, if Foo is a typedef to Bar, and there is a formatter for any/all of Bar*, Bar&, Bar&&, then Foo*, Foo&, and Foo&& should pick these up if Foo-specific formatters don't exist llvm-svn: 205939
This commit is contained in:
parent
e4fef71981
commit
1ac6296376
|
@ -213,7 +213,7 @@ public:
|
||||||
IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const;
|
IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsReferenceType (ClangASTType *pointee_type = NULL) const;
|
IsReferenceType (ClangASTType *pointee_type = nullptr, bool* is_rvalue = nullptr) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsScalarType () const;
|
IsScalarType () const;
|
||||||
|
|
|
@ -185,8 +185,8 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
||||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
||||||
}
|
}
|
||||||
entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
|
entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
|
||||||
|
|
||||||
if (clang_type.IsReferenceType())
|
for (bool is_rvalue_ref = true, j = true; j && clang_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
|
||||||
{
|
{
|
||||||
ClangASTType non_ref_type = clang_type.GetNonReferenceType();
|
ClangASTType non_ref_type = clang_type.GetNonReferenceType();
|
||||||
GetPossibleMatches(valobj,
|
GetPossibleMatches(valobj,
|
||||||
|
@ -197,8 +197,22 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
||||||
did_strip_ptr,
|
did_strip_ptr,
|
||||||
true,
|
true,
|
||||||
did_strip_typedef);
|
did_strip_typedef);
|
||||||
|
if (non_ref_type.IsTypedefType())
|
||||||
|
{
|
||||||
|
ClangASTType deffed_referenced_type = non_ref_type.GetTypedefedType();
|
||||||
|
deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType();
|
||||||
|
GetPossibleMatches(valobj,
|
||||||
|
deffed_referenced_type,
|
||||||
|
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
||||||
|
use_dynamic,
|
||||||
|
entries,
|
||||||
|
did_strip_ptr,
|
||||||
|
did_strip_ref,
|
||||||
|
true); // this is not exactly the usual meaning of stripping typedefs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (clang_type.IsPointerType())
|
|
||||||
|
if (clang_type.IsPointerType())
|
||||||
{
|
{
|
||||||
ClangASTType non_ptr_type = clang_type.GetPointeeType();
|
ClangASTType non_ptr_type = clang_type.GetPointeeType();
|
||||||
GetPossibleMatches(valobj,
|
GetPossibleMatches(valobj,
|
||||||
|
@ -209,6 +223,18 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
||||||
true,
|
true,
|
||||||
did_strip_ref,
|
did_strip_ref,
|
||||||
did_strip_typedef);
|
did_strip_typedef);
|
||||||
|
if (non_ptr_type.IsTypedefType())
|
||||||
|
{
|
||||||
|
ClangASTType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
|
||||||
|
GetPossibleMatches(valobj,
|
||||||
|
deffed_pointed_type,
|
||||||
|
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
||||||
|
use_dynamic,
|
||||||
|
entries,
|
||||||
|
did_strip_ptr,
|
||||||
|
did_strip_ref,
|
||||||
|
true); // this is not exactly the usual meaning of stripping typedefs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
|
bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
|
||||||
false, // no C
|
false, // no C
|
||||||
|
|
|
@ -680,7 +680,7 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
|
||||||
return true;
|
return true;
|
||||||
case clang::Type::RValueReference:
|
case clang::Type::RValueReference:
|
||||||
if (pointee_type)
|
if (pointee_type)
|
||||||
pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
|
pointee_type->SetClangType(m_ast, cast<RValueReferenceType>(qual_type)->desugar());
|
||||||
return true;
|
return true;
|
||||||
case clang::Type::Typedef:
|
case clang::Type::Typedef:
|
||||||
return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
|
return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
|
||||||
|
@ -699,7 +699,7 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClangASTType::IsReferenceType (ClangASTType *pointee_type) const
|
ClangASTType::IsReferenceType (ClangASTType *pointee_type, bool* is_rvalue) const
|
||||||
{
|
{
|
||||||
if (IsValid())
|
if (IsValid())
|
||||||
{
|
{
|
||||||
|
@ -711,17 +711,21 @@ ClangASTType::IsReferenceType (ClangASTType *pointee_type) const
|
||||||
case clang::Type::LValueReference:
|
case clang::Type::LValueReference:
|
||||||
if (pointee_type)
|
if (pointee_type)
|
||||||
pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
|
pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
|
||||||
|
if (is_rvalue)
|
||||||
|
*is_rvalue = false;
|
||||||
return true;
|
return true;
|
||||||
case clang::Type::RValueReference:
|
case clang::Type::RValueReference:
|
||||||
if (pointee_type)
|
if (pointee_type)
|
||||||
pointee_type->SetClangType(m_ast, cast<RValueReferenceType>(qual_type)->desugar());
|
pointee_type->SetClangType(m_ast, cast<RValueReferenceType>(qual_type)->desugar());
|
||||||
|
if (is_rvalue)
|
||||||
|
*is_rvalue = true;
|
||||||
return true;
|
return true;
|
||||||
case clang::Type::Typedef:
|
case clang::Type::Typedef:
|
||||||
return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type);
|
return ClangASTType(m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type, is_rvalue);
|
||||||
case clang::Type::Elaborated:
|
case clang::Type::Elaborated:
|
||||||
return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsReferenceType(pointee_type);
|
return ClangASTType(m_ast, cast<ElaboratedType>(qual_type)->getNamedType()).IsReferenceType(pointee_type, is_rvalue);
|
||||||
case clang::Type::Paren:
|
case clang::Type::Paren:
|
||||||
return ClangASTType(m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsReferenceType(pointee_type);
|
return ClangASTType(m_ast, cast<clang::ParenType>(qual_type)->desugar()).IsReferenceType(pointee_type, is_rvalue);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
LEVEL = ../../../make
|
||||||
|
|
||||||
|
CXX_SOURCES := main.cpp
|
||||||
|
|
||||||
|
CFLAGS_EXTRAS += -std=c++11
|
||||||
|
|
||||||
|
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,68 @@
|
||||||
|
"""
|
||||||
|
Test lldb data formatter subsystem.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os, time
|
||||||
|
import unittest2
|
||||||
|
import lldb
|
||||||
|
from lldbtest import *
|
||||||
|
import lldbutil
|
||||||
|
|
||||||
|
class PtrRef2TypedefTestCase(TestBase):
|
||||||
|
|
||||||
|
mydir = TestBase.compute_mydir(__file__)
|
||||||
|
|
||||||
|
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||||
|
@dsym_test
|
||||||
|
def test_with_dsym_and_run_command(self):
|
||||||
|
"""Test data formatter commands."""
|
||||||
|
self.buildDsym()
|
||||||
|
self.data_formatter_commands()
|
||||||
|
|
||||||
|
@dwarf_test
|
||||||
|
def test_with_dwarf_and_run_command(self):
|
||||||
|
"""Test data formatter commands."""
|
||||||
|
self.buildDwarf()
|
||||||
|
self.data_formatter_commands()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Call super's setUp().
|
||||||
|
TestBase.setUp(self)
|
||||||
|
# Find the line number to break at.
|
||||||
|
self.line = line_number('main.cpp', '// Set breakpoint here')
|
||||||
|
|
||||||
|
def data_formatter_commands(self):
|
||||||
|
"""Test that a pointer/reference to a typedef is formatted as we want."""
|
||||||
|
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||||
|
|
||||||
|
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
|
||||||
|
|
||||||
|
self.runCmd("run", RUN_SUCCEEDED)
|
||||||
|
|
||||||
|
# The stop reason of the thread should be breakpoint.
|
||||||
|
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||||
|
substrs = ['stopped',
|
||||||
|
'stop reason = breakpoint'])
|
||||||
|
|
||||||
|
# This is the function to remove the custom formats in order to have a
|
||||||
|
# clean slate for the next test case.
|
||||||
|
def cleanup():
|
||||||
|
self.runCmd('type format clear', check=False)
|
||||||
|
self.runCmd('type summary clear', check=False)
|
||||||
|
|
||||||
|
# Execute the cleanup function during test case tear down.
|
||||||
|
self.addTearDownHook(cleanup)
|
||||||
|
|
||||||
|
self.runCmd('type summary add --cascade true -s "IntPointer" "int *"')
|
||||||
|
self.runCmd('type summary add --cascade true -s "IntLRef" "int &"')
|
||||||
|
self.runCmd('type summary add --cascade true -s "IntRRef" "int &&"')
|
||||||
|
|
||||||
|
self.expect("frame variable x", substrs = ['(Foo *) x = 0x','IntPointer'])
|
||||||
|
self.expect("frame variable y", substrs = ['(Foo &) y = 0x','IntLRef'])
|
||||||
|
self.expect("frame variable z", substrs = ['(Foo &&) z = 0x','IntRRef'])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import atexit
|
||||||
|
lldb.SBDebugger.Initialize()
|
||||||
|
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||||
|
unittest2.main()
|
|
@ -0,0 +1,19 @@
|
||||||
|
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
typedef int Foo;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int lval = 1;
|
||||||
|
Foo* x = &lval;
|
||||||
|
Foo& y = lval;
|
||||||
|
Foo&& z = 1;
|
||||||
|
return 0; // Set breakpoint here
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue