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;
|
||||
|
||||
bool
|
||||
IsReferenceType (ClangASTType *pointee_type = NULL) const;
|
||||
IsReferenceType (ClangASTType *pointee_type = nullptr, bool* is_rvalue = nullptr) const;
|
||||
|
||||
bool
|
||||
IsScalarType () const;
|
||||
|
|
|
@ -185,8 +185,8 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
|||
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
||||
}
|
||||
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();
|
||||
GetPossibleMatches(valobj,
|
||||
|
@ -197,8 +197,22 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
|||
did_strip_ptr,
|
||||
true,
|
||||
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();
|
||||
GetPossibleMatches(valobj,
|
||||
|
@ -209,6 +223,18 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
|
|||
true,
|
||||
did_strip_ref,
|
||||
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,
|
||||
false, // no C
|
||||
|
|
|
@ -680,7 +680,7 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
|
|||
return true;
|
||||
case clang::Type::RValueReference:
|
||||
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;
|
||||
case clang::Type::Typedef:
|
||||
return ClangASTType (m_ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
|
||||
|
@ -699,7 +699,7 @@ ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
|
|||
|
||||
|
||||
bool
|
||||
ClangASTType::IsReferenceType (ClangASTType *pointee_type) const
|
||||
ClangASTType::IsReferenceType (ClangASTType *pointee_type, bool* is_rvalue) const
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
|
@ -711,17 +711,21 @@ ClangASTType::IsReferenceType (ClangASTType *pointee_type) const
|
|||
case clang::Type::LValueReference:
|
||||
if (pointee_type)
|
||||
pointee_type->SetClangType(m_ast, cast<LValueReferenceType>(qual_type)->desugar());
|
||||
if (is_rvalue)
|
||||
*is_rvalue = false;
|
||||
return true;
|
||||
case clang::Type::RValueReference:
|
||||
if (pointee_type)
|
||||
pointee_type->SetClangType(m_ast, cast<RValueReferenceType>(qual_type)->desugar());
|
||||
if (is_rvalue)
|
||||
*is_rvalue = true;
|
||||
return true;
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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