Fix up LLDB for a change in the way clang represents anonymous unions such that the 'frame variable' command can still find the members of such union as if they were top-level variables in the current scope

llvm-svn: 253613
This commit is contained in:
Enrico Granata 2015-11-19 22:28:58 +00:00
parent 379cc5e71b
commit 46252398f0
6 changed files with 98 additions and 9 deletions

View File

@ -47,11 +47,12 @@ class StackFrame :
public:
enum ExpressionPathOption
{
eExpressionPathOptionCheckPtrVsMember = (1u << 0),
eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4)
eExpressionPathOptionCheckPtrVsMember = (1u << 0),
eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4),
eExpressionPathOptionsInspectAnonymousUnions = (1u << 5)
};
//------------------------------------------------------------------

View File

@ -0,0 +1,5 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,27 @@
"""
Tests that frame variable looks into anonymous unions
"""
import lldb
from lldbsuite.test.lldbtest import *
import lldbsuite.test.lldbutil as lldbutil
class FrameVariableAnonymousUnionsTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
def test_with_run_command(self):
"""Tests that frame variable looks into anonymous unions"""
self.build()
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
line = line_number('main.cpp', '// break here')
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=-1, loc_exact=False)
self.runCmd("process launch", RUN_SUCCEEDED)
self.expect('frame variable -f x i', substrs=['ffffff41'])
self.expect('frame variable c', substrs=["'A"])
self.expect('frame variable x', matching=False, substrs=['3'])
self.expect('frame variable y', matching=False, substrs=["'B'"])
self.expect('frame variable z', matching=False, substrs=['14'])

View File

@ -0,0 +1,23 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
int main() {
union {
int i;
char c;
};
struct {
int x;
char y;
short z;
} s{3,'B',14};
i = 0xFFFFFF00;
c = 'A';
return c; // break here
}

View File

@ -478,7 +478,8 @@ protected:
{
Error error;
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
lldb::VariableSP var_sp;
valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr,
m_varobj_options.use_dynamic,

View File

@ -24,6 +24,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
@ -667,7 +668,8 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
{
var_path.erase (0, name_const_string.GetLength ());
}
else if (options & eExpressionPathOptionsAllowDirectIVarAccess)
if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess))
{
// Check for direct ivars access which helps us with implicit
// access to ivars with the "this->" or "self->"
@ -689,13 +691,43 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
}
}
}
if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions))
{
// Check if any anonymous unions are there which contain a variable with the name we need
for (size_t i = 0;
i < variable_list->GetSize();
i++)
{
if (VariableSP variable_sp = variable_list->GetVariableAtIndex(i))
{
if (variable_sp->GetName().IsEmpty())
{
if (Type *var_type = variable_sp->GetType())
{
if (var_type->GetForwardCompilerType().IsAnonymousType())
{
valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
if (!valobj_sp)
return valobj_sp;
valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true);
if (valobj_sp)
break;
}
}
}
}
}
}
if (var_sp)
if (var_sp && !valobj_sp)
{
valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic);
if (!valobj_sp)
return valobj_sp;
}
if (valobj_sp)
{
// We are dumping at least one child
while (separator_idx != std::string::npos)
{