diff options
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. +} |