summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2013-12-28 08:44:02 +0000
committerEnrico Granata <egranata@apple.com>2013-12-28 08:44:02 +0000
commit30f287fde5b1e4d871726dccd0aad5913917f4f0 (patch)
treee5897c00d57db3da41508fff19955a4cf2dab98e
parentffd810525de92bed4d8d197fd3f73fc1897ea0c6 (diff)
downloadbcm5719-llvm-30f287fde5b1e4d871726dccd0aad5913917f4f0.tar.gz
bcm5719-llvm-30f287fde5b1e4d871726dccd0aad5913917f4f0.zip
Add a new way to bind a format to a type: by enum type
The "type format add" command gets a new flag --type (-t). If you pass -t <sometype>, upon fetching the value for an object of your type, LLDB will display it as-if it was of enumeration type <sometype> This is useful in cases of non-contiguous enums where there are empty gaps of unspecified values, and as such one cannot type their variables as the enum type, but users would still like to see them as-if they were of the enum type (e.g. DWARF field types with their user-reserved ranges) The SB API has also been improved to handle both types of formats, and a test case is added llvm-svn: 198105
-rw-r--r--lldb/include/lldb/API/SBTypeFormat.h18
-rw-r--r--lldb/include/lldb/DataFormatters/TypeFormat.h130
-rw-r--r--lldb/scripts/Python/interface/SBTypeFormat.i8
-rw-r--r--lldb/source/API/SBTypeFormat.cpp56
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp32
-rw-r--r--lldb/source/Core/ValueObject.cpp4
-rw-r--r--lldb/source/DataFormatters/FormatManager.cpp2
-rw-r--r--lldb/source/DataFormatters/TypeFormat.cpp102
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-enum-format/Makefile5
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py80
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp13
11 files changed, 399 insertions, 51 deletions
diff --git a/lldb/include/lldb/API/SBTypeFormat.h b/lldb/include/lldb/API/SBTypeFormat.h
index cd6345fbe6f..eb45ff2b0eb 100644
--- a/lldb/include/lldb/API/SBTypeFormat.h
+++ b/lldb/include/lldb/API/SBTypeFormat.h
@@ -22,6 +22,9 @@ public:
SBTypeFormat (lldb::Format format,
uint32_t options = 0); // see lldb::eTypeOption values
+
+ SBTypeFormat (const char* type,
+ uint32_t options = 0); // see lldb::eTypeOption values
SBTypeFormat (const lldb::SBTypeFormat &rhs);
@@ -33,6 +36,9 @@ public:
lldb::Format
GetFormat ();
+ const char*
+ GetTypeName ();
+
uint32_t
GetOptions();
@@ -40,6 +46,9 @@ public:
SetFormat (lldb::Format);
void
+ SetTypeName (const char*);
+
+ void
SetOptions (uint32_t);
bool
@@ -73,8 +82,15 @@ protected:
SBTypeFormat (const lldb::TypeFormatImplSP &);
+ enum class Type
+ {
+ eTypeKeepSame,
+ eTypeFormat,
+ eTypeEnum
+ };
+
bool
- CopyOnWrite_Impl();
+ CopyOnWrite_Impl(Type);
};
diff --git a/lldb/include/lldb/DataFormatters/TypeFormat.h b/lldb/include/lldb/DataFormatters/TypeFormat.h
index a0198498d01..20fa8f2d4e7 100644
--- a/lldb/include/lldb/DataFormatters/TypeFormat.h
+++ b/lldb/include/lldb/DataFormatters/TypeFormat.h
@@ -130,15 +130,12 @@ namespace lldb_private {
uint32_t m_flags;
};
- TypeFormatImpl (lldb::Format f = lldb::eFormatInvalid,
- const Flags& flags = Flags());
+ TypeFormatImpl (const Flags& flags = Flags());
typedef std::shared_ptr<TypeFormatImpl> SharedPointer;
typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeFormatImplSP&);
- ~TypeFormatImpl ()
- {
- }
+ virtual ~TypeFormatImpl () = default;
bool
Cascades () const
@@ -173,6 +170,66 @@ namespace lldb_private {
{
m_flags.SetSkipReferences(value);
}
+
+ uint32_t
+ GetOptions ()
+ {
+ return m_flags.GetValue();
+ }
+
+ void
+ SetOptions (uint32_t value)
+ {
+ m_flags.SetValue(value);
+ }
+
+ uint32_t&
+ GetRevision ()
+ {
+ return m_my_revision;
+ }
+
+ enum class Type
+ {
+ eTypeUnknown,
+ eTypeFormat,
+ eTypeEnum
+ };
+
+ virtual Type
+ GetType ()
+ {
+ return Type::eTypeUnknown;
+ }
+
+ // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for
+ // extended periods of time and we trust the ValueObject to stay around for as long as it is required
+ // for us to generate its value
+ virtual bool
+ FormatObject (ValueObject *valobj,
+ std::string& dest) const = 0;
+
+ virtual std::string
+ GetDescription() = 0;
+
+ protected:
+ Flags m_flags;
+ uint32_t m_my_revision;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl);
+ };
+
+ class TypeFormatImpl_Format : public TypeFormatImpl
+ {
+ public:
+ TypeFormatImpl_Format (lldb::Format f = lldb::eFormatInvalid,
+ const TypeFormatImpl::Flags& flags = Flags());
+
+ typedef std::shared_ptr<TypeFormatImpl_Format> SharedPointer;
+ typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_Format::SharedPointer&);
+
+ virtual ~TypeFormatImpl_Format () = default;
lldb::Format
GetFormat () const
@@ -186,42 +243,69 @@ namespace lldb_private {
m_format = fmt;
}
- uint32_t
- GetOptions ()
+ virtual TypeFormatImpl::Type
+ GetType ()
{
- return m_flags.GetValue();
+ return TypeFormatImpl::Type::eTypeFormat;
+ }
+
+ virtual bool
+ FormatObject (ValueObject *valobj,
+ std::string& dest) const;
+
+ virtual std::string
+ GetDescription();
+
+ protected:
+ lldb::Format m_format;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl_Format);
+ };
+
+ class TypeFormatImpl_EnumType : public TypeFormatImpl
+ {
+ public:
+ TypeFormatImpl_EnumType (ConstString type_name = ConstString(""),
+ const TypeFormatImpl::Flags& flags = Flags());
+
+ typedef std::shared_ptr<TypeFormatImpl_EnumType> SharedPointer;
+ typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_EnumType::SharedPointer&);
+
+ ~TypeFormatImpl_EnumType () = default;
+
+ ConstString
+ GetTypeName ()
+ {
+ return m_enum_type;
}
void
- SetOptions (uint32_t value)
+ SetTypeName (ConstString enum_type)
{
- m_flags.SetValue(value);
+ m_enum_type = enum_type;
}
- uint32_t&
- GetRevision ()
+ virtual TypeFormatImpl::Type
+ GetType ()
{
- return m_my_revision;
+ return TypeFormatImpl::Type::eTypeEnum;
}
- // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for
- // extended periods of time and we trust the ValueObject to stay around for as long as it is required
- // for us to generate its value
- bool
+ virtual bool
FormatObject (ValueObject *valobj,
std::string& dest) const;
- std::string
+ virtual std::string
GetDescription();
protected:
- Flags m_flags;
- lldb::Format m_format;
- uint32_t m_my_revision;
+ ConstString m_enum_type;
+ mutable std::map<void*,ClangASTType> m_types;
private:
- DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl);
- };
+ DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl_EnumType);
+ };
} // namespace lldb_private
#endif // lldb_TypeFormat_h_
diff --git a/lldb/scripts/Python/interface/SBTypeFormat.i b/lldb/scripts/Python/interface/SBTypeFormat.i
index 9d2f1a675aa..4e4b69c3f1f 100644
--- a/lldb/scripts/Python/interface/SBTypeFormat.i
+++ b/lldb/scripts/Python/interface/SBTypeFormat.i
@@ -21,6 +21,8 @@ namespace lldb {
SBTypeFormat (lldb::Format format, uint32_t options = 0);
+ SBTypeFormat (const char* type, uint32_t options = 0);
+
SBTypeFormat (const lldb::SBTypeFormat &rhs);
~SBTypeFormat ();
@@ -34,6 +36,9 @@ namespace lldb {
lldb::Format
GetFormat ();
+ const char*
+ GetTypeName ();
+
uint32_t
GetOptions();
@@ -41,6 +46,9 @@ namespace lldb {
SetFormat (lldb::Format);
void
+ SetTypeName (const char*);
+
+ void
SetOptions (uint32_t);
bool
diff --git a/lldb/source/API/SBTypeFormat.cpp b/lldb/source/API/SBTypeFormat.cpp
index 34ab404a206..d3ec9bc00bd 100644
--- a/lldb/source/API/SBTypeFormat.cpp
+++ b/lldb/source/API/SBTypeFormat.cpp
@@ -25,7 +25,13 @@ m_opaque_sp()
SBTypeFormat::SBTypeFormat (lldb::Format format,
uint32_t options)
-: m_opaque_sp(TypeFormatImplSP(new TypeFormatImpl(format,options)))
+: m_opaque_sp(TypeFormatImplSP(new TypeFormatImpl_Format(format,options)))
+{
+}
+
+SBTypeFormat::SBTypeFormat (const char* type,
+ uint32_t options)
+: m_opaque_sp(TypeFormatImplSP(new TypeFormatImpl_EnumType(ConstString(type ? type : ""),options)))
{
}
@@ -47,11 +53,19 @@ SBTypeFormat::IsValid() const
lldb::Format
SBTypeFormat::GetFormat ()
{
- if (IsValid())
- return m_opaque_sp->GetFormat();
+ if (IsValid() && m_opaque_sp->GetType() == TypeFormatImpl::Type::eTypeFormat)
+ return ((TypeFormatImpl_Format*)m_opaque_sp.get())->GetFormat();
return lldb::eFormatInvalid;
}
+const char*
+SBTypeFormat::GetTypeName ()
+{
+ if (IsValid() && m_opaque_sp->GetType() == TypeFormatImpl::Type::eTypeEnum)
+ return ((TypeFormatImpl_EnumType*)m_opaque_sp.get())->GetTypeName().AsCString("");
+ return "";
+}
+
uint32_t
SBTypeFormat::GetOptions()
{
@@ -63,14 +77,21 @@ SBTypeFormat::GetOptions()
void
SBTypeFormat::SetFormat (lldb::Format fmt)
{
- if (CopyOnWrite_Impl())
- m_opaque_sp->SetFormat(fmt);
+ if (CopyOnWrite_Impl(Type::eTypeFormat))
+ ((TypeFormatImpl_Format*)m_opaque_sp.get())->SetFormat(fmt);
+}
+
+void
+SBTypeFormat::SetTypeName (const char* type)
+{
+ if (CopyOnWrite_Impl(Type::eTypeEnum))
+ ((TypeFormatImpl_EnumType*)m_opaque_sp.get())->SetTypeName(ConstString(type ? type : ""));
}
void
SBTypeFormat::SetOptions (uint32_t value)
{
- if (CopyOnWrite_Impl())
+ if (CopyOnWrite_Impl(Type::eTypeKeepSame))
m_opaque_sp->SetOptions(value);
}
@@ -143,13 +164,30 @@ SBTypeFormat::SBTypeFormat (const lldb::TypeFormatImplSP &typeformat_impl_sp) :
}
bool
-SBTypeFormat::CopyOnWrite_Impl()
+SBTypeFormat::CopyOnWrite_Impl(Type type)
{
if (!IsValid())
return false;
- if (m_opaque_sp.unique())
+
+ if (m_opaque_sp.unique() &&
+ ((type == Type::eTypeKeepSame) ||
+ (type == Type::eTypeFormat && m_opaque_sp->GetType() == TypeFormatImpl::Type::eTypeFormat) ||
+ (type == Type::eTypeEnum && m_opaque_sp->GetType() == TypeFormatImpl::Type::eTypeEnum))
+ )
return true;
- SetSP(TypeFormatImplSP(new TypeFormatImpl(GetFormat(),GetOptions())));
+ if (type == Type::eTypeKeepSame)
+ {
+ if (m_opaque_sp->GetType() == TypeFormatImpl::Type::eTypeFormat)
+ type = Type::eTypeFormat;
+ else
+ type = Type::eTypeEnum;
+ }
+
+ if (type == Type::eTypeFormat)
+ SetSP(TypeFormatImplSP(new TypeFormatImpl_Format(GetFormat(),GetOptions())));
+ else
+ SetSP(TypeFormatImplSP(new TypeFormatImpl_EnumType(ConstString(GetTypeName()),GetOptions())));
+
return true;
}
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index d4bc9672f6a..8c7d239bc37 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -371,6 +371,7 @@ private:
m_skip_references = false;
m_regex = false;
m_category.assign("default");
+ m_custom_type_name.clear();
}
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
@@ -400,6 +401,9 @@ private:
case 'x':
m_regex = true;
break;
+ case 't':
+ m_custom_type_name.assign(option_value);
+ break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
@@ -419,6 +423,7 @@ private:
bool m_skip_pointers;
bool m_regex;
std::string m_category;
+ std::string m_custom_type_name;
};
OptionGroupOptions m_option_group;
@@ -480,7 +485,7 @@ public:
);
// Add the "--format" to all options groups
- m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_ALL);
+ m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
m_option_group.Append (&m_command_options);
m_option_group.Finalize();
@@ -504,7 +509,7 @@ protected:
}
const Format format = m_format_options.GetFormat();
- if (format == eFormatInvalid)
+ if (format == eFormatInvalid && m_command_options.m_custom_type_name.empty())
{
result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
@@ -513,10 +518,16 @@ protected:
TypeFormatImplSP entry;
- entry.reset(new TypeFormatImpl(format,
- TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade).
- SetSkipPointers(m_command_options.m_skip_pointers).
- SetSkipReferences(m_command_options.m_skip_references)));
+ if (m_command_options.m_custom_type_name.empty())
+ entry.reset(new TypeFormatImpl_Format(format,
+ TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade).
+ SetSkipPointers(m_command_options.m_skip_pointers).
+ SetSkipReferences(m_command_options.m_skip_references)));
+ else
+ entry.reset(new TypeFormatImpl_EnumType(ConstString(m_command_options.m_custom_type_name.c_str()),
+ TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade).
+ SetSkipPointers(m_command_options.m_skip_pointers).
+ SetSkipReferences(m_command_options.m_skip_references)));
// now I have a valid format, let's add it to every type
@@ -562,11 +573,12 @@ protected:
OptionDefinition
CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
{ LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
+ { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Format variables as if they were of this type."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index fc29f6dcc99..56ac7e134ab 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -1402,7 +1402,7 @@ bool
ValueObject::GetValueAsCString (lldb::Format format,
std::string& destination)
{
- return GetValueAsCString(TypeFormatImpl(format),destination);
+ return GetValueAsCString(TypeFormatImpl_Format(format),destination);
}
const char *
@@ -1439,7 +1439,7 @@ ValueObject::GetValueAsCString ()
{
m_last_format = my_format;
if (!format_sp)
- format_sp.reset(new TypeFormatImpl(my_format));
+ format_sp.reset(new TypeFormatImpl_Format(my_format));
if (GetValueAsCString(*format_sp.get(), m_value_str))
{
if (!m_value_did_change && m_old_value_valid)
diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp
index ca4603c94bb..41e2acb1c99 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -741,7 +741,7 @@ AddFormat (TypeCategoryImpl::SharedPointer category_sp,
TypeFormatImpl::Flags flags,
bool regex = false)
{
- lldb::TypeFormatImplSP format_sp(new TypeFormatImpl(format, flags));
+ lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags));
if (regex)
category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp);
diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index 6a1a103b5af..a72f551c741 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -25,22 +25,30 @@
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
-TypeFormatImpl::TypeFormatImpl (lldb::Format f,
- const Flags& flags) :
+TypeFormatImpl::TypeFormatImpl (const Flags& flags) :
m_flags(flags),
+m_my_revision(0)
+{
+}
+
+
+TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
+ const TypeFormatImpl::Flags& flags) :
+TypeFormatImpl(flags),
m_format (f)
{
}
bool
-TypeFormatImpl::FormatObject (ValueObject *valobj,
- std::string& dest) const
+TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
+ std::string& dest) const
{
if (!valobj)
return false;
@@ -127,7 +135,7 @@ TypeFormatImpl::FormatObject (ValueObject *valobj,
}
std::string
-TypeFormatImpl::GetDescription()
+TypeFormatImpl_Format::GetDescription()
{
StreamString sstr;
sstr.Printf ("%s%s%s%s",
@@ -138,3 +146,87 @@ TypeFormatImpl::GetDescription()
return sstr.GetString();
}
+TypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name,
+ const TypeFormatImpl::Flags& flags) :
+TypeFormatImpl(flags),
+m_enum_type(type_name),
+m_types()
+{
+}
+
+bool
+TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
+ std::string& dest) const
+{
+ dest.clear();
+ if (!valobj)
+ return false;
+ if (valobj->GetClangType().IsAggregateType ())
+ return false;
+ ProcessSP process_sp;
+ TargetSP target_sp;
+ void* valobj_key = (process_sp = valobj->GetProcessSP()).get();
+ if (!valobj_key)
+ valobj_key = (target_sp = valobj->GetTargetSP()).get();
+ else
+ target_sp = process_sp->GetTarget().shared_from_this();
+ if (!valobj_key)
+ return false;
+ auto iter = m_types.find(valobj_key),
+ end = m_types.end();
+ ClangASTType valobj_enum_type;
+ if (iter == end)
+ {
+ // probably a redundant check
+ if (!target_sp)
+ return false;
+ const ModuleList& images(target_sp->GetImages());
+ SymbolContext sc;
+ TypeList types;
+ images.FindTypes(sc, m_enum_type, false, UINT32_MAX, types);
+ if (types.GetSize() == 0)
+ return false;
+ for (lldb::TypeSP type_sp : types.Types())
+ {
+ if (!type_sp)
+ continue;
+ if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration)
+ {
+ valobj_enum_type = type_sp->GetClangFullType();
+ m_types.emplace(valobj_key,valobj_enum_type);
+ break;
+ }
+ }
+ }
+ else
+ valobj_enum_type = iter->second;
+ if (valobj_enum_type.IsValid() == false)
+ return false;
+ DataExtractor data;
+ valobj->GetData(data);
+ ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
+ StreamString sstr;
+ valobj_enum_type.DumpTypeValue(&sstr,
+ lldb::eFormatEnum,
+ data,
+ 0,
+ data.GetByteSize(),
+ 0,
+ 0,
+ exe_ctx.GetBestExecutionContextScope());
+ if (!sstr.GetString().empty())
+ dest.swap(sstr.GetString());
+ return !dest.empty();
+}
+
+std::string
+TypeFormatImpl_EnumType::GetDescription()
+{
+ StreamString sstr;
+ sstr.Printf ("as type %s%s%s%s",
+ m_enum_type.AsCString("<invalid type>"),
+ Cascades() ? "" : " (not cascading)",
+ SkipsPointers() ? " (skip pointers)" : "",
+ SkipsReferences() ? " (skip references)" : "");
+ return sstr.GetString();
+}
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-enum-format/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/Makefile
new file mode 100644
index 00000000000..314f1cb2f07
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py
new file mode 100644
index 00000000000..69e477dfc16
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/TestDataFormatterEnumFormat.py
@@ -0,0 +1,80 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class EnumFormatTestCase(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 break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+ 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'])
+
+ self.expect("frame variable",
+ substrs = ['(Foo) f = Case45',
+ '(int) x = 1',
+ '(int) y = 45',
+ '(int) z = 43'
+ ]);
+
+ # 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 format add --type Foo int")
+
+ # The type format list should show our custom formats.
+ self.expect("type format list -w default",
+ substrs = ['int: as type Foo'])
+
+ self.expect("frame variable",
+ substrs = ['(Foo) f = Case45',
+ '(int) x = Case1',
+ '(int) y = Case45',
+ '(int) z = 43'
+ ]);
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp
new file mode 100644
index 00000000000..6a8074ff9fb
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-enum-format/main.cpp
@@ -0,0 +1,13 @@
+enum Foo {
+ Case1 = 1,
+ Case2 = 2,
+ Case45 = 45
+};
+
+int main() {
+ Foo f = Case45;
+ int x = 1;
+ int y = 45;
+ int z = 43;
+ return 1; // Set break point at this line.
+}
OpenPOWER on IntegriCloud