Fix dereferencing of pointers to empty classes
llvm-svn: 291350
This commit is contained in:
parent
7850602f0a
commit
1c62e0356d
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,60 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
class ValueAPIEmptyClassTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@add_test_categories(['pyapi'])
|
||||
def test(self):
|
||||
self.build()
|
||||
exe = os.path.join(os.getcwd(), 'a.out')
|
||||
line = line_number('main.cpp', '// Break at this line')
|
||||
|
||||
# Create a target by the debugger.
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
# Create the breakpoint inside function 'main'.
|
||||
breakpoint = target.BreakpointCreateByLocation('main.cpp', line)
|
||||
self.assertTrue(breakpoint, VALID_BREAKPOINT)
|
||||
|
||||
# Now launch the process, and do not stop at entry point.
|
||||
process = target.LaunchSimple(
|
||||
None, None, self.get_process_working_directory())
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
|
||||
# Get Frame #0.
|
||||
self.assertTrue(process.GetState() == lldb.eStateStopped)
|
||||
thread = lldbutil.get_stopped_thread(
|
||||
process, lldb.eStopReasonBreakpoint)
|
||||
self.assertTrue(
|
||||
thread.IsValid(),
|
||||
"There should be a thread stopped due to breakpoint condition")
|
||||
frame0 = thread.GetFrameAtIndex(0)
|
||||
|
||||
# Verify that we can access to a frame variable with an empty class type
|
||||
e = frame0.FindVariable('e')
|
||||
self.assertTrue(e.IsValid(), VALID_VARIABLE)
|
||||
self.DebugSBValue(e)
|
||||
self.assertEqual(e.GetNumChildren(), 0)
|
||||
|
||||
# Verify that we can acces to a frame variable what is a pointer to an
|
||||
# empty class
|
||||
ep = frame0.FindVariable('ep')
|
||||
self.assertTrue(ep.IsValid(), VALID_VARIABLE)
|
||||
self.DebugSBValue(ep)
|
||||
|
||||
# Verify that we can dereference a pointer to an empty class
|
||||
epd = ep.Dereference()
|
||||
self.assertTrue(epd.IsValid(), VALID_VARIABLE)
|
||||
self.DebugSBValue(epd)
|
||||
self.assertEqual(epd.GetNumChildren(), 0)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Empty {};
|
||||
|
||||
int main (int argc, char const *argv[]) {
|
||||
Empty e;
|
||||
Empty* ep = new Empty;
|
||||
return 0; // Break at this line
|
||||
}
|
|
@ -6752,43 +6752,42 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
|
|||
}
|
||||
break;
|
||||
|
||||
case clang::Type::Pointer:
|
||||
if (idx_is_valid) {
|
||||
CompilerType pointee_clang_type(GetPointeeType(type));
|
||||
case clang::Type::Pointer: {
|
||||
CompilerType pointee_clang_type(GetPointeeType(type));
|
||||
|
||||
// Don't dereference "void *" pointers
|
||||
if (pointee_clang_type.IsVoidType())
|
||||
return CompilerType();
|
||||
// Don't dereference "void *" pointers
|
||||
if (pointee_clang_type.IsVoidType())
|
||||
return CompilerType();
|
||||
|
||||
if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
|
||||
child_is_deref_of_parent = false;
|
||||
bool tmp_child_is_deref_of_parent = false;
|
||||
return pointee_clang_type.GetChildCompilerTypeAtIndex(
|
||||
exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
|
||||
ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
|
||||
child_bitfield_bit_size, child_bitfield_bit_offset,
|
||||
child_is_base_class, tmp_child_is_deref_of_parent, valobj,
|
||||
language_flags);
|
||||
} else {
|
||||
child_is_deref_of_parent = true;
|
||||
if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
|
||||
child_is_deref_of_parent = false;
|
||||
bool tmp_child_is_deref_of_parent = false;
|
||||
return pointee_clang_type.GetChildCompilerTypeAtIndex(
|
||||
exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
|
||||
ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
|
||||
child_bitfield_bit_size, child_bitfield_bit_offset,
|
||||
child_is_base_class, tmp_child_is_deref_of_parent, valobj,
|
||||
language_flags);
|
||||
} else {
|
||||
child_is_deref_of_parent = true;
|
||||
|
||||
const char *parent_name =
|
||||
valobj ? valobj->GetName().GetCString() : NULL;
|
||||
if (parent_name) {
|
||||
child_name.assign(1, '*');
|
||||
child_name += parent_name;
|
||||
}
|
||||
const char *parent_name =
|
||||
valobj ? valobj->GetName().GetCString() : NULL;
|
||||
if (parent_name) {
|
||||
child_name.assign(1, '*');
|
||||
child_name += parent_name;
|
||||
}
|
||||
|
||||
// We have a pointer to an simple type
|
||||
if (idx == 0) {
|
||||
child_byte_size = pointee_clang_type.GetByteSize(
|
||||
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
|
||||
child_byte_offset = 0;
|
||||
return pointee_clang_type;
|
||||
}
|
||||
// We have a pointer to an simple type
|
||||
if (idx == 0) {
|
||||
child_byte_size = pointee_clang_type.GetByteSize(
|
||||
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
|
||||
child_byte_offset = 0;
|
||||
return pointee_clang_type;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case clang::Type::LValueReference:
|
||||
case clang::Type::RValueReference:
|
||||
|
|
Loading…
Reference in New Issue