diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 | 
| commit | 9e6d35490a6542f9c97607f93c2ef8ca8e03cbcc (patch) | |
| tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/lang/cpp | |
| parent | 3bd2e91faeb9eeec1aae82c64a3253afff551cfd (diff) | |
Notes
Diffstat (limited to 'packages/Python/lldbsuite/test/lang/cpp')
117 files changed, 4832 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/lang/cpp/auto/Makefile b/packages/Python/lldbsuite/test/lang/cpp/auto/Makefile new file mode 100644 index 000000000000..194af7b32398 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/auto/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS += $(NO_LIMIT_DEBUG_INFO_FLAGS) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py b/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py new file mode 100644 index 000000000000..9746dec2fa3d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py @@ -0,0 +1,25 @@ +""" +Tests that auto types work +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPAutoTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureGcc("GCC does not generate complete debug info") +    def test_with_run_command(self): +        """Test that auto types work in the expression parser""" +        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('expr auto f = 123456; f', substrs=['int', '123456']) +        self.expect('expr struct Test { int x; int y; Test() : x(123), y(456) {} }; auto t = Test(); t', substrs=['Test', '123', '456']) +        self.expect('expr auto s = helloworld; s', substrs=['string', 'hello world']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/auto/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/auto/main.cpp new file mode 100644 index 000000000000..76fb95e0a34c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/auto/main.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +#include <string> + +int main() +{ +  std::string helloworld("hello world"); +  return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/bool/Makefile b/packages/Python/lldbsuite/test/lang/cpp/bool/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/bool/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/bool/TestCPPBool.py b/packages/Python/lldbsuite/test/lang/cpp/bool/TestCPPBool.py new file mode 100644 index 000000000000..ef7135cfaa07 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/bool/TestCPPBool.py @@ -0,0 +1,26 @@ +""" +Tests that bool types work +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPBoolTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    def test_with_run_command(self): +        """Test that bool types work in the expression parser""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        line = line_number('main.cpp', '// breakpoint 1') +        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("expression -- bool second_bool = my_bool; second_bool", +                    startstr = "(bool) $0 = false") + +        self.expect("expression -- my_bool = true", +                    startstr = "(bool) $1 = true") diff --git a/packages/Python/lldbsuite/test/lang/cpp/bool/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/bool/main.cpp new file mode 100644 index 000000000000..88d02d5b2894 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/bool/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +int main() +{ +  bool my_bool = false; + +  printf("%s\n", my_bool ? "true" : "false"); // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/Makefile b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/Makefile new file mode 100644 index 000000000000..1d1f38f7fd0e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := nested.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py new file mode 100644 index 000000000000..6c06f3750d13 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py @@ -0,0 +1,84 @@ +""" +Test lldb breakpoint command for CPP methods & functions in a namespace. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * + +class CPPBreakpointCommandsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureWindows +    def test(self): +        """Test a sequence of breakpoint command add, list, and delete.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        a_out_module = lldb.SBFileSpecList() +        a_out_module.Append(lldb.SBFileSpec(exe)) + +        nested_comp_unit = lldb.SBFileSpecList() +        nested_comp_unit.Append (lldb.SBFileSpec("nested.cpp")) + +        # First provide ONLY the method name.  This should get everybody... +        auto_break = target.BreakpointCreateByName ("Function", +                                                    lldb.eFunctionNameTypeAuto, +                                                    a_out_module, +                                                    nested_comp_unit) +        self.assertTrue (auto_break.GetNumLocations() == 5) + +        # Now add the Baz class specifier.  This should get the version contained in Bar, +        # AND the one contained in :: +        auto_break = target.BreakpointCreateByName ("Baz::Function", +                                                    lldb.eFunctionNameTypeAuto, +                                                    a_out_module, +                                                    nested_comp_unit) +        self.assertTrue (auto_break.GetNumLocations() == 2) + +        # Then add the Bar::Baz specifier.  This should get the version contained in Bar only +        auto_break = target.BreakpointCreateByName ("Bar::Baz::Function", +                                                    lldb.eFunctionNameTypeAuto, +                                                    a_out_module, +                                                    nested_comp_unit) +        self.assertTrue (auto_break.GetNumLocations() == 1) + +        plain_method_break = target.BreakpointCreateByName ("Function",  +                                                            lldb.eFunctionNameTypeMethod, +                                                            a_out_module, +                                                            nested_comp_unit) +        self.assertTrue (plain_method_break.GetNumLocations() == 3) + +        plain_method_break = target.BreakpointCreateByName ("Baz::Function",  +                                                            lldb.eFunctionNameTypeMethod, +                                                            a_out_module, +                                                            nested_comp_unit) +        self.assertTrue (plain_method_break.GetNumLocations() == 2) + +        plain_method_break = target.BreakpointCreateByName ("Bar::Baz::Function",  +                                                            lldb.eFunctionNameTypeMethod, +                                                            a_out_module, +                                                            nested_comp_unit) +        self.assertTrue (plain_method_break.GetNumLocations() == 1) + +        plain_method_break = target.BreakpointCreateByName ("Function",  +                                                            lldb.eFunctionNameTypeBase, +                                                            a_out_module, +                                                            nested_comp_unit) +        self.assertTrue (plain_method_break.GetNumLocations() == 2) + +        plain_method_break = target.BreakpointCreateByName ("Bar::Function",  +                                                            lldb.eFunctionNameTypeBase, +                                                            a_out_module, +                                                            nested_comp_unit) +        self.assertTrue (plain_method_break.GetNumLocations() == 1) diff --git a/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/nested.cpp b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/nested.cpp new file mode 100644 index 000000000000..29d4b4cb19e7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/nested.cpp @@ -0,0 +1,76 @@ +#include <stdio.h> + +namespace Foo +{ +  namespace Bar +  { +    class Baz +    { +    public: +      Baz (int value):m_value(value) {} +      int Function ()  +      { +        printf ("%s returning: %d.\n", __FUNCTION__, m_value); +        return m_value; +      } +    private: +      int m_value; +    }; + +    class Baz2 +    { +    public: +      Baz2 (int value):m_value(value) {} +      int Function ()  +      { +        printf ("%s returning: %d.\n", __FUNCTION__, m_value); +        return m_value; +      } +    private: +      int m_value; +    }; + +    static int bar_value = 20; +    int Function () +    { +      printf ("%s returning: %d.\n", __FUNCTION__, bar_value); +      return bar_value; +    } +  } +} + +class Baz +{ +public: +    Baz (int value):m_value(value) {} +    int Function ()  +    { +        printf ("%s returning: %d.\n", __FUNCTION__, m_value); +        return m_value; +    } +private: +    int m_value; +}; + +int +Function () +{ +    printf ("I am a global function, I return 333.\n"); +    return 333; +} + +int main () +{ +  Foo::Bar::Baz mine(200); +  Foo::Bar::Baz2 mine2(300); +  ::Baz bare_baz (500); + +  printf ("Yup, got %d from Baz.\n", mine.Function()); +  printf ("Yup, got %d from Baz.\n", mine2.Function()); +  printf ("Yup, got %d from Baz.\n", bare_baz.Function());   +  printf ("And  got %d from Bar.\n", Foo::Bar::Function()); +  printf ("And  got %d from ::.\n", ::Function()); + +  return 0; + +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/Makefile b/packages/Python/lldbsuite/test/lang/cpp/call-function/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py new file mode 100644 index 000000000000..3aa97af68819 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py @@ -0,0 +1,33 @@ +""" +Tests calling a function by basename +""" + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CallCPPFunctionTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    def setUp(self): +        TestBase.setUp(self) +        self.line = line_number('main.cpp', '// breakpoint') +     +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_with_run_command(self): +        """Test calling a function by basename""" +        self.build() +        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("process launch", 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("expression -- a_function_to_call()", +                    startstr = "(int) $0 = 0") diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/call-function/main.cpp new file mode 100644 index 000000000000..61a5e9d21abb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/main.cpp @@ -0,0 +1,11 @@ +#include <stdio.h> + +int a_function_to_call() +{  +    return 0; +} + +int main() +{ +    printf("%d\n", a_function_to_call()); // breakpoint +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/Makefile b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py new file mode 100644 index 000000000000..272665a78577 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py @@ -0,0 +1,73 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCppChainedCalls(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureWindows("llvm.org/pr21765") +    def test_with_run_command(self): +        self.build() + +        # Get main source file +        src_file = "main.cpp" +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "Main source file") + +        # Get the path of the executable +        cwd = os.getcwd()  +        exe_file = "a.out" +        exe_path  = os.path.join(cwd, exe_file) + +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        main_breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec) +        self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        args = None +        env = None +        process = target.LaunchSimple(args, env, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Get frame for current thread +        frame = thread.GetSelectedFrame() + +        # Test chained calls +        test_result = frame.EvaluateExpression("get(set(true))") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "true", "get(set(true)) = true") + +        test_result = frame.EvaluateExpression("get(set(false))") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(set(false)) = false") + +        test_result = frame.EvaluateExpression("get(t & f)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(t & f) = false") + +        test_result = frame.EvaluateExpression("get(f & t)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(f & t) = false") + +        test_result = frame.EvaluateExpression("get(t & t)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "true", "get(t & t) = true") + +        test_result = frame.EvaluateExpression("get(f & f)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(f & f) = false") + +        test_result = frame.EvaluateExpression("get(t & f)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(t & f) = false") + +        test_result = frame.EvaluateExpression("get(f) && get(t)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(f) && get(t) = false") + +        test_result = frame.EvaluateExpression("get(f) && get(f)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "get(f) && get(t) = false") + +        test_result = frame.EvaluateExpression("get(t) && get(t)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "true", "get(t) && get(t) = true") diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/main.cpp new file mode 100644 index 000000000000..a888c3f6c557 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/main.cpp @@ -0,0 +1,33 @@ +class Bool { +public: +    Bool operator&(const Bool other) +    { +        Bool result; +        result.value = value && other.value; +        return result; +    } + +    bool value; +}; + +bool get(Bool object) +{ +    return object.value; +} + +Bool set(bool value) +{ +    Bool result; +    result.value = value; +    return result; +} + +int main() +{ +    Bool t = set(true); +    Bool f = set(false); +    get(t); +    get(f); +    get(t & f); +    return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/.categories b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/.categories new file mode 100644 index 000000000000..fe1da0247c62 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/.categories @@ -0,0 +1 @@ +dataformatters diff --git a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/Makefile b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/Makefile new file mode 100644 index 000000000000..932046f26968 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS :=-g -O0 -std=c++11 + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py new file mode 100644 index 000000000000..9bb1faf4ba6d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py @@ -0,0 +1,90 @@ +# coding=utf8 +""" +Test that the C++11 support for char16_t and char32_t works correctly. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class Char1632TestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.source = 'main.cpp' +        self.lines = [ line_number(self.source, '// breakpoint1'),  +                       line_number(self.source, '// breakpoint2') ] + +    @expectedFailureIcc # ICC (13.1) does not emit the DW_TAG_base_type for char16_t and char32_t. +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test(self): +        """Test that the C++11 support for char16_t and char32_t works correctly.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set breakpoints +        for line in self.lines: +            lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line) + +        # Now launch the process, and do not stop at entry point and stop at breakpoint1 +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        if not process: +            self.fail("SBTarget.Launch() failed") + +        if self.TraceOn(): +             self.runCmd("frame variable") + +        # Check that we correctly report the const types +        self.expect("frame variable cs16 cs32", +            substrs = ['(const char16_t *) cs16 = ','(const char32_t *) cs32 = ','u"hello world ྒྙྐ"','U"hello world ྒྙྐ"']) + +        # Check that we correctly report the non-const types +        self.expect("frame variable s16 s32", +            substrs = ['(char16_t *) s16 = ','(char32_t *) s32 = ','u"ﺸﺵۻ"','U"ЕЙРГЖО"']) + +        # Check that we correctly report the array types +        self.expect("frame variable as16 as32", +            patterns = ['\(char16_t \[[0-9]+\]\) as16 = ', '\(char32_t \[[0-9]+\]\) as32 = '], +            substrs = ['u"ﺸﺵۻ"','U"ЕЙРГЖО"']) + +        self.runCmd("next") # step to after the string is nullified + +        # check that we don't crash on NULL +        self.expect("frame variable s32", +            substrs = ['(char32_t *) s32 = 0x00000000']) + +        # continue and hit breakpoint2 +        self.runCmd("continue") + +        # check that the new strings show +        self.expect("frame variable s16 s32", +            substrs = ['(char16_t *) s16 = 0x','(char32_t *) s32 = ','"色ハ匂ヘト散リヌルヲ"','"෴"']) + +        # check the same as above for arrays +        self.expect("frame variable as16 as32", +            patterns = ['\(char16_t \[[0-9]+\]\) as16 = ', '\(char32_t \[[0-9]+\]\) as32 = '], +            substrs = ['"色ハ匂ヘト散リヌルヲ"','"෴"']) + +        # check that zero values are properly handles +        self.expect('frame variable cs16_zero', substrs=["U+0000 u'\\0'"]) +        self.expect('frame variable cs32_zero', substrs=["U+0x00000000 U'\\0'"]) +        self.expect('expression cs16_zero', substrs=["U+0000 u'\\0'"]) +        self.expect('expression cs32_zero', substrs=["U+0x00000000 U'\\0'"]) + +        # Check that we can run expressions that return charN_t +        self.expect("expression u'a'",substrs = ['(char16_t) $',"61 u'a'"]) +        self.expect("expression U'a'",substrs = ['(char32_t) $',"61 U'a'"]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/main.cpp new file mode 100644 index 000000000000..b92c2d572923 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/main.cpp @@ -0,0 +1,44 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <assert.h> +#include <string> + +#define UASZ 64 + +template<class T, int N> +void copy_char_seq (T (&arr)[N], const T* src) +{ +    size_t src_len = std::char_traits<T>::length(src); +    assert(src_len < N); + +    std::char_traits<T>::copy(arr, src, src_len); +    arr[src_len] = 0; +} + +int main (int argc, char const *argv[]) +{ +    char16_t as16[UASZ]; +    char32_t as32[UASZ]; +    auto cs16_zero = (char16_t)0; +    auto cs32_zero = (char32_t)0; +    auto cs16 = u"hello world ྒྙྐ"; +    auto cs32 = U"hello world ྒྙྐ"; +    char16_t *s16 = (char16_t *)u"ﺸﺵۻ"; +    char32_t *s32 = (char32_t *)U"ЕЙРГЖО"; +    copy_char_seq(as16, s16); +    copy_char_seq(as32, s32); +    s32 = nullptr; // breakpoint1 +    s32 = (char32_t *)U"෴"; +    s16 = (char16_t *)u"色ハ匂ヘト散リヌルヲ"; +    copy_char_seq(as16, s16); +    copy_char_seq(as32, s32); +    s32 = nullptr; // breakpoint2 +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/Makefile b/packages/Python/lldbsuite/test/lang/cpp/class_static/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py new file mode 100644 index 000000000000..d47d1b7dde41 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py @@ -0,0 +1,120 @@ +""" +Test display and Python APIs on file and class static variables. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class StaticVariableTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    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.') + +    @expectedFailureWindows("llvm.org/pr24764") +    def test_with_run_command(self): +        """Test that file and class static variables display correctly.""" +        self.build() +        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']) + +        # global variables are no longer displayed with the "frame variable" command.  +        self.expect('target variable A::g_points', VARIABLES_DISPLAYED_CORRECTLY, +            patterns=['\(PointType \[[1-9]*\]\) A::g_points = {.*}']) +        self.expect('target variable g_points', VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ['(PointType [2]) g_points']) + +        # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points. +        # A::g_points is an array of two elements. +        if self.platformIsDarwin() or self.getPlatform() == "linux": +            self.expect("target variable A::g_points[1].x", VARIABLES_DISPLAYED_CORRECTLY, +                startstr = "(int) A::g_points[1].x = 11") + +    @expectedFailureDarwin(9980907) +    @expectedFailureClang('Clang emits incomplete debug info.') +    @expectedFailureFreeBSD('llvm.org/pr20550 failing on FreeBSD-11') +    @expectedFailureGcc('GCC emits incomplete debug info.') +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test Python APIs on file and class static variables.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.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) + +        # The stop reason of the thread should be breakpoint. +        thread = process.GetThreadAtIndex(0) +        if thread.GetStopReason() != lldb.eStopReasonBreakpoint: +            from lldbsuite.test.lldbutil import stop_reason_to_str +            self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % +                      stop_reason_to_str(thread.GetStopReason())) + +        # Get the SBValue of 'A::g_points' and 'g_points'. +        frame = thread.GetFrameAtIndex(0) + +        # arguments =>     False +        # locals =>        False +        # statics =>       True +        # in_scope_only => False +        valList = frame.GetVariables(False, False, True, False) + +        for val in valList: +            self.DebugSBValue(val) +            name = val.GetName() +            self.assertTrue(name in ['g_points', 'A::g_points']) +            if name == 'g_points': +                self.assertTrue(val.GetValueType() == lldb.eValueTypeVariableStatic) +                self.assertTrue(val.GetNumChildren() == 2) +            elif name == 'A::g_points': +                self.assertTrue(val.GetValueType() == lldb.eValueTypeVariableGlobal) +                self.assertTrue(val.GetNumChildren() == 2) +                child1 = val.GetChildAtIndex(1) +                self.DebugSBValue(child1) +                child1_x = child1.GetChildAtIndex(0) +                self.DebugSBValue(child1_x) +                self.assertTrue(child1_x.GetTypeName() == 'int' and +                                child1_x.GetValue() == '11') + +        # SBFrame.FindValue() should also work. +        val = frame.FindValue("A::g_points", lldb.eValueTypeVariableGlobal) +        self.DebugSBValue(val) +        self.assertTrue(val.GetName() == 'A::g_points') + +        # Also exercise the "parameter" and "local" scopes while we are at it. +        val = frame.FindValue("argc", lldb.eValueTypeVariableArgument) +        self.DebugSBValue(val) +        self.assertTrue(val.GetName() == 'argc') + +        val = frame.FindValue("argv", lldb.eValueTypeVariableArgument) +        self.DebugSBValue(val) +        self.assertTrue(val.GetName() == 'argv') + +        val = frame.FindValue("hello_world", lldb.eValueTypeVariableLocal) +        self.DebugSBValue(val) +        self.assertTrue(val.GetName() == 'hello_world') diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/class_static/main.cpp new file mode 100644 index 000000000000..2068eadcac5f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/main.cpp @@ -0,0 +1,53 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// I made this example after noting that I was unable to display an unsized +// static class array. It turns out that gcc 4.2 will emit DWARF that correctly +// describes the PointType, but it will incorrectly emit debug info for the +// "g_points" array where the following things are wrong: +//  - the DW_TAG_array_type won't have a subrange info +//  - the DW_TAG_variable for "g_points" won't have a valid byte size, so even +//    though we know the size of PointType, we can't infer the actual size +//    of the array by dividing the size of the variable by the number of +//    elements. + +#include <stdio.h> + +typedef struct PointType +{ +    int x, y; +} PointType; + +class A +{ +public: +    static PointType g_points[]; +}; + +PointType A::g_points[] =  +{ +    {    1,    2 }, +    {   11,   22 } +}; + +static PointType g_points[] =  +{ +    {    3,    4 }, +    {   33,   44 } +}; + +int +main (int argc, char const *argv[]) +{ +    const char *hello_world = "Hello, world!"; +    printf ("A::g_points[1].x = %i\n", A::g_points[1].x); // Set break point at this line. +    printf ("::g_points[1].x = %i\n", g_points[1].x); +    printf ("%s\n", hello_world); +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/class_types/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py new file mode 100644 index 000000000000..b67e53c30745 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py @@ -0,0 +1,215 @@ +"""Test breakpoint on a class constructor; and variable list the this object.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ClassTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.line = line_number('main.cpp', '// Set break point at this line.') + +    def test_with_run_command(self): +        """Test 'frame variable this' when stopped on a class constructor.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break on the ctor function of class C. +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The test suite sometimes shows that the process has exited without stopping. +        # +        # CC=clang ./dotest.py -v -t class_types +        # ... +        # Process 76604 exited with status = 0 (0x00000000) +        self.runCmd("process status") + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # We should be stopped on the ctor function of class C. +        self.expect("frame variable --show-types this", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ['C *', +                       ' this = ']) + +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Use Python APIs to create a breakpoint by (filespec, line).""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        filespec = target.GetExecutable() +        self.assertTrue(filespec, VALID_FILESPEC) + +        fsDir = os.path.normpath(filespec.GetDirectory()) +        fsFile = filespec.GetFilename() + +        self.assertTrue(fsDir == os.getcwd() and fsFile == "a.out", +                        "FileSpec matches the executable") + +        bpfilespec = lldb.SBFileSpec("main.cpp", False) + +        breakpoint = target.BreakpointCreateByLocation(bpfilespec, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        # Verify the breakpoint just created. +        self.expect(str(breakpoint), BREAKPOINT_CREATED, exe=False, +            substrs = ['main.cpp', +                       str(self.line)]) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        if not process: +            self.fail("SBTarget.Launch() failed") + +        if process.GetState() != lldb.eStateStopped: +            self.fail("Process should be in the 'stopped' state, " +                      "instead the actual state is: '%s'" % +                      lldbutil.state_type_to_str(process.GetState())) + +        # The stop reason of the thread should be breakpoint. +        thread = process.GetThreadAtIndex(0) +        if thread.GetStopReason() != lldb.eStopReasonBreakpoint: +            from lldbsuite.test.lldbutil import stop_reason_to_str +            self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % +                      stop_reason_to_str(thread.GetStopReason())) + +        # The filename of frame #0 should be 'main.cpp' and the line number +        # should be 93. +        self.expect("%s:%d" % (lldbutil.get_filenames(thread)[0], +                               lldbutil.get_line_numbers(thread)[0]), +                    "Break correctly at main.cpp:%d" % self.line, exe=False, +            startstr = "main.cpp:") +            ### clang compiled code reported main.cpp:94? +            ### startstr = "main.cpp:93") + +        # We should be stopped on the breakpoint with a hit count of 1. +        self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + +        process.Continue() + +    def test_with_expr_parser(self): +        """Test 'frame variable this' and 'expr this' when stopped inside a constructor.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # rdar://problem/8516141 +        # Is this a case of clang (116.1) generating bad debug info? +        # +        # Break on the ctor function of class C. +        #self.expect("breakpoint set -M C", BREAKPOINT_CREATED, +        #    startstr = "Breakpoint created: 1: name = 'C'") + +        # Make the test case more robust by using line number to break, instead. +        lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=-1) + +        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']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # Continue on inside the ctor() body... +        self.runCmd("register read pc") +        self.runCmd("thread step-over") + +        # Verify that 'frame variable this' gets the data type correct. +        self.expect("frame variable this",VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ['C *']) + +        # Verify that frame variable --show-types this->m_c_int behaves correctly. +        self.runCmd("register read pc") +        self.runCmd("expr m_c_int") +        self.expect("frame variable --show-types this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = '(int) this->m_c_int = 66') + +        # Verify that 'expression this' gets the data type correct. +        self.expect("expression this", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ['C *']) + +        # rdar://problem/8430916 +        # expr this->m_c_int returns an incorrect value +        # +        # Verify that expr this->m_c_int behaves correctly. +        self.expect("expression this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY, +            patterns = ['\(int\) \$[0-9]+ = 66']) + +    def test_with_constructor_name (self): +        """Test 'frame variable this' and 'expr this' when stopped inside a constructor.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        filespec = target.GetExecutable() +        self.assertTrue(filespec, VALID_FILESPEC) + +        fsDir = os.path.normpath(filespec.GetDirectory()) +        fsFile = filespec.GetFilename() + +        self.assertTrue(fsDir == os.getcwd() and fsFile == "a.out", +                        "FileSpec matches the executable") + +        bpfilespec = lldb.SBFileSpec("main.cpp", False) + +        breakpoint = target.BreakpointCreateByLocation(bpfilespec, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        # Verify the breakpoint just created. +        self.expect(str(breakpoint), BREAKPOINT_CREATED, exe=False, +            substrs = ['main.cpp', +                       str(self.line)]) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        if not process: +            self.fail("SBTarget.Launch() failed") + +        if process.GetState() != lldb.eStateStopped: +            self.fail("Process should be in the 'stopped' state, " +                      "instead the actual state is: '%s'" % +                      lldbutil.state_type_to_str(process.GetState())) + +        # The stop reason of the thread should be breakpoint. +        thread = process.GetThreadAtIndex(0) +        if thread.GetStopReason() != lldb.eStopReasonBreakpoint: +            from lldbsuite.test.lldbutil import stop_reason_to_str +            self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % +                      stop_reason_to_str(thread.GetStopReason())) + +        frame = thread.frames[0] +        self.assertTrue (frame.IsValid(), "Got a valid frame.") + +        self.assertTrue ("C::C" in frame.name, "Constructor name includes class name.") diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py new file mode 100644 index 000000000000..595d075d5180 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py @@ -0,0 +1,94 @@ +""" +Test the lldb disassemble command on each call frame when stopped on C's ctor. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class IterateFrameAndDisassembleTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def test_and_run_command(self): +        """Disassemble each call frame when stopped on C's constructor.""" +        self.build() +        self.breakOnCtor() + +        raw_output = self.res.GetOutput() +        frameRE = re.compile(r""" +                              ^\s\sframe        # heading for the frame info, +                              .*                # wildcard, and +                              0x[0-9a-f]{16}    # the frame pc, and +                              \sa.out`(.+)      # module`function, and +                              \s\+\s            # the rest ' + ....' +                              """, re.VERBOSE) +        for line in raw_output.split(os.linesep): +            match = frameRE.search(line) +            if match: +                function = match.group(1) +                #print("line:", line) +                #print("function:", function) +                self.runCmd("disassemble -n '%s'" % function) + +    @add_test_categories(['pyapi']) +    def test_and_python_api(self): +        """Disassemble each call frame when stopped on C's constructor.""" +        self.build() +        self.breakOnCtor() + +        # Now use the Python API to get at each function on the call stack and +        # disassemble it. +        target = self.dbg.GetSelectedTarget() +        process = target.GetProcess() +        thread = process.GetThreadAtIndex(0) +        depth = thread.GetNumFrames() +        for i in range(depth - 1): +            frame = thread.GetFrameAtIndex(i) +            function = frame.GetFunction() +            # Print the function header. +            if self.TraceOn(): +                print() +                print(function) +            if function: +                # Get all instructions for this function and print them out. +                insts = function.GetInstructions(target) +                for inst in insts: +                    # We could simply do 'print inst' to print out the disassembly. +                    # But we want to print to stdout only if self.TraceOn() is True. +                    disasm = str(inst) +                    if self.TraceOn(): +                        print(disasm) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.line = line_number('main.cpp', '// Set break point at this line.') + +    def breakOnCtor(self): +        """Setup/run the program so it stops on C's constructor.""" +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break on the ctor function of class C. +        bpno = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1) + +        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 %d.'%(bpno)]) + +        # This test was failing because we fail to put the C:: in front of constructore. +        # We should maybe make another testcase to cover that specifically, but we shouldn't +        # fail this whole testcase for an inessential issue. +        # We should be stopped on the ctor function of class C. +        # self.expect("thread backtrace", BACKTRACE_DISPLAYED_CORRECTLY, +        #  substrs = ['C::C']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/cmds.txt b/packages/Python/lldbsuite/test/lang/cpp/class_types/cmds.txt new file mode 100644 index 000000000000..1c7ef9f1c8ad --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/cmds.txt @@ -0,0 +1,3 @@ +b main.cpp:97 +c +var diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/class_types/main.cpp new file mode 100644 index 000000000000..251e66c3c9f7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/main.cpp @@ -0,0 +1,126 @@ +//===-- 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 Conversion +{ +public: +    Conversion (int i) : +      m_i (i) +      {} + +    operator bool() +    { +        return m_i != 0; +    } +     +private: +    int m_i; +}; + +class A +{ +public: +    A(int i=0): +        m_a_int(i), +        m_aa_int(i+1) +    { +    } + +    //virtual +    ~A() +    { +    } + +    int +    GetInteger() const +    { +        return m_a_int; +    } +    void +    SetInteger(int i) +    { +        m_a_int = i; +    } + +protected: +    int m_a_int; +    int m_aa_int; +}; + +class B : public A +{ +public: +    B(int ai, int bi) : +        A(ai), +        m_b_int(bi) +    { +    } + +    //virtual +    ~B() +    { +    } + +    int +    GetIntegerB() const +    { +        return m_b_int; +    } +    void +    SetIntegerB(int i) +    { +        m_b_int = i; +    } + +protected: +    int m_b_int; +}; + +#include <cstdio> +class C : public B +{ +public: +    C(int ai, int bi, int ci) : +        B(ai, bi), +        m_c_int(ci) +    { +        printf("Within C::ctor() m_c_int=%d\n", m_c_int); // Set break point at this line. +    } + +    //virtual +    ~C() +    { +    } + +    int +    GetIntegerC() const +    { +        return m_c_int; +    } +    void +    SetIntegerC(int i) +    { +        m_c_int = i; +    } + +protected: +    int m_c_int; +}; + +int +main (int argc, char const *argv[]) +{ +    A a(12); +    B b(22,33); +    C c(44,55,66); +    Conversion conv(1); +    if (conv) +        return b.GetIntegerB() - a.GetInteger() + c.GetInteger(); +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/diamond/Makefile b/packages/Python/lldbsuite/test/lang/cpp/diamond/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/diamond/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py b/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py new file mode 100644 index 000000000000..67de03b54b20 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py @@ -0,0 +1,41 @@ +""" +Tests that bool types work +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPTestDiamondInheritance(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    def test_with_run_command(self): +        """Test that virtual base classes work in when SBValue objects are used to explore the variable value""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +         +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 1')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 2')) +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue(process, PROCESS_IS_VALID) +        thread = process.GetThreadAtIndex(0) +        frame = thread.GetFrameAtIndex(0) +        j1 = frame.FindVariable("j1") +        j1_Derived1 = j1.GetChildAtIndex(0) +        j1_Derived2 = j1.GetChildAtIndex(1) +        j1_Derived1_VBase = j1_Derived1.GetChildAtIndex(0) +        j1_Derived2_VBase = j1_Derived2.GetChildAtIndex(0) +        j1_Derived1_VBase_m_value = j1_Derived1_VBase.GetChildAtIndex(0) +        j1_Derived2_VBase_m_value = j1_Derived2_VBase.GetChildAtIndex(0) +        self.assertTrue(j1_Derived1_VBase.GetLoadAddress() == j1_Derived2_VBase.GetLoadAddress(), "ensure virtual base class is the same between Derived1 and Derived2") +        self.assertTrue(j1_Derived1_VBase_m_value.GetValueAsUnsigned(1) == j1_Derived2_VBase_m_value.GetValueAsUnsigned(2), "ensure m_value in VBase is the same") +        self.assertTrue(frame.FindVariable("d").GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned(0) == 12345, "ensure Derived2 from j1 is correct"); +        thread.StepOver() +        self.assertTrue(frame.FindVariable("d").GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned(0) == 12346, "ensure Derived2 from j2 is correct"); +     +    def set_breakpoint(self, line): +        # Some compilers (for example GCC 4.4.7 and 4.6.1) emit multiple locations for the statement with the ternary +        # operator in the test program, while others emit only 1. +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=-1, loc_exact=False) diff --git a/packages/Python/lldbsuite/test/lang/cpp/diamond/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/diamond/main.cpp new file mode 100644 index 000000000000..bfe098a089f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/diamond/main.cpp @@ -0,0 +1,85 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +static int g_next_value = 12345; + +class VBase +{ +public: +    VBase() : m_value(g_next_value++) {} +    virtual ~VBase() {} +    void Print()  +    { +        printf("%p: %s\n%p: m_value = 0x%8.8x\n", this, __PRETTY_FUNCTION__, &m_value, m_value); +    } +    int m_value; +}; + +class Derived1 : public virtual VBase +{ +public: +    Derived1() {}; +    void Print () +    { +        printf("%p: %s\n", this, __PRETTY_FUNCTION__); +        VBase::Print(); +    } + +}; + +class Derived2 : public virtual VBase +{ +public: +    Derived2() {}; +     +    void Print () +    { +        printf("%p: %s\n", this, __PRETTY_FUNCTION__); +        VBase::Print(); +    } +}; + +class Joiner1 : public Derived1, public Derived2 +{ +public: +    Joiner1() :  +        m_joiner1(3456),  +        m_joiner2(6789) {} +    void Print () +    { +        printf("%p: %s \n%p: m_joiner1 = 0x%8.8x\n%p: m_joiner2 = 0x%8.8x\n", +               this, +               __PRETTY_FUNCTION__, +               &m_joiner1, +               m_joiner1, +               &m_joiner2, +               m_joiner2); +        Derived1::Print(); +        Derived2::Print(); +    } +    int m_joiner1; +    int m_joiner2; +}; + +class Joiner2 : public Derived2 +{ +    int m_stuff[32]; +}; + +int main(int argc, const char * argv[]) +{ +    Joiner1 j1; +    Joiner2 j2; +    j1.Print(); +    j2.Print(); +    Derived2 *d = &j1; +    d = &j2;  // breakpoint 1 +    return 0; // breakpoint 2 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/Makefile b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/Makefile new file mode 100644 index 000000000000..8770b2343ef0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := pass-to-base.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py new file mode 100644 index 000000000000..4e23cd899285 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py @@ -0,0 +1,129 @@ +""" +Test lldb Python API SBValue::Cast(SBType) for C++ types. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class CppValueCastTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @unittest2.expectedFailure("rdar://problem/10808472 SBValue::Cast test case is failing (virtual inheritance)") +    @add_test_categories(['pyapi']) +    def test_value_cast_with_virtual_inheritance(self): +        """Test SBValue::Cast(SBType) API for C++ types with virtual inheritance.""" +        self.build(dictionary=self.d_virtual) +        self.setTearDownCleanup(dictionary=self.d_virtual) +        self.do_sbvalue_cast(self.exe_name) + +    @add_test_categories(['pyapi']) +    def test_value_cast_with_regular_inheritance(self): +        """Test SBValue::Cast(SBType) API for C++ types with regular inheritance.""" +        self.build(dictionary=self.d_regular) +        self.setTearDownCleanup(dictionary=self.d_regular) +        self.do_sbvalue_cast(self.exe_name) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        # Find the line number to break for main.c.                                                                                        +        self.source = 'sbvalue-cast.cpp'; +        self.line = line_number(self.source, '// Set breakpoint here.') +        self.exe_name = self.testMethodName +        self.d_virtual = {'CXX_SOURCES': self.source, 'EXE': self.exe_name, 'CFLAGS_EXTRAS': '-DDO_VIRTUAL_INHERITANCE'} +        self.d_regular = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + +    def do_sbvalue_cast (self, exe_name): +        """Test SBValue::Cast(SBType) API for C++ types.""" +        exe = os.path.join(os.getcwd(), exe_name) + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: + +        breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        # Find DerivedA and DerivedB types. +        typeA = target.FindFirstType('DerivedA') +        typeB = target.FindFirstType('DerivedB') +        self.DebugSBType(typeA) +        self.DebugSBType(typeB) +        self.assertTrue(typeA) +        self.assertTrue(typeB) +        error = lldb.SBError() + +        # First stop is for DerivedA instance. +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] +        frame0 = thread.GetFrameAtIndex(0) + +        tellerA = frame0.FindVariable('teller', lldb.eNoDynamicValues) +        self.DebugSBValue(tellerA) +        self.assertTrue(tellerA.GetChildMemberWithName('m_base_val').GetValueAsUnsigned(error, 0) == 20) + +        if self.TraceOn(): +            for child in tellerA: +                print("child name:", child.GetName()) +                print(child) + +        # Call SBValue.Cast() to obtain instanceA. +        instanceA = tellerA.Cast(typeA.GetPointerType()) +        self.DebugSBValue(instanceA) + +        # Iterate through all the children and print their values. +        if self.TraceOn(): +            for child in instanceA: +                print("child name:", child.GetName()) +                print(child) +        a_member_val = instanceA.GetChildMemberWithName('m_a_val') +        self.DebugSBValue(a_member_val) +        self.assertTrue(a_member_val.GetValueAsUnsigned(error, 0) == 10) + +        # Second stop is for DerivedB instance. +        threads = lldbutil.continue_to_breakpoint (process, breakpoint) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] +        frame0 = thread.GetFrameAtIndex(0) + +        tellerB = frame0.FindVariable('teller', lldb.eNoDynamicValues) +        self.DebugSBValue(tellerB) +        self.assertTrue(tellerB.GetChildMemberWithName('m_base_val').GetValueAsUnsigned(error, 0) == 12) + +        if self.TraceOn(): +            for child in tellerB: +                print("child name:", child.GetName()) +                print(child) + +        # Call SBValue.Cast() to obtain instanceB. +        instanceB = tellerB.Cast(typeB.GetPointerType()) +        self.DebugSBValue(instanceB) + +        # Iterate through all the children and print their values. +        if self.TraceOn(): +            for child in instanceB: +                print("child name:", child.GetName()) +                print(child) +        b_member_val = instanceB.GetChildMemberWithName('m_b_val') +        self.DebugSBValue(b_member_val) +        self.assertTrue(b_member_val.GetValueAsUnsigned(error, 0) == 36) diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py new file mode 100644 index 000000000000..56e81c56cfa6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py @@ -0,0 +1,223 @@ +""" +Use lldb Python API to test dynamic values in C++ +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class DynamicValueTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        # Find the line number to break for main.c.                                                                                        + +        self.do_something_line = line_number('pass-to-base.cpp', '// Break here in doSomething.') +        self.main_first_call_line = line_number('pass-to-base.cpp', +                                                 '// Break here and get real addresses of myB and otherB.') +        self.main_second_call_line = line_number('pass-to-base.cpp', +                                                       '// Break here and get real address of reallyA.') + +    @expectedFailureFreeBSD # FIXME: This needs to be root-caused. +    @expectedFailureWindows("llvm.org/pr24663") +    @add_test_categories(['pyapi']) +    def test_get_dynamic_vals(self): +        """Test fetching C++ dynamic values from pointers & references.""" +        self.build(dictionary=self.getBuildFlags()) +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: + +        do_something_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.do_something_line) +        self.assertTrue(do_something_bpt, +                        VALID_BREAKPOINT) + +        first_call_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.main_first_call_line) +        self.assertTrue(first_call_bpt, +                        VALID_BREAKPOINT) + +        second_call_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.main_second_call_line) +        self.assertTrue(second_call_bpt, +                        VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, first_call_bpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) + +        # Now find the dynamic addresses of myB and otherB so we can compare them +        # with the dynamic values we get in doSomething: + +        use_dynamic = lldb.eDynamicCanRunTarget +        no_dynamic  = lldb.eNoDynamicValues + +        myB = frame.FindVariable ('myB', no_dynamic); +        self.assertTrue (myB) +        myB_loc = int (myB.GetLocation(), 16) + +        otherB = frame.FindVariable('otherB', no_dynamic) +        self.assertTrue (otherB) +        otherB_loc = int (otherB.GetLocation(), 16) + +        # Okay now run to doSomething: + +        threads = lldbutil.continue_to_breakpoint (process, do_something_bpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) + +        # Get "this" using FindVariable: + +        this_static = frame.FindVariable ('this', no_dynamic) +        this_dynamic = frame.FindVariable ('this', use_dynamic) +        self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc) +         +        # Now make sure that the "GetDynamicValue" works: +        # This doesn't work currently because we can't get dynamic values from ConstResult objects. +        fetched_dynamic_value = this_static.GetDynamicValue(use_dynamic) +        self.examine_value_object_of_this_ptr (this_static, fetched_dynamic_value, myB_loc) + +        # And conversely that the GetDynamicValue() interface also works: +        fetched_static_value = this_dynamic.GetStaticValue() +        self.examine_value_object_of_this_ptr (fetched_static_value, this_dynamic, myB_loc) + +        # Get "this" using FindValue, make sure that works too: +        this_static = frame.FindValue ('this', lldb.eValueTypeVariableArgument, no_dynamic) +        this_dynamic = frame.FindValue ('this', lldb.eValueTypeVariableArgument, use_dynamic) +        self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc) + +        # Get "this" using the EvaluateExpression: +        this_static = frame.EvaluateExpression ('this', False) +        this_dynamic = frame.EvaluateExpression ('this', True) +        self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc) +         +        # The "frame var" code uses another path to get into children, so let's +        # make sure that works as well: + +        self.expect('frame var -d run-target --ptr-depth=2 --show-types anotherA.m_client_A', 'frame var finds its way into a child member', +            patterns = ['\(B \*\)']) + +        # Now make sure we also get it right for a reference as well: + +        anotherA_static = frame.FindVariable ('anotherA', False) +        self.assertTrue (anotherA_static) +        anotherA_static_addr = int (anotherA_static.GetValue(), 16) + +        anotherA_dynamic = frame.FindVariable ('anotherA', True) +        self.assertTrue (anotherA_dynamic) +        anotherA_dynamic_addr = int (anotherA_dynamic.GetValue(), 16) +        anotherA_dynamic_typename = anotherA_dynamic.GetTypeName() +        self.assertTrue (anotherA_dynamic_typename.find('B') != -1) + +        self.assertTrue(anotherA_dynamic_addr < anotherA_static_addr) + +        anotherA_m_b_value_dynamic = anotherA_dynamic.GetChildMemberWithName('m_b_value', True) +        self.assertTrue (anotherA_m_b_value_dynamic) +        anotherA_m_b_val = int (anotherA_m_b_value_dynamic.GetValue(), 10) +        self.assertTrue (anotherA_m_b_val == 300) + +        anotherA_m_b_value_static = anotherA_static.GetChildMemberWithName('m_b_value', True) +        self.assertFalse (anotherA_m_b_value_static) + +        # Okay, now continue again, and when we hit the second breakpoint in main + +        threads = lldbutil.continue_to_breakpoint (process, second_call_bpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) +        reallyA_value = frame.FindVariable ('reallyA', False) +        self.assertTrue(reallyA_value) +        reallyA_loc = int (reallyA_value.GetLocation(), 16) +         +        # Finally continue to doSomething again, and make sure we get the right value for anotherA, +        # which this time around is just an "A". + +        threads = lldbutil.continue_to_breakpoint (process, do_something_bpt) +        self.assertTrue(len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) +        anotherA_value = frame.FindVariable ('anotherA', True) +        self.assertTrue(anotherA_value) +        anotherA_loc = int (anotherA_value.GetValue(), 16) +        self.assertTrue (anotherA_loc == reallyA_loc) +        self.assertTrue (anotherA_value.GetTypeName().find ('B') == -1) + +    def examine_value_object_of_this_ptr (self, this_static, this_dynamic, dynamic_location): +        # Get "this" as its static value +        self.assertTrue (this_static) +        this_static_loc = int (this_static.GetValue(), 16) +         +        # Get "this" as its dynamic value +         +        self.assertTrue (this_dynamic) +        this_dynamic_typename = this_dynamic.GetTypeName() +        self.assertTrue (this_dynamic_typename.find('B') != -1) +        this_dynamic_loc = int (this_dynamic.GetValue(), 16) +         +        # Make sure we got the right address for "this" +         +        self.assertTrue (this_dynamic_loc == dynamic_location) + +        # And that the static address is greater than the dynamic one + +        self.assertTrue (this_static_loc > this_dynamic_loc) +         +        # Now read m_b_value which is only in the dynamic value: + +        use_dynamic = lldb.eDynamicCanRunTarget +        no_dynamic  = lldb.eNoDynamicValues + +        this_dynamic_m_b_value = this_dynamic.GetChildMemberWithName('m_b_value', use_dynamic) +        self.assertTrue (this_dynamic_m_b_value) +         +        m_b_value = int (this_dynamic_m_b_value.GetValue(), 0) +        self.assertTrue (m_b_value == 10) +         +        # Make sure it is not in the static version + +        this_static_m_b_value = this_static.GetChildMemberWithName('m_b_value', no_dynamic) +        self.assertFalse (this_static_m_b_value) + +        # Okay, now let's make sure that we can get the dynamic type of a child element: + +        contained_auto_ptr = this_dynamic.GetChildMemberWithName ('m_client_A', use_dynamic) +        self.assertTrue (contained_auto_ptr) +        contained_b = contained_auto_ptr.GetChildMemberWithName ('_M_ptr', use_dynamic) +        if not contained_b: +                contained_b = contained_auto_ptr.GetChildMemberWithName ('__ptr_', use_dynamic) +        self.assertTrue (contained_b) +         +        contained_b_static = contained_auto_ptr.GetChildMemberWithName ('_M_ptr', no_dynamic) +        if not contained_b_static: +                contained_b_static = contained_auto_ptr.GetChildMemberWithName ('__ptr_', no_dynamic) +        self.assertTrue (contained_b_static) +         +        contained_b_addr = int (contained_b.GetValue(), 16) +        contained_b_static_addr = int (contained_b_static.GetValue(), 16) +         +        self.assertTrue (contained_b_addr < contained_b_static_addr) diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/pass-to-base.cpp b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/pass-to-base.cpp new file mode 100644 index 000000000000..2bccf3303823 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/pass-to-base.cpp @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <memory> + +class Extra +{ +public: +  Extra (int in_one, int in_two) : m_extra_one(in_one), m_extra_two(in_two) {} + +private: +  int m_extra_one; +  int m_extra_two; +}; + +class A +{ +public: +  A(int value) : m_a_value (value) {} +  A(int value, A* client_A) : m_a_value (value), m_client_A (client_A) {} + +  virtual ~A() {} + +  virtual void +  doSomething (A &anotherA) +  { +    printf ("In A %p doing something with %d.\n", this, m_a_value); +    int tmp_value = anotherA.Value(); +    printf ("Also have another A at %p: %d.\n", &anotherA, tmp_value); // Break here in doSomething. +  } + +  int  +  Value() +  { +    return m_a_value; +  } + +private: +  int m_a_value; +  std::auto_ptr<A> m_client_A; +}; + +class B : public Extra, public virtual A +{ +public: +  B (int b_value, int a_value) : Extra(b_value, a_value), A(a_value), m_b_value(b_value) {} +  B (int b_value, int a_value, A *client_A) : Extra(b_value, a_value), A(a_value, client_A), m_b_value(b_value) {} + +  virtual ~B () {} + +private: +  int m_b_value; +}; + +static A* my_global_A_ptr; + +int +main (int argc, char **argv) +{ +  my_global_A_ptr = new B (100, 200); +  B myB (10, 20, my_global_A_ptr); +  B *second_fake_A_ptr = new B (150, 250); +  B otherB (300, 400, second_fake_A_ptr); + +  myB.doSomething(otherB); // Break here and get real addresses of myB and otherB. + +  A reallyA (500); +  myB.doSomething (reallyA);  // Break here and get real address of reallyA. + +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/sbvalue-cast.cpp b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/sbvalue-cast.cpp new file mode 100644 index 000000000000..00fd7dad438c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/sbvalue-cast.cpp @@ -0,0 +1,80 @@ +//===-- sbvalue-cast.cpp ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifdef DO_VIRTUAL_INHERITANCE +#define VIRTUAL virtual +#else +#define VIRTUAL  +#endif + +#include <stdio.h> + +class Base +{ +public: +    Base(int val) : m_base_val (val) {} +    virtual ~Base() {} + +    virtual void +    forcast(int input) { +        int future_val = m_base_val + input * 1; +        printf("Forcasting %d\n", future_val); +    } + +protected: +    int m_base_val; +}; + +class DerivedA : public VIRTUAL Base +{ +public: +    DerivedA(int val) : Base(val*2), m_a_val(val) { +        printf("DerivedA::ctor()->\n"); +        printf("m_base_val=%d\n", m_base_val); +        printf("m_a_val=%d\n", m_a_val); +    } +    virtual ~DerivedA() {} + +private: +    int m_a_val; +}; + +class DerivedB : public VIRTUAL Base +{ +public: +    DerivedB(int val) : Base(val), m_b_val(val*3) { +        printf("DerivedB::ctor()->\n"); +        printf("m_base_val=%d\n", m_base_val); +        printf("m_b_val=%d\n", m_b_val); +    } +    virtual ~DerivedB() {} +     +    virtual void +    forcast(int input) { +        int future_val = m_b_val + input * 2; +        printf("Forcasting %d\n", future_val); +    } + +private: +    int m_b_val; +}; + +int +main(int argc, char **argv) +{ +	DerivedA* dA = new DerivedA(10); +	DerivedB* dB = new DerivedB(12); +	Base *array[2] = {dA, dB}; +    Base *teller = NULL; +    for (int i = 0; i < 2; ++i) { +        teller = array[i]; +        teller->forcast(i); // Set breakpoint here. +    } + +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/enum_types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/enum_types/Makefile new file mode 100644 index 000000000000..0e0f5d1dad3d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/enum_types/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +CXXFLAGS += -std=c++11 + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules + diff --git a/packages/Python/lldbsuite/test/lang/cpp/enum_types/TestCPP11EnumTypes.py b/packages/Python/lldbsuite/test/lang/cpp/enum_types/TestCPP11EnumTypes.py new file mode 100644 index 000000000000..51c145c7b7cd --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/enum_types/TestCPP11EnumTypes.py @@ -0,0 +1,110 @@ +"""Look up enum type information and check for correct display.""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPP11EnumTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def test_int8_t(self): +        """Test C++11 enumeration class types as int8_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=int8_t"'}) +        self.image_lookup_for_enum_type() + +    def test_int16_t(self): +        """Test C++11 enumeration class types as int16_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=int16_t"'}) +        self.image_lookup_for_enum_type() + +    def test_int32_t(self): +        """Test C++11 enumeration class types as int32_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=int32_t"'}) +        self.image_lookup_for_enum_type() + +    def test_int64_t(self): +        """Test C++11 enumeration class types as int64_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=int64_t"'}) +        self.image_lookup_for_enum_type() + +    def test_uint8_t(self): +        """Test C++11 enumeration class types as uint8_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=uint8_t"'}) +        self.image_lookup_for_enum_type() + +    def test_uint16_t(self): +        """Test C++11 enumeration class types as uint16_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=uint16_t"'}) +        self.image_lookup_for_enum_type() + +    def test_uint32_t(self): +        """Test C++11 enumeration class types as uint32_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=uint32_t"'}) +        self.image_lookup_for_enum_type() + +    def test_uint64_t(self): +        """Test C++11 enumeration class types as uint64_t types.""" +        self.build(dictionary={'CFLAGS_EXTRAS': '"-DTEST_BLOCK_CAPTURED_VARS=uint64_t"'}) +        self.image_lookup_for_enum_type() + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.cpp', '// Set break point at this line.') + +    def image_lookup_for_enum_type(self): +        """Test C++11 enumeration class types.""" +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the main. +        bkpt_id = 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']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # Look up information about the 'DayType' enum type. +        # Check for correct display. +        self.expect("image lookup -t DayType", DATA_TYPES_DISPLAYED_CORRECTLY, +            substrs = ['enum DayType {', +                       'Monday', +                       'Tuesday', +                       'Wednesday', +                       'Thursday', +                       'Friday', +                       'Saturday', +                       'Sunday', +                       'kNumDays', +                       '}']) + +        enum_values = [ '-4',  +                        'Monday',  +                        'Tuesday',  +                        'Wednesday',  +                        'Thursday', +                        'Friday', +                        'Saturday', +                        'Sunday', +                        'kNumDays', +                        '5']; + +        bkpt = self.target().FindBreakpointByID(bkpt_id) +        for enum_value in enum_values: +            self.expect("frame variable day", 'check for valid enumeration value', +                substrs = [enum_value]) +            lldbutil.continue_to_breakpoint (self.process(), bkpt) diff --git a/packages/Python/lldbsuite/test/lang/cpp/enum_types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/enum_types/main.cpp new file mode 100644 index 000000000000..8595050afbbf --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/enum_types/main.cpp @@ -0,0 +1,33 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + + +int main (int argc, char const *argv[]) +{ +    typedef int16_t enum_integer_t; +    enum class DayType : enum_integer_t { +        Monday = -3, +        Tuesday, +        Wednesday, +        Thursday, +        Friday, +        Saturday, +        Sunday, +        kNumDays +    }; +    enum_integer_t day_value; +    for (day_value = (enum_integer_t)DayType::Monday - 1; day_value <= (enum_integer_t)DayType::kNumDays + 1; ++day_value) +    { +        DayType day = (DayType)day_value; +        printf("day as int is %i\n", (int)day); // Set break point at this line. +    } +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/exceptions/Makefile b/packages/Python/lldbsuite/test/lang/cpp/exceptions/Makefile new file mode 100644 index 000000000000..a6bd8463ad54 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/exceptions/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := exceptions.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py b/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py new file mode 100644 index 000000000000..65cf0b361d84 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py @@ -0,0 +1,65 @@ +""" +Test lldb exception breakpoint command for CPP. +""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class CPPBreakpointTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        self.source = 'exceptions.cpp' +        self.catch_line = line_number(self.source, '// This is the line you should stop at for catch') + +    @expectedFailureWindows("llvm.org/pr24538") # clang-cl does not support throw or catch +    def test(self): +        """Test lldb exception breakpoint command for CPP.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeC_plus_plus, True, True) +        self.assertTrue (exception_bkpt, "Made an exception breakpoint") + +        # Now run, and make sure we hit our breakpoint: +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue (process, "Got a valid process") +         +        stopped_threads = [] +        stopped_threads = lldbutil.get_threads_stopped_at_breakpoint (process, exception_bkpt) +        self.assertTrue (len(stopped_threads) == 1, "Stopped at our exception breakpoint.") +        thread = stopped_threads[0] +        # Make sure our throw function is still above us on the stack: + +        frame_functions = lldbutil.get_function_names(thread) +        self.assertTrue (frame_functions.count ("throws_exception_on_even(int)") == 1, "Our throw function is still on the stack.") + +        # Okay we hit our exception throw breakpoint, now make sure we get our catch breakpoint. +        # One potential complication is that we might hit a couple of the exception breakpoints in getting out of the throw. +        # so loop till we don't see the throws function on the stack.  We should stop one more time for our exception breakpoint +        # and that should be the catch... + +        while frame_functions.count ("throws_exception_on_even(int)") == 1:  +            stopped_threads = lldbutil.continue_to_breakpoint (process, exception_bkpt) +            self.assertTrue (len(stopped_threads) == 1) +         +            thread = stopped_threads[0] +            frame_functions = lldbutil.get_function_names(thread) + +        self.assertTrue (frame_functions.count ("throws_exception_on_even(int)") == 0, "At catch our throw function is off the stack") +        self.assertTrue (frame_functions.count ("intervening_function(int)") == 0,     "At catch our intervening function is off the stack") +        self.assertTrue (frame_functions.count ("catches_exception(int)") == 1, "At catch our catch function is on the stack") diff --git a/packages/Python/lldbsuite/test/lang/cpp/exceptions/exceptions.cpp b/packages/Python/lldbsuite/test/lang/cpp/exceptions/exceptions.cpp new file mode 100644 index 000000000000..150d420b241b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/exceptions/exceptions.cpp @@ -0,0 +1,42 @@ +#include <exception> +#include <stdio.h> + +int throws_exception_on_even (int value); +int intervening_function (int value); +int catches_exception (int value); + +int +catches_exception (int value) +{ +    try +    { +        return intervening_function(value); // This is the line you should stop at for catch +    } +    catch (int value) +    { +        return value;   +    } +} + +int  +intervening_function (int value) +{ +    return throws_exception_on_even (2 * value); +} + +int +throws_exception_on_even (int value) +{ +    printf ("Mod two works: %d.\n", value%2); +    if (value % 2 == 0) +        throw 30; +    else +        return value; +} + +int  +main () +{ +    catches_exception (10); // Stop here +    return 5; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/Makefile b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py new file mode 100644 index 000000000000..396a637041cb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py @@ -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']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/main.cpp new file mode 100644 index 000000000000..494b846336ff --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/main.cpp @@ -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 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/Makefile b/packages/Python/lldbsuite/test/lang/cpp/global_operators/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py new file mode 100644 index 000000000000..de56cd6a6c49 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py @@ -0,0 +1,54 @@ +""" +Test that global operators are found and evaluated. +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCppGlobalOperators(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    @expectedFailureWindows("llvm.org/pr21765") +    def test_with_run_command(self): +        self.build() + +        # Get main source file +        src_file = "main.cpp" +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "Main source file") +         +        # Get the path of the executable +        cwd = os.getcwd() +        exe_file = "a.out" +        exe_path  = os.path.join(cwd, exe_file) +         +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        main_breakpoint = target.BreakpointCreateBySourceRegex("// break here", src_file_spec) +        self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        args = None +        env = None +        process = target.LaunchSimple(args, env, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Check if global operators are evaluated  +        frame = thread.GetSelectedFrame() + +        test_result = frame.EvaluateExpression("operator==(s1, s2)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "operator==(s1, s2) = false") +  +        test_result = frame.EvaluateExpression("operator==(s1, s3)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "true", "operator==(s1, s3) = true") + +        test_result = frame.EvaluateExpression("operator==(s2, s3)") +        self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "operator==(s2, s3) = false") diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/global_operators/main.cpp new file mode 100644 index 000000000000..a0dd0787fa32 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/main.cpp @@ -0,0 +1,16 @@ +struct Struct { +	int value; +}; + +bool operator==(const Struct &a, const Struct &b) { +	return a.value == b.value; +} + +int main() { +	Struct s1, s2, s3; +	s1.value = 3; +	s2.value = 5; +	s3.value = 3; +	return 0; // break here +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/Makefile new file mode 100644 index 000000000000..6595e33b7269 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/Makefile @@ -0,0 +1,35 @@ +LEVEL = ../../../make + +CXX_SOURCES = main.cpp length.cpp a.cpp + +CFLAGS_LIMIT = -c $(CXXFLAGS) +CFLAGS_NO_LIMIT = -c $(CXXFLAGS) + +ifneq (,$(findstring clang,$(CC))) +  CFLAGS_LIMIT += -flimit-debug-info +  CFLAGS_NO_LIMIT += -fno-limit-debug-info +endif + +all: limit nolimit + +limit: main.o length_limit.o a.o +	$(CXX) $(LDFLAGS) main.o length_limit.o a.o -o limit + +nolimit: main.o length_nolimit.o a.o +	$(CXX) $(LDFLAGS) main.o length_nolimit.o a.o -o nolimit + +main.o: main.cpp +	$(CXX) $(CFLAGS_LIMIT) main.cpp -o main.o + +length_limit.o: length.cpp +	$(CXX) $(CFLAGS_LIMIT) length.cpp -o length_limit.o + +length_nolimit.o: length.cpp +	$(CXX) $(CFLAGS_NO_LIMIT) length.cpp -o length_nolimit.o + +a.o: a.cpp +	$(CXX) $(CFLAGS_NO_DEBUG) -c a.cpp -o a.o + +clean: OBJECTS += limit nolimit length_limit.o length_nolimit.o length_limit.dwo length_nolimit.dwo + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py new file mode 100644 index 000000000000..324f476efb9b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py @@ -0,0 +1,66 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCppIncompleteTypes(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureFreeBSD("llvm.org/pr25626 test executable not built correctly on FreeBSD") +    @skipIfGcc +    def test_limit_debug_info(self): +        self.build() +        frame = self.get_test_frame('limit') + +        value_f = frame.EvaluateExpression("f") +        self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object") +        self.assertTrue(value_f.GetError().Success(), "'expr f' is successful") + +        value_a = frame.EvaluateExpression("a") +        self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object") +        self.assertTrue(value_a.GetError().Success(), "'expr a' is successful") + +    @skipIfGcc +    @skipIfWindows # Clang on Windows asserts in external record layout in this case. +    def test_partial_limit_debug_info(self): +        self.build() +        frame = self.get_test_frame('nolimit') + +        value_f = frame.EvaluateExpression("f") +        self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object") +        self.assertTrue(value_f.GetError().Success(), "'expr f' is successful") + +        value_a = frame.EvaluateExpression("a") +        self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object") +        self.assertTrue(value_a.GetError().Success(), "'expr a' is successful") + +    def get_test_frame(self, exe): +        # Get main source file +        src_file = "main.cpp" +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "Main source file") + +        # Get the path of the executable +        cwd = os.getcwd() +        exe_path  = os.path.join(cwd, exe) + +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        main_breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec) +        self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        args = None +        env = None +        process = target.LaunchSimple(args, env, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Get frame for current thread +        return thread.GetSelectedFrame() diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.cpp b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.cpp new file mode 100644 index 000000000000..36b374be6f33 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.cpp @@ -0,0 +1,10 @@ + +#include "a.h" + +A::A () { } + +int +A::length () +{ +  return 123; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.h b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.h new file mode 100644 index 000000000000..13e9496e3fd7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/a.h @@ -0,0 +1,11 @@ +#ifndef __A_H__ +#define __A_H__ + +class A +{ +public: +  A(); +  virtual int length(); +}; + +#endif diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.cpp b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.cpp new file mode 100644 index 000000000000..90a3b640f732 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.cpp @@ -0,0 +1,8 @@ + +#include "length.h" + +int +length (A &a) +{ +  return a.length(); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.h b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.h new file mode 100644 index 000000000000..96df4f021808 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/length.h @@ -0,0 +1,8 @@ +#ifndef __LENGTH_H__ +#define __LENGTH_H__ + +#include "a.h" + +int length (A &a); + +#endif diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/main.cpp new file mode 100644 index 000000000000..ad324c905818 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/main.cpp @@ -0,0 +1,18 @@ + +#include "length.h" + +class Foo { +public: +    A a; +}; + +class MyA : public A { +}; + +int main() +{ +    Foo f; +    MyA a; + +    return length(a); // break here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/Makefile b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/Makefile new file mode 100644 index 000000000000..b9a3d3fe1c81 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES = main.cpp derived.cpp base.cpp + +CFLAGS_EXTRAS += $(LIMIT_DEBUG_INFO_FLAGS) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py new file mode 100644 index 000000000000..ec26f9efe907 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py @@ -0,0 +1,48 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestWithLimitDebugInfo(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipIf(debug_info=not_in(["dwarf"])) +    def test_limit_debug_info(self): +        self.build() + +        cwd = os.getcwd() + +        src_file = os.path.join(cwd, "main.cpp") +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "breakpoint file") + +        # Get the path of the executable +        exe_path  = os.path.join(cwd, 'a.out') + +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec) +        self.assertTrue(breakpoint.IsValid() and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        process = target.LaunchSimple(None, None, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) +        thread.StepInto() + +        # Get frame for current thread +        frame = thread.GetSelectedFrame() + +        v1 = frame.EvaluateExpression("1") +        self.assertTrue(v1.IsValid(), "'expr 1' results in a valid SBValue object") +        self.assertTrue(v1.GetError().Success(), "'expr 1' succeeds without an error.") + +        v2 = frame.EvaluateExpression("this") +        self.assertTrue(v2.IsValid(), "'expr this' results in a valid SBValue object") +        self.assertTrue(v2.GetError().Success(), "'expr this' succeeds without an error.") diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.cpp b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.cpp new file mode 100644 index 000000000000..4023bdbc64af --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.cpp @@ -0,0 +1,6 @@ +#include "base.h" + +void FooNS::bar() { +    x = 54321; +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.h b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.h new file mode 100644 index 000000000000..d3a09572bd25 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/base.h @@ -0,0 +1,10 @@ +class FooNS +{ +public: +    virtual void bar(); +    virtual char baz() = 0; + +protected: +    int x; +}; + diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.cpp b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.cpp new file mode 100644 index 000000000000..9d773593eb51 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.cpp @@ -0,0 +1,6 @@ +#include "derived.h" + +char Foo::baz() { +    return (char)(x&0xff); +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.h b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.h new file mode 100644 index 000000000000..46b3f83b9f74 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/derived.h @@ -0,0 +1,13 @@ +#include "base.h" + +class Foo : public FooNS +{ +public: +    Foo() { +        a = 12345; +    } + +    char baz() override; +    int a; +}; + diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/main.cpp new file mode 100644 index 000000000000..64e0349b5826 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/main.cpp @@ -0,0 +1,7 @@ +#include "derived.h" + +int main() { +    Foo f; // break here +    f.bar(); +    return f.baz(); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/Makefile b/packages/Python/lldbsuite/test/lang/cpp/namespace/Makefile new file mode 100644 index 000000000000..7dd5eb4c11f1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp ns.cpp ns2.cpp ns3.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py new file mode 100644 index 000000000000..a60d8252e9f0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py @@ -0,0 +1,125 @@ +""" +Test the printing of anonymous and named namespace variables. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class NamespaceTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers for declarations of namespace variables i and j. +        self.line_var_i = line_number('main.cpp', +                '// Find the line number for anonymous namespace variable i.') +        self.line_var_j = line_number('main.cpp', +                '// Find the line number for named namespace variable j.') +        # And the line number to break at. +        self.line_break = line_number('main.cpp', +                '// Set break point at this line.') +        # Break inside do {} while and evaluate value +        self.line_break_ns1 = line_number('main.cpp', '// Evaluate ns1::value') +        self.line_break_ns2 = line_number('main.cpp', '// Evaluate ns2::value') + +    def runToBkpt(self, command): +        self.runCmd(command, RUN_SUCCEEDED) +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +    # rdar://problem/8668674 +    @expectedFailureWindows("llvm.org/pr24764") +    def test_with_run_command(self): +        """Test that anonymous and named namespace variables display correctly.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line_break_ns1, num_expected_locations=1, loc_exact=True) +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line_break_ns2, num_expected_locations=1, loc_exact=True) +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line_break, num_expected_locations=1, loc_exact=True) + +        self.runToBkpt("run") +        # Evaluate ns1::value +        self.expect("expression -- value", startstr = "(int) $0 = 100") + +        self.runToBkpt("continue") +        # Evaluate ns2::value +        self.expect("expression -- value", startstr = "(int) $1 = 200") +         +        self.runToBkpt("continue") +        # On Mac OS X, gcc 4.2 emits the wrong debug info with respect to types. +        slist = ['(int) a = 12', 'anon_uint', 'a_uint', 'b_uint', 'y_uint'] +        if self.platformIsDarwin() and self.getCompiler() in ['clang', 'llvm-gcc']: +            slist = ['(int) a = 12', +                     '::my_uint_t', 'anon_uint = 0', +                     '(A::uint_t) a_uint = 1', +                     '(A::B::uint_t) b_uint = 2', +                     '(Y::uint_t) y_uint = 3'] + +        # 'frame variable' displays the local variables with type information. +        self.expect('frame variable', VARIABLES_DISPLAYED_CORRECTLY, +            substrs = slist) + +        # 'frame variable' with basename 'i' should work. +        self.expect("frame variable --show-declaration --show-globals i", +            startstr = "main.cpp:%d: (int) (anonymous namespace)::i = 3" % self.line_var_i) +        # main.cpp:12: (int) (anonymous namespace)::i = 3 + +        # 'frame variable' with basename 'j' should work, too. +        self.expect("frame variable --show-declaration --show-globals j", +            startstr = "main.cpp:%d: (int) A::B::j = 4" % self.line_var_j) +        # main.cpp:19: (int) A::B::j = 4 + +        # 'frame variable' should support address-of operator. +        self.runCmd("frame variable &i") + +        # 'frame variable' with fully qualified name 'A::B::j' should work. +        self.expect("frame variable A::B::j", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = '(int) A::B::j = 4', +            patterns = [' = 4']) + +        # So should the anonymous namespace case. +        self.expect("frame variable '(anonymous namespace)::i'", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = '(int) (anonymous namespace)::i = 3', +            patterns = [' = 3']) + +        # rdar://problem/8660275 +        # test/namespace: 'expression -- i+j' not working +        # This has been fixed. +        self.expect("expression -- i + j", +            startstr = "(int) $2 = 7") +        # (int) $2 = 7 + +        self.runCmd("expression -- i") +        self.runCmd("expression -- j") + +        # rdar://problem/8668674 +        # expression command with fully qualified namespace for a variable does not work +        self.expect("expression -- ::i", VARIABLES_DISPLAYED_CORRECTLY, +            patterns = [' = 3']) +        self.expect("expression -- A::B::j", VARIABLES_DISPLAYED_CORRECTLY, +            patterns = [' = 4']) + +        # expression command with function in anonymous namespace +        self.expect("expression -- myanonfunc(3)", +            patterns = [' = 6']) + +        # global namespace qualification with function in anonymous namespace +        self.expect("expression -- ::myanonfunc(4)", +            patterns = [' = 8']) + +        self.expect("p myanonfunc", +            patterns = ['\(anonymous namespace\)::myanonfunc\(int\)']) + +        self.expect("p variadic_sum", +            patterns = ['\(anonymous namespace\)::variadic_sum\(int, ...\)']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py new file mode 100644 index 000000000000..4cad45564c87 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py @@ -0,0 +1,223 @@ +""" +Test the printing of anonymous and named namespace variables. +""" + +from __future__ import print_function + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class NamespaceLookupTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Break inside different scopes and evaluate value +        self.line_break_global_scope = line_number('ns.cpp', '// BP_global_scope') +        self.line_break_file_scope = line_number('ns2.cpp', '// BP_file_scope') +        self.line_break_ns_scope = line_number('ns2.cpp', '// BP_ns_scope') +        self.line_break_nested_ns_scope = line_number('ns2.cpp', '// BP_nested_ns_scope') +        self.line_break_nested_ns_scope_after_using = line_number('ns2.cpp', '// BP_nested_ns_scope_after_using') +        self.line_break_before_using_directive = line_number('ns3.cpp', '// BP_before_using_directive') +        self.line_break_after_using_directive = line_number('ns3.cpp', '// BP_after_using_directive') + +    def runToBkpt(self, command): +        self.runCmd(command, RUN_SUCCEEDED) +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +    @expectedFailureFreeBSD("llvm.org/pr25819") +    @expectedFailureLinux("llvm.org/pr25819") +    def test_scope_lookup_with_run_command(self): +        """Test scope lookup of functions in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns.cpp", self.line_break_global_scope, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_ns_scope, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_nested_ns_scope, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_nested_ns_scope_after_using, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns3.cpp", self.line_break_before_using_directive, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns3.cpp", self.line_break_after_using_directive, num_expected_locations=1, loc_exact=False) + +        # Run to BP_global_scope at global scope +        self.runToBkpt("run") +        # Evaluate func() - should call ::func() +        self.expect("expr -- func()", startstr = "(int) $0 = 1") +        # Evaluate A::B::func() - should call A::B::func() +        self.expect("expr -- A::B::func()", startstr = "(int) $1 = 4") +        # Evaluate func(10) - should call ::func(int) +        self.expect("expr -- func(10)", startstr = "(int) $2 = 11") +        # Evaluate ::func() - should call A::func() +        self.expect("expr -- ::func()", startstr = "(int) $3 = 1") +        # Evaluate A::foo() - should call A::foo() +        self.expect("expr -- A::foo()", startstr = "(int) $4 = 42") + +        # Continue to BP_ns_scope at ns scope +        self.runToBkpt("continue") +        # Evaluate func(10) - should call A::func(int) +        self.expect("expr -- func(10)", startstr = "(int) $5 = 13") +        # Evaluate B::func() - should call B::func() +        self.expect("expr -- B::func()", startstr = "(int) $6 = 4") +        # Evaluate func() - should call A::func() +        self.expect("expr -- func()", startstr = "(int) $7 = 3") + +        # Continue to BP_nested_ns_scope at nested ns scope +        self.runToBkpt("continue") +        # Evaluate func() - should call A::B::func() +        self.expect("expr -- func()", startstr = "(int) $8 = 4") +        # Evaluate A::func() - should call A::func() +        self.expect("expr -- A::func()", startstr = "(int) $9 = 3") + +        # Evaluate func(10) - should call A::func(10) +        # NOTE: Under the rules of C++, this test would normally get an error +        # because A::B::func() hides A::func(), but lldb intentionally +        # disobeys these rules so that the intended overload can be found +        # by only removing duplicates if they have the same type. +        self.expect("expr -- func(10)", startstr = "(int) $10 = 13") + +        # Continue to BP_nested_ns_scope_after_using at nested ns scope after using declaration +        self.runToBkpt("continue") +        # Evaluate A::func(10) - should call A::func(int) +        self.expect("expr -- A::func(10)", startstr = "(int) $11 = 13") + +        # Continue to BP_before_using_directive at global scope before using declaration +        self.runToBkpt("continue") +        # Evaluate ::func() - should call ::func() +        self.expect("expr -- ::func()", startstr = "(int) $12 = 1") +        # Evaluate B::func() - should call B::func() +        self.expect("expr -- B::func()", startstr = "(int) $13 = 4") + +        # Continue to BP_after_using_directive at global scope after using declaration +        self.runToBkpt("continue") +        # Evaluate ::func() - should call ::func() +        self.expect("expr -- ::func()", startstr = "(int) $14 = 1") +        # Evaluate B::func() - should call B::func() +        self.expect("expr -- B::func()", startstr = "(int) $15 = 4") + +    @unittest2.expectedFailure("lldb scope lookup of functions bugs") +    def test_function_scope_lookup_with_run_command(self): +        """Test scope lookup of functions in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns.cpp", self.line_break_global_scope, num_expected_locations=1, loc_exact=False) +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_ns_scope, num_expected_locations=1, loc_exact=False) + +        # Run to BP_global_scope at global scope +        self.runToBkpt("run") +        # Evaluate foo() - should call ::foo() +        # FIXME: lldb finds Y::foo because lookup for variables is done +        # before functions. +        self.expect("expr -- foo()", startstr = "(int) $0 = 42") +        # Evaluate ::foo() - should call ::foo() +        # FIXME: lldb finds Y::foo because lookup for variables is done +        # before functions and :: is ignored. +        self.expect("expr -- ::foo()", startstr = "(int) $1 = 42") + +        # Continue to BP_ns_scope at ns scope +        self.runToBkpt("continue") +        # Evaluate foo() - should call A::foo() +        # FIXME: lldb finds Y::foo because lookup for variables is done +        # before functions. +        self.expect("expr -- foo()", startstr = "(int) $2 = 42") + +    @unittest2.expectedFailure("lldb file scope lookup bugs") +    def test_file_scope_lookup_with_run_command(self): +        """Test file scope lookup in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_file_scope, num_expected_locations=1, loc_exact=False) + +        # Run to BP_file_scope at file scope +        self.runToBkpt("run") +        # Evaluate func() - should call static ns2.cpp:func() +        # FIXME: This test fails because lldb doesn't know about file scopes so +        # finds the global ::func(). +        self.expect("expr -- func()", startstr = "(int) $0 = 2") + +    @expectedFailureLinux("llvm.org/pr25819") +    def test_scope_lookup_before_using_with_run_command(self): +        """Test scope lookup before using in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns3.cpp", self.line_break_before_using_directive, num_expected_locations=1, loc_exact=False) + +        # Run to BP_before_using_directive at global scope before using declaration +        self.runToBkpt("run") +        # Evaluate func() - should call ::func() +        self.expect("expr -- func()", startstr = "(int) $0 = 1") + +    # NOTE: this test may fail on older systems that don't emit import +    # emtries in DWARF - may need to add checks for compiler versions here. +    @expectedFailureFreeBSD("llvm.org/pr25819") +    @expectedFailureLinux("llvm.org/pr25819") +    def test_scope_after_using_directive_lookup_with_run_command(self): +        """Test scope lookup after using directive in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns3.cpp", self.line_break_after_using_directive, num_expected_locations=1, loc_exact=False) + +        # Run to BP_after_using_directive at global scope after using declaration +        self.runToBkpt("run") +        # Evaluate func2() - should call A::func2() +        self.expect("expr -- func2()", startstr = "(int) $0 = 3") + +    @unittest2.expectedFailure("lldb scope lookup after using declaration bugs") +    # NOTE: this test may fail on older systems that don't emit import +    # emtries in DWARF - may need to add checks for compiler versions here. +    def test_scope_after_using_declaration_lookup_with_run_command(self): +        """Test scope lookup after using declaration in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_nested_ns_scope_after_using, num_expected_locations=1, loc_exact=False) + +        # Run to BP_nested_ns_scope_after_using at nested ns scope after using declaration +        self.runToBkpt("run") +        # Evaluate func() - should call A::func() +        self.expect("expr -- func()", startstr = "(int) $0 = 3") + +    @unittest2.expectedFailure("lldb scope lookup ambiguity after using bugs") +    def test_scope_ambiguity_after_using_lookup_with_run_command(self): +        """Test scope lookup ambiguity after using in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns3.cpp", self.line_break_after_using_directive, num_expected_locations=1, loc_exact=False) + +        # Run to BP_after_using_directive at global scope after using declaration +        self.runToBkpt("run") +        # Evaluate func() - should get error: ambiguous +        # FIXME: This test fails because lldb removes duplicates if they have +        # the same type. +        self.expect("expr -- func()", startstr = "error") + +    @expectedFailureFreeBSD("llvm.org/pr25819") +    @expectedFailureLinux("llvm.org/pr25819") +    def test_scope_lookup_shadowed_by_using_with_run_command(self): +        """Test scope lookup shadowed by using in lldb.""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "ns2.cpp", self.line_break_nested_ns_scope, num_expected_locations=1, loc_exact=False) + +        # Run to BP_nested_ns_scope at nested ns scope +        self.runToBkpt("run") +        # Evaluate func(10) - should call A::func(10) +        # NOTE: Under the rules of C++, this test would normally get an error +        # because A::B::func() shadows A::func(), but lldb intentionally +        # disobeys these rules so that the intended overload can be found +        # by only removing duplicates if they have the same type. +        self.expect("expr -- func(10)", startstr = "(int) $0 = 13") + diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/cmds.txt b/packages/Python/lldbsuite/test/lang/cpp/namespace/cmds.txt new file mode 100644 index 000000000000..76bb1bcba759 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/cmds.txt @@ -0,0 +1,3 @@ +b main.cpp:54 +c +var diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace/main.cpp new file mode 100644 index 000000000000..560ec40f4733 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/main.cpp @@ -0,0 +1,124 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstdarg> +#include "ns.h" + +namespace { +    typedef unsigned int my_uint_t; +    int i; // Find the line number for anonymous namespace variable i. + +    int myanonfunc (int a) +    { +        return a + a; +    } + +    int +    variadic_sum (int arg_count...) +    { +        int sum = 0; +        va_list args; +        va_start(args, arg_count); + +        for (int i = 0; i < arg_count; i++) +            sum += va_arg(args, int); + +        va_end(args); +        return sum; +    } +} + +namespace A { +    typedef unsigned int uint_t; +    namespace B { +        typedef unsigned int uint_t; +        int j; // Find the line number for named namespace variable j. +        int myfunc (int a); +        int myfunc2(int a) +        { +             return a + 2; +        } +        float myfunc (float f) +        { +            return f - 2.0; +        } +    } +} + +namespace Y +{ +    typedef unsigned int uint_t; +    using A::B::j; +    int foo; +} + +using A::B::j;          // using declaration + +namespace Foo = A::B;   // namespace alias + +using Foo::myfunc;      // using declaration + +using namespace Foo;    // using directive + +namespace A { +    namespace B { +        using namespace Y; +        int k; +    } +} + +namespace ns1 { +    int value = 100; +} + +namespace ns2 { +    int value = 200; +} + +void test_namespace_scopes() { +    do { +        using namespace ns1; +        printf("ns1::value = %d\n", value); // Evaluate ns1::value +    } while(0); +     +    do { +        using namespace ns2; +        printf("ns2::value = %d\n", value); // Evaluate ns2::value +    } while(0); +} + +int Foo::myfunc(int a) +{ +    test_namespace_scopes();     + +    ::my_uint_t anon_uint = 0; +    A::uint_t a_uint = 1; +    B::uint_t b_uint = 2; +    Y::uint_t y_uint = 3; +    i = 3; +    j = 4; +    printf("::i=%d\n", ::i); +    printf("A::B::j=%d\n", A::B::j); +    printf("variadic_sum=%d\n", variadic_sum(3, 1, 2, 3)); +    myanonfunc(3); +    return myfunc2(3) + j + i + a + 2 + anon_uint + a_uint + b_uint + y_uint; // Set break point at this line. +} + +int +main (int argc, char const *argv[]) +{ +    test_lookup_at_global_scope(); +    test_lookup_at_file_scope(); +    A::test_lookup_at_ns_scope(); +    A::B::test_lookup_at_nested_ns_scope(); +    A::B::test_lookup_at_nested_ns_scope_after_using(); +    test_lookup_before_using_directive(); +    test_lookup_after_using_directive(); +    return Foo::myfunc(12); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.cpp new file mode 100644 index 000000000000..9e5637d02b4b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.cpp @@ -0,0 +1,32 @@ +//===-- ns.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ns.h" + +int foo() +{ +    printf("global foo()\n"); +    return 42; +} +int func() +{ +    printf("global func()\n"); +    return 1; +} +int func(int a) +{ +    printf("global func(int)\n"); +    return a + 1; +} +void test_lookup_at_global_scope() +{ +    // BP_global_scope +    printf("at global scope: foo() = %d\n", foo()); // eval foo(), exp: 42 +    printf("at global scope: func() = %d\n", func()); // eval func(), exp: 1 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.h b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.h new file mode 100644 index 000000000000..a07b600efa30 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns.h @@ -0,0 +1,36 @@ +//===-- ns.h ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +void test_lookup_at_global_scope(); +void test_lookup_at_file_scope(); +void test_lookup_before_using_directive(); +void test_lookup_after_using_directive(); +int func(int a); +namespace A { +    int foo(); +    int func(int a); +    inline int func() +    { +        printf("A::func()\n"); +        return 3; +    } +    inline int func2() +    { +        printf("A::func2()\n"); +        return 3; +    } +    void test_lookup_at_ns_scope(); +    namespace B { +        int func(); +        void test_lookup_at_nested_ns_scope(); +        void test_lookup_at_nested_ns_scope_after_using(); +    } +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/ns2.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns2.cpp new file mode 100644 index 000000000000..04046ad9b7f4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns2.cpp @@ -0,0 +1,65 @@ +//===-- ns2.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ns.h" + +static int func() +{ +    printf("static m2.cpp func()\n"); +    return 2; +} +void test_lookup_at_file_scope() +{ +    // BP_file_scope +    printf("at file scope: func() = %d\n", func()); // eval func(), exp: 2 +    printf("at file scope: func(10) = %d\n", func(10)); // eval func(10), exp: 11 +} +namespace A { +    namespace B { +        int func() +        { +            printf("A::B::func()\n"); +            return 4; +        } +        void test_lookup_at_nested_ns_scope() +        { +            // BP_nested_ns_scope +            printf("at nested ns scope: func() = %d\n", func()); // eval func(), exp: 4 + +            //printf("func(10) = %d\n", func(10)); // eval func(10), exp: 13 +            // NOTE: Under the rules of C++, this test would normally get an error +            // because A::B::func() hides A::func(), but lldb intentionally +            // disobeys these rules so that the intended overload can be found +            // by only removing duplicates if they have the same type. +        } +        void test_lookup_at_nested_ns_scope_after_using() +        { +            // BP_nested_ns_scope_after_using +            using A::func; +            printf("at nested ns scope after using: func() = %d\n", func()); // eval func(), exp: 3 +        } +    } +} +int A::foo() +{ +    printf("A::foo()\n"); +    return 42; +} +int A::func(int a) +{ +    printf("A::func(int)\n"); +    return a + 3; +} +void A::test_lookup_at_ns_scope() +{ +    // BP_ns_scope +    printf("at nested ns scope: func() = %d\n", func()); // eval func(), exp: 3 +    printf("at nested ns scope: func(10) = %d\n", func(10)); // eval func(10), exp: 13 +    printf("at nested ns scope: foo() = %d\n", foo()); // eval foo(), exp: 42 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/ns3.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns3.cpp new file mode 100644 index 000000000000..10b0df784225 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/ns3.cpp @@ -0,0 +1,27 @@ +//===-- ns3.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ns.h" +extern int func(); + +// Note: the following function must be before the using. +void test_lookup_before_using_directive() +{ +    // BP_before_using_directive +    printf("before using directive: func() = %d\n", func()); // eval func(), exp: 1 +} +using namespace A; +void test_lookup_after_using_directive() +{ +    // BP_after_using_directive +    //printf("func() = %d\n", func()); // eval func(), exp: error, amiguous +    printf("after using directive: func2() = %d\n", func2()); // eval func2(), exp: 3 +    printf("after using directive: ::func() = %d\n", ::func()); // eval ::func(), exp: 1 +    printf("after using directive: B::func() = %d\n", B::func()); // eval B::func(), exp: 4 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/nsimport/Makefile b/packages/Python/lldbsuite/test/lang/cpp/nsimport/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/nsimport/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py b/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py new file mode 100644 index 000000000000..97e9e27a6e98 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py @@ -0,0 +1,101 @@ +""" +Tests imported namespaces in C++. +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCppNsImport(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureFreeBSD("llvm.org/pr25925") +    @expectedFailureGcc(None, ['>=', '4.9']) +    def test_with_run_command(self): +        """Tests imported namespaces in C++.""" +        self.build() + +        # Get main source file +        src_file = "main.cpp" +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "Main source file") + +        # Get the path of the executable +        cwd = os.getcwd() +        exe_file = "a.out" +        exe_path  = os.path.join(cwd, exe_file) + +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        break_0 = target.BreakpointCreateBySourceRegex("// break 0", src_file_spec) +        self.assertTrue(break_0.IsValid() and break_0.GetNumLocations() >= 1, VALID_BREAKPOINT) +        break_1 = target.BreakpointCreateBySourceRegex("// break 1", src_file_spec) +        self.assertTrue(break_1.IsValid() and break_1.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        args = None +        env = None +        process = target.LaunchSimple(args, env, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Get current fream of the thread at the breakpoint +        frame = thread.GetSelectedFrame() + +        # Test imported namespaces +        test_result = frame.EvaluateExpression("n") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 1, "n = 1") + +        test_result = frame.EvaluateExpression("N::n") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 1, "N::n = 1") + +        test_result = frame.EvaluateExpression("nested") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 3, "nested = 3") + +        test_result = frame.EvaluateExpression("anon") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 2, "anon = 2") + +        test_result = frame.EvaluateExpression("global") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 4, "global = 4") + +        test_result = frame.EvaluateExpression("fun_var") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 9, "fun_var = 9") + +        test_result = frame.EvaluateExpression("Fun::fun_var") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 0, "Fun::fun_var = 0") + +        test_result = frame.EvaluateExpression("not_imported") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 35, "not_imported = 35") + +        # Currently there is no way to distinguish between "::imported" and "imported" in ClangExpressionDeclMap so this fails +        #test_result = frame.EvaluateExpression("::imported") +        #self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 89, "::imported = 89") + +        test_result = frame.EvaluateExpression("Imported::imported") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 99, "Imported::imported = 99") +         +        test_result = frame.EvaluateExpression("imported") +        self.assertTrue(test_result.IsValid() and test_result.GetError().Fail(), "imported is ambiguous") + +        test_result = frame.EvaluateExpression("single") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 3, "single = 3") + +        # Continue to second breakpoint +        process.Continue() + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Get current fream of the thread at the breakpoint +        frame = thread.GetSelectedFrame() + +        # Test function inside namespace +        test_result = frame.EvaluateExpression("fun_var") +        self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 5, "fun_var = 5") diff --git a/packages/Python/lldbsuite/test/lang/cpp/nsimport/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/nsimport/main.cpp new file mode 100644 index 000000000000..e125ebaa2430 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/nsimport/main.cpp @@ -0,0 +1,72 @@ +namespace N +{ +    int n; +} + +namespace +{ +    int anon; +} + +namespace Nested +{ +    namespace +    { +        int nested; +    } +} + +namespace Global +{ +    int global; +} + +namespace Fun +{ +    int fun_var; +    int fun() +    { +        fun_var = 5; +        return 0; // break 1 +    } +} + +namespace Single +{ +    int single = 3; +} + +namespace NotImportedBefore +{ +    int not_imported = 45; +} + +using namespace Global; + +int not_imported = 35; +int fun_var = 9; + +namespace NotImportedAfter +{ +    int not_imported = 55; +} + +namespace Imported +{ +    int imported = 99; +} + +int imported = 89; + +int main() +{ +    using namespace N; +    using namespace Nested; +    using namespace Imported; +    using Single::single; +    n = 1; +    anon = 2; +    nested = 3; +    global = 4; +    return Fun::fun(); // break 0 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/Makefile b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/Makefile new file mode 100644 index 000000000000..a8d5c4eb0268 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp static-a.cpp static-b.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py new file mode 100644 index 000000000000..d485dcd0f652 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py @@ -0,0 +1,36 @@ +""" +Tests that functions with the same name are resolved correctly. +""" + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPStaticMethodsTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    def setUp(self): +        TestBase.setUp(self) +        self.line = line_number('main.cpp', '// breakpoint') + +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_with_run_command(self): +        """Test that functions with the same name are resolved correctly""" +        self.build() +        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("process launch", 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("expression -- Dump(myB)", +                    startstr = "(int) $0 = 2") + +        self.expect("expression -- Static()", +                    startstr = "(int) $1 = 1") diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/main.cpp new file mode 100644 index 000000000000..250e2cd1d96c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/main.cpp @@ -0,0 +1,43 @@ +#include <stdio.h> + +struct A { +    int aa; +    char ab; +}; + +struct B { +    int ba; +    int bb; +}; + +struct C { +    int ca; +    int cb; +}; + +int Dump (A &a) +{ +    return 1; +} + +int Dump (B &b) +{ +    return 2; +} + +int Dump (C &c) +{ +    return 3; +} + +extern int CallStaticA(); +extern int CallStaticB(); + +int main() +{ +    A myA; +    B myB; +    C myC; + +    printf("%d\n", CallStaticA() + CallStaticB()); // breakpoint +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-a.cpp b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-a.cpp new file mode 100644 index 000000000000..7250fa4bed5e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-a.cpp @@ -0,0 +1,9 @@ +static int Static() +{ +  return 1; +} + +int CallStaticA() +{ +  return Static(); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-b.cpp b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-b.cpp new file mode 100644 index 000000000000..90a20f69e6db --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/static-b.cpp @@ -0,0 +1,9 @@ +static int Static() +{ +  return 1; +} + +int CallStaticB() +{ +  return Static(); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile new file mode 100644 index 000000000000..1476447db355 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS := -g -O0 -std=c++11 + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py new file mode 100644 index 000000000000..636a82b425da --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py @@ -0,0 +1,85 @@ +# coding=utf8 +""" +Test that the expression parser returns proper Unicode strings. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +# this test case fails because of rdar://12991846 +# the expression parser does not deal correctly with Unicode expressions +# e.g. +#(lldb) expr L"Hello" +#(const wchar_t [6]) $0 = { +#  [0] = \0\0\0\0 +#  [1] = \0\0\0\0 +#  [2] = \0\0\0\0 +#  [3] = \0\0\0\0 +#  [4] = H\0\0\0 +#  [5] = e\0\0\0 +#} + +class Rdar12991846TestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @unittest2.expectedFailure("rdar://18684408") +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_expr1(self): +        """Test that the expression parser returns proper Unicode strings.""" +        self.build() +        self.rdar12991846(expr=1) + +    @unittest2.expectedFailure("rdar://18684408") +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_expr2(self): +        """Test that the expression parser returns proper Unicode strings.""" +        self.build() +        self.rdar12991846(expr=2) + +    @unittest2.expectedFailure("rdar://18684408") +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_expr3(self): +        """Test that the expression parser returns proper Unicode strings.""" +        self.build() +        self.rdar12991846(expr=3) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.source = 'main.cpp' +        self.line = line_number(self.source, '// Set break point at this line.') + +    def rdar12991846(self, expr=None): +        """Test that the expression parser returns proper Unicode strings.""" +        if self.getArchitecture() in ['i386']: +            self.skipTest("Skipping because this test is known to crash on i386") + +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        # Break on the struct declration statement in main.cpp. +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        if not process: +            self.fail("SBTarget.Launch() failed") + +        if expr == 1: self.expect('expression L"hello"', substrs = ['hello']) + +        if expr == 2: self.expect('expression u"hello"', substrs = ['hello']) + +        if expr == 3: self.expect('expression U"hello"', substrs = ['hello']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp new file mode 100644 index 000000000000..fda951a78991 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp @@ -0,0 +1,21 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +int main (int argc, char const *argv[]) +{ +    auto cs16 = u"hello world ྒྙྐ"; +	auto cs32 = U"hello world ྒྙྐ"; +    char16_t *s16 = (char16_t *)u"ﺸﺵۻ"; +    char32_t *s32 = (char32_t *)U"ЕЙРГЖО"; +    s32 = nullptr; // Set break point at this line. +    s32 = (char32_t *)U"෴"; +    s16 = (char16_t *)u"色ハ匂ヘト散リヌルヲ"; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/Makefile b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/Makefile new file mode 100644 index 000000000000..3a1d8a579350 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +CXXFLAGS += -std=c++11 + +include $(LEVEL)/Makefile.rules
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py new file mode 100644 index 000000000000..d02c34ecb0fe --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py @@ -0,0 +1,49 @@ +""" +Tests that rvalue references are supported in C++ +""" + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class RvalueReferencesTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    #rdar://problem/11479676 +    @expectedFailureIcc("ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.") +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    def test_with_run_command(self): +        """Test that rvalues are supported in the C++ expression parser""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 1')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 2')) + +        self.runCmd("process launch", RUN_SUCCEEDED) + +        # Note that clang as of r187480 doesn't emit DW_TAG_const_type, unlike gcc 4.8.1 +        # With gcc 4.8.1, lldb reports the type as (int &&const) +        self.expect("frame variable i", +                    startstr = "(int &&", +                    substrs = ["i = 0x", "&i = 3"]) + +        self.expect("expression -- i", +                    startstr = "(int) ", +                    substrs = ["3"]) + +        self.expect("breakpoint delete 1") + +        self.runCmd("process continue") +         +        self.expect("expression -- foo(2)") + +        self.expect("expression -- int &&j = 3; foo(j)", +                    error = True) + +        self.expect("expression -- int &&k = 6; k", +                    startstr = "(int) $1 = 6") + +    def set_breakpoint(self, line): +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=1, loc_exact=True) diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/main.cpp new file mode 100644 index 000000000000..6da34c73f101 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/main.cpp @@ -0,0 +1,12 @@ +#include <stdio.h> + +void foo (int &&i) +{ +  printf("%d\n", i); // breakpoint 1 +} + +int main() +{ +  foo(3); +  return 0; // breakpoint 2 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/Makefile b/packages/Python/lldbsuite/test/lang/cpp/scope/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py new file mode 100644 index 000000000000..66d4a1591575 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py @@ -0,0 +1,67 @@ +""" +Test scopes in C++. +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestCppScopes(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @expectedFailureDarwin +    @expectedFailureWindows("llvm.org/pr24764") +    def test_with_run_command(self): +        self.build() + +        # Get main source file +        src_file = "main.cpp" +        src_file_spec = lldb.SBFileSpec(src_file) +        self.assertTrue(src_file_spec.IsValid(), "Main source file") + +        # Get the path of the executable +        cwd = os.getcwd() +        exe_file = "a.out" +        exe_path  = os.path.join(cwd, exe_file) + +        # Load the executable +        target = self.dbg.CreateTarget(exe_path) +        self.assertTrue(target.IsValid(), VALID_TARGET) + +        # Break on main function +        main_breakpoint = target.BreakpointCreateBySourceRegex("// break here", src_file_spec) +        self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + +        # Launch the process +        args = None +        env = None +        process = target.LaunchSimple(args, env, self.get_process_working_directory()) +        self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + +        # Get the thread of the process +        self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) +        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + +        # Get current fream of the thread at the breakpoint +        frame = thread.GetSelectedFrame() + +        # Test result for scopes of variables + +        global_variables = frame.GetVariables(True, True, True, False) +        global_variables_assert = { +            'A::a': 1111, +            'B::a': 2222, +            'C::a': 3333, +            '::a': 4444, +            'a': 4444 +        } + +        self.assertTrue(global_variables.GetSize() == 4, "target variable returns all variables") +        for variable in global_variables: +            name = variable.GetName() +            self.assertTrue(name in global_variables_assert, "target variable returns wrong variable " + name) + +        for name in global_variables_assert: +            value = frame.EvaluateExpression(name) +            assert_value = global_variables_assert[name] +            self.assertTrue(value.IsValid() and value.GetValueAsSigned() == assert_value, name + " = " + str(assert_value)) diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/scope/main.cpp new file mode 100644 index 000000000000..da5d7ed529d1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/main.cpp @@ -0,0 +1,25 @@ +class A { +public: +    static int a; +    int b; +}; + +class B { +public: +    static int a; +    int b; +}; + +struct C { +    static int a; +}; + +int A::a = 1111; +int B::a = 2222; +int C::a = 3333; +int a = 4444; + +int main() // break here +{ +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/signed_types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/signed_types/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/signed_types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py b/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py new file mode 100644 index 000000000000..51e6d4579e28 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py @@ -0,0 +1,60 @@ +""" +Test that variables with signed types display correctly. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class UnsignedTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.source = 'main.cpp' +        self.line = line_number(self.source, '// Set break point at this line.') + +    def test(self): +        """Test that variables with signed types display correctly.""" +        self.build() + +        # Run in synchronous mode +        self.dbg.SetAsync(False) + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        lldbutil.run_break_set_by_file_and_line (self, self.source, self.line, num_expected_locations=1, loc_exact=True) + +        # 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) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', 'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # Execute the assignment statement. +        self.runCmd("thread step-over") + +        # Test that signed types display correctly. +        self.expect("frame variable --show-types --no-args", VARIABLES_DISPLAYED_CORRECTLY, +            patterns = ["\((short int|short)\) the_signed_short = 99", +                       "\((signed char|char)\) the_signed_char = 'c'"], +            substrs = ["(int) the_signed_int = 99", +                       "(long) the_signed_long = 99", +                       "(long long) the_signed_long_long = 99"]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/signed_types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/signed_types/main.cpp new file mode 100644 index 000000000000..dbf3606aeba8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/signed_types/main.cpp @@ -0,0 +1,33 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +int main (int argc, char const *argv[]) +{ +    char the_char = 'c'; +    short the_short = 'c'; +    wchar_t the_wchar_t = 'c'; +    int the_int = 'c'; +    long the_long = 'c'; +    long long the_long_long = 'c'; + +    signed char the_signed_char = 'c'; +    signed short the_signed_short = 'c'; +    signed int the_signed_int = 'c'; +    signed long the_signed_long = 'c'; +    signed long long the_signed_long_long = 'c'; +    puts("");    // Set break point at this line. +    return  the_char        - the_signed_char + +            the_short       - the_signed_short + +            the_int         - the_signed_int + +            the_long        - the_signed_long + +            the_long_long   - the_signed_long_long; //// break $source:$line; c +    //// var the_int +    //// val -set 22 1 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_members/Makefile b/packages/Python/lldbsuite/test/lang/cpp/static_members/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_members/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py b/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py new file mode 100644 index 000000000000..1c41b1b6f571 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py @@ -0,0 +1,59 @@ +""" +Tests that C++ member and static variables have correct layout and scope. +""" + +from __future__ import print_function + + + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPStaticMembersTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    @unittest2.expectedFailure # llvm.org/pr15401 +    @expectedFailureWindows("llvm.org/pr21765") +    def test_with_run_command(self): +        """Test that member variables have the correct layout, scope and qualifiers when stopped inside and outside C++ methods""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 1')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 2')) + +        self.runCmd("process launch", RUN_SUCCEEDED) +        self.expect("expression my_a.access()", +                    startstr = "(long) $0 = 10") +         +        self.expect("expression my_a.m_a", +                    startstr = "(short) $1 = 1") +         +        # Note: SymbolFileDWARF::ParseChildMembers doesn't call AddFieldToRecordType, consistent with clang's AST layout. +        self.expect("expression my_a.s_d", +                    startstr = "(int) $2 = 4") +         +        self.expect("expression my_a.s_b", +                    startstr = "(long) $3 = 2") +         +        self.expect("expression A::s_b", +                    startstr = "(long) $4 = 2") + +        # should not be available in global scope  +        self.expect("expression s_d", +                    startstr = "error: use of undeclared identifier 's_d'") +         +        self.runCmd("process continue") +        self.expect("expression m_c", +                    startstr = "(char) $5 = \'\\x03\'") +         +        self.expect("expression s_b", +                    startstr = "(long) $6 = 2") + +        self.runCmd("process continue") + +    def set_breakpoint(self, line): +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=1, loc_exact=False) diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_members/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/static_members/main.cpp new file mode 100644 index 000000000000..7ccc2f9a328b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_members/main.cpp @@ -0,0 +1,36 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +struct A +{ +    short m_a; +    static long s_b; +    char m_c; +    static int s_d; + +    long access() { +        return m_a + s_b + m_c + s_d; // breakpoint 2 +    } +}; + +long A::s_b = 2; +int A::s_d = 4; + +int main() +{ +    A my_a; +    my_a.m_a = 1; +    my_a.m_c = 3; + +    my_a.access(); // breakpoint 1  +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/Makefile b/packages/Python/lldbsuite/test/lang/cpp/static_methods/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py new file mode 100644 index 000000000000..dba556431e39 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py @@ -0,0 +1,36 @@ +""" +Tests expressions that distinguish between static and non-static methods. +""" + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPStaticMethodsTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    def setUp(self): +        TestBase.setUp(self) +        self.line = line_number('main.cpp', '// Break at this line') + +    @expectedFailureWindows +    def test_with_run_command(self): +        """Test that static methods are properly distinguished from regular methods""" +        self.build() +        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("process launch", 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("expression -- A::getStaticValue()", +                    startstr = "(int) $0 = 5") + +        self.expect("expression -- my_a.getMemberValue()", +                    startstr = "(int) $1 = 3") diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/static_methods/main.cpp new file mode 100644 index 000000000000..5141a407d111 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +class A +{ +public: +  static int getStaticValue(); +  int getMemberValue(); +  int a; +}; + +int A::getStaticValue() +{ +  return 5; +}  + +int A::getMemberValue() +{ +  return a; +} + +int main() +{ +  A my_a; + +  my_a.a = 3; + +  printf("%d\n", A::getStaticValue()); // Break at this line +  printf("%d\n", my_a.getMemberValue()); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/Makefile b/packages/Python/lldbsuite/test/lang/cpp/stl/Makefile new file mode 100644 index 000000000000..f61a6300a994 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS := -g -O0 + +clean: OBJECTS+=$(wildcard main.d.*) + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD  +# targets.  Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) +  CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py new file mode 100644 index 000000000000..6dba1398947e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py @@ -0,0 +1,118 @@ +""" +Test some expressions involving STL data types. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class STLTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.source = 'main.cpp' +        self.line = line_number(self.source, '// Set break point at this line.') + +    # rdar://problem/10400981 +    @unittest2.expectedFailure +    def test(self): +        """Test some expressions involving STL data types.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # The following two lines, if uncommented, will enable loggings. +        #self.ci.HandleCommand("log enable -f /tmp/lldb.log lldb default", res) +        #self.assertTrue(res.Succeeded()) + +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # rdar://problem/8543077 +        # test/stl: clang built binaries results in the breakpoint locations = 3, +        # is this a problem with clang generated debug info? +        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) + +        # Stop at 'std::string hello_world ("Hello World!");'. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['main.cpp:%d' % self.line, +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # Now try some expressions.... + +        self.runCmd('expr for (int i = 0; i < hello_world.length(); ++i) { (void)printf("%c\\n", hello_world[i]); }') + +        # rdar://problem/10373783 +        # rdar://problem/10400981 +        self.expect('expr associative_array.size()', +            substrs = [' = 3']) +        self.expect('expr associative_array.count(hello_world)', +            substrs = [' = 1']) +        self.expect('expr associative_array[hello_world]', +            substrs = [' = 1']) +        self.expect('expr associative_array["hello"]', +            substrs = [' = 2']) + +    @expectedFailureIcc # icc 13.1 and 14-beta do not emit DW_TAG_template_type_parameter +    @add_test_categories(['pyapi']) +    def test_SBType_template_aspects(self): +        """Test APIs for getting template arguments from an SBType.""" +        self.build() +        exe = os.path.join(os.getcwd(), 'a.out') + +        # 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(self.source, self.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) + +        # Get the type for variable 'associative_array'. +        associative_array = frame0.FindVariable('associative_array') +        self.DebugSBValue(associative_array) +        self.assertTrue(associative_array, VALID_VARIABLE) +        map_type = associative_array.GetType() +        self.DebugSBType(map_type) +        self.assertTrue(map_type, VALID_TYPE) +        num_template_args = map_type.GetNumberOfTemplateArguments() +        self.assertTrue(num_template_args > 0) + +        # We expect the template arguments to contain at least 'string' and 'int'. +        expected_types = { 'string': False, 'int': False } +        for i in range(num_template_args): +            t = map_type.GetTemplateArgumentType(i) +            self.DebugSBType(t) +            self.assertTrue(t, VALID_TYPE) +            name = t.GetName() +            if 'string' in name: +                expected_types['string'] = True +            elif 'int' == name: +                expected_types['int'] = True + +        # Check that both entries of the dictionary have 'True' as the value. +        self.assertTrue(all(expected_types.values())) diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py new file mode 100644 index 000000000000..d7435c467274 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py @@ -0,0 +1,111 @@ +""" +Test the lldb disassemble command on lib stdc++. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class StdCXXDisassembleTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.cpp', '// Set break point at this line.') + +    # rdar://problem/8504895 +    # Crash while doing 'disassemble -n "-[NSNumber descriptionWithLocale:]" +    @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") +    def test_stdcxx_disasm(self): +        """Do 'disassemble' on each and every 'Code' symbol entry from the std c++ lib.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # rdar://problem/8543077 +        # test/stl: clang built binaries results in the breakpoint locations = 3, +        # is this a problem with clang generated debug info? +        # +        # Break on line 13 of main.cpp. +        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) + +        # Now let's get the target as well as the process objects. +        target = self.dbg.GetSelectedTarget() +        process = target.GetProcess() + +        # The process should be in a 'stopped' state. +        self.expect(str(process), STOPPED_DUE_TO_BREAKPOINT, exe=False, +            substrs = ["a.out", +                       "stopped"]) + +        # Disassemble the functions on the call stack. +        self.runCmd("thread backtrace") +        thread = process.GetThreadAtIndex(0) +        depth = thread.GetNumFrames() +        for i in range(depth - 1): +            frame = thread.GetFrameAtIndex(i) +            function = frame.GetFunction() +            if function.GetName(): +                self.runCmd("disassemble -n '%s'" % function.GetName()) + +        lib_stdcxx = "FAILHORRIBLYHERE" +        # Iterate through the available modules, looking for stdc++ library... +        for i in range(target.GetNumModules()): +            module = target.GetModuleAtIndex(i) +            fs = module.GetFileSpec() +            if (fs.GetFilename().startswith("libstdc++") or fs.GetFilename().startswith("libc++")): +                lib_stdcxx = str(fs) +                break + +        # At this point, lib_stdcxx is the full path to the stdc++ library and +        # module is the corresponding SBModule. + +        self.expect(lib_stdcxx, "Libraray StdC++ is located", exe=False, +            substrs = ["lib"]) + +        self.runCmd("image dump symtab '%s'" % lib_stdcxx) +        raw_output = self.res.GetOutput() +        # Now, look for every 'Code' symbol and feed its load address into the +        # command: 'disassemble -s load_address -e end_address', where the +        # end_address is taken from the next consecutive 'Code' symbol entry's +        # load address. +        # +        # The load address column comes after the file address column, with both +        # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits. +        codeRE = re.compile(r""" +                             \ Code\ {9}      # ' Code' followed by 9 SPCs, +                             0x[0-9a-f]{16}   # the file address column, and +                             \                # a SPC, and +                             (0x[0-9a-f]{16}) # the load address column, and +                             .*               # the rest. +                             """, re.VERBOSE) +        # Maintain a start address variable; if we arrive at a consecutive Code +        # entry, then the load address of the that entry is fed as the end +        # address to the 'disassemble -s SA -e LA' command. +        SA = None +        for line in raw_output.split(os.linesep): +            match = codeRE.search(line) +            if match: +                LA = match.group(1) +                if self.TraceOn(): +                    print("line:", line) +                    print("load address:", LA) +                    print("SA:", SA) +                if SA and LA: +                    if int(LA, 16) > int(SA, 16): +                        self.runCmd("disassemble -s %s -e %s" % (SA, LA)) +                SA = LA +            else: +                # This entry is not a Code entry.  Reset SA = None. +                SA = None diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/cmds.txt b/packages/Python/lldbsuite/test/lang/cpp/stl/cmds.txt new file mode 100644 index 000000000000..9c9c2e3db57b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/cmds.txt @@ -0,0 +1,3 @@ +b main.cpp:6 +continue +var diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp new file mode 100644 index 000000000000..cfdb7b2d3db5 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp @@ -0,0 +1,30 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <cstdio> +#include <iostream> +#include <string> +#include <map> +int main (int argc, char const *argv[]) +{ +    std::string hello_world ("Hello World!"); +    std::cout << hello_world << std::endl; +    std::cout << hello_world.length() << std::endl; +    std::cout << hello_world[11] << std::endl; + +    std::map<std::string, int> associative_array; +    std::cout << "size of upon construction associative_array: " << associative_array.size() << std::endl; +    associative_array[hello_world] = 1; +    associative_array["hello"] = 2; +    associative_array["world"] = 3; + +    std::cout << "size of associative_array: " << associative_array.size() << std::endl; +    printf("associative_array[\"hello\"]=%d\n", associative_array["hello"]); + +    printf("before returning....\n"); // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/this/Makefile b/packages/Python/lldbsuite/test/lang/cpp/this/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/this/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py b/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py new file mode 100644 index 000000000000..07cc2e8e9788 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py @@ -0,0 +1,53 @@ +""" +Tests that C++ member and static variables are available where they should be. +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CPPThisTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    #rdar://problem/9962849 +    @expectedFailureGcc # llvm.org/pr15439 The 'this' pointer isn't available during expression evaluation when stopped in an inlined member function. +    @expectedFailureIcc # ICC doesn't emit correct DWARF inline debug info for inlined member functions +    @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") +    @expectedFailureWindows("llvm.org/pr24490: We shouldn't be using platform-specific names like `getpid` in tests") +    @expectedFlakeyClang(bugnumber='llvm.org/pr23012', compiler_version=['>=','3.6']) # failed with totclang - clang3.7 +    def test_with_run_command(self): +        """Test that the appropriate member variables are available when stopped in C++ static, inline, and const methods""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 1')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 2')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 3')) +        self.set_breakpoint(line_number('main.cpp', '// breakpoint 4')) + +        self.runCmd("process launch", RUN_SUCCEEDED) + +        self.expect("expression -- m_a = 2", +                    startstr = "(int) $0 = 2") +         +        self.runCmd("process continue") +         +        # This would be disallowed if we enforced const.  But we don't. +        self.expect("expression -- m_a = 2", +                    startstr = "(int) $1 = 2") +         +        self.expect("expression -- (int)getpid(); m_a",  +                    startstr = "(int) $2 = 2") + +        self.runCmd("process continue") + +        self.expect("expression -- s_a", +                    startstr = "(int) $3 = 5") + +        self.runCmd("process continue") + +        self.expect("expression -- m_a", +                    startstr = "(int) $4 = 2") +     +    def set_breakpoint(self, line): +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=1, loc_exact=False) diff --git a/packages/Python/lldbsuite/test/lang/cpp/this/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/this/main.cpp new file mode 100644 index 000000000000..4448a5cadf57 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/this/main.cpp @@ -0,0 +1,53 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +template <class T> class A +{ +public: +  void accessMember(T a); +  T accessMemberConst() const; +  static int accessStaticMember(); + +  void accessMemberInline(T a) __attribute__ ((always_inline)) +  { +    m_a = a; // breakpoint 4 +  } + +  T m_a; +  static int s_a; +}; + +template <class T> int A<T>::s_a = 5; + +template <class T> void A<T>::accessMember(T a) +{ +  m_a = a; // breakpoint 1 +} + +template <class T> T A<T>::accessMemberConst() const +{ +  return m_a; // breakpoint 2 +} + +template <class T> int A<T>::accessStaticMember() +{ +  return s_a; // breakpoint 3 +}  + +int main() +{ +  A<int> my_a; + +  my_a.accessMember(3); +  my_a.accessMemberConst(); +  A<int>::accessStaticMember(); +  my_a.accessMemberInline(5); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/unique-types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/unique-types/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unique-types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/unique-types/TestUniqueTypes.py b/packages/Python/lldbsuite/test/lang/cpp/unique-types/TestUniqueTypes.py new file mode 100644 index 000000000000..2cbb1a191e68 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unique-types/TestUniqueTypes.py @@ -0,0 +1,62 @@ +""" +Test that template instaniations of std::vector<long> and <short> in the same module have the correct types. +""" + +from __future__ import print_function + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class UniqueTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number inside main.cpp. +        self.line = line_number("main.cpp", +          "// Set breakpoint here to verify that std::vector 'longs' and 'shorts' have unique types.") + +    def test(self): +        """Test for unique types of std::vector<long> and std::vector<short>.""" +        self.build() + +        compiler = self.getCompiler() +        compiler_basename = os.path.basename(compiler) +        if "clang" in compiler_basename and int(self.getCompilerVersion().split('.')[0]) < 3: +            self.skipTest("rdar://problem/9173060 lldb hangs while running unique-types for clang version < 3") + +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, 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']) + +        # Do a "frame variable --show-types longs" and verify "long" is in each line of output. +        self.runCmd("frame variable --show-types longs") +        output = self.res.GetOutput() +        for x in [line.strip() for line in output.split(os.linesep)]: +            # Skip empty line, closing brace, and messages about more variables than can be displayed. +            if not x or x == '}' or x == '...' or "Some of your variables have more members than the debugger will show by default" in x: +                continue +            self.expect(x, "Expect type 'long'", exe=False, +                substrs = ['long']) + +        # Do a "frame variable --show-types shorts" and verify "short" is in each line of output. +        self.runCmd("frame variable --show-types shorts") +        output = self.res.GetOutput() +        for x in [line.strip() for line in output.split(os.linesep)]: +            # Skip empty line, closing brace, and messages about more variables than can be displayed. +            if not x or x == '}' or x == '...' or "Some of your variables have more members than the debugger will show by default" in x: +                continue +            self.expect(x, "Expect type 'short'", exe=False, +                substrs = ['short']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/unique-types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/unique-types/main.cpp new file mode 100644 index 000000000000..c551c0e2c0d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unique-types/main.cpp @@ -0,0 +1,24 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <vector> + +#include <stdio.h> +#include <stdint.h> + +int main (int argc, char const *argv[], char const *envp[]) +{ +    std::vector<long> longs; +    std::vector<short> shorts;   +    for (int i=0; i<12; i++) +    { +        longs.push_back(i); +        shorts.push_back(i); +    } +    return 0; // Set breakpoint here to verify that std::vector 'longs' and 'shorts' have unique types. +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/Makefile b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py new file mode 100644 index 000000000000..c137592558ed --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py @@ -0,0 +1,54 @@ +""" +Test that variables with unsigned types display correctly. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class UnsignedTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.cpp', '// Set break point at this line.') + +    def test(self): +        """Test that variables with unsigned types display correctly.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # GCC puts a breakpoint on the last line of a multi-line expression, so +        # if GCC is the target compiler, we cannot rely on an exact line match. +        need_exact = "gcc" not in self.getCompiler() +        # Break on line 19 in main() aftre the variables are assigned values. +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=need_exact) + +        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']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # Test that unsigned types display correctly. +        self.expect("frame variable --show-types --no-args", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = "(unsigned char) the_unsigned_char = 'c'", +            patterns = ["\((short unsigned int|unsigned short)\) the_unsigned_short = 99"], +            substrs = ["(unsigned int) the_unsigned_int = 99", +                       "(unsigned long) the_unsigned_long = 99", +                       "(unsigned long long) the_unsigned_long_long = 99", +                       "(uint32_t) the_uint32 = 99"]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/main.cpp new file mode 100644 index 000000000000..b0d68377e983 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/main.cpp @@ -0,0 +1,22 @@ +//===-- 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 (int argc, char const *argv[]) +{ +    typedef unsigned int uint32_t; +    unsigned char the_unsigned_char = 'c'; +    unsigned short the_unsigned_short = 'c'; +    unsigned int the_unsigned_int = 'c'; +    unsigned long the_unsigned_long = 'c'; +    unsigned long long the_unsigned_long_long = 'c'; +    uint32_t the_uint32 = 'c'; + +    return  the_unsigned_char - the_unsigned_short + // Set break point at this line. +            the_unsigned_int - the_unsigned_long + +            the_unsigned_long_long - the_uint32; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/Makefile b/packages/Python/lldbsuite/test/lang/cpp/virtual/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py new file mode 100644 index 000000000000..1553a43e1a73 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py @@ -0,0 +1,90 @@ +""" +Test C++ virtual function and virtual inheritance. +""" + +from __future__ import print_function + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +def Msg(expr, val): +    return "'expression %s' matches the output (from compiled code): %s" % (expr, val) + +class CppVirtualMadness(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    # This is the pattern by design to match the "my_expr = 'value'" output from +    # printf() stmts (see main.cpp). +    pattern = re.compile("^([^=]*) = '([^=]*)'$") + +    # Assert message. +    PRINTF_OUTPUT_GROKKED = "The printf output from compiled code is parsed correctly" + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.source = 'main.cpp' +        self.line = line_number(self.source, '// Set first breakpoint here.') + +    @expectedFailureIcc('llvm.org/pr16808') # lldb does not call the correct virtual function with icc +    @expectedFailureAll(oslist=['windows']) +    def test_virtual_madness(self): +        """Test that expression works correctly with virtual inheritance as well as virtual function.""" +        self.build() + +        # Bring the program to the point where we can issue a series of +        # 'expression' command to compare against the golden output. +        self.dbg.SetAsync(False) +         +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        # Create the breakpoint inside function 'main'. +        breakpoint = target.BreakpointCreateByLocation(self.source, self.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) +         +        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") + +        # First, capture the golden output from the program itself from the +        # series of printf statements. +        stdout = process.GetSTDOUT(1024) +         +        self.assertIsNotNone(stdout, "Encountered an error reading the process's output") + +        # This golden list contains a list of "my_expr = 'value' pairs extracted +        # from the golden output. +        gl = [] + +        # Scan the golden output line by line, looking for the pattern: +        # +        #     my_expr = 'value' +        # +        for line in stdout.split(os.linesep): +            match = self.pattern.search(line) +            if match: +                my_expr, val = match.group(1), match.group(2) +                gl.append((my_expr, val)) +        #print("golden list:", gl) + +        # Now iterate through the golden list, comparing against the output from +        # 'expression var'. +        for my_expr, val in gl: + +            self.runCmd("expression %s" % my_expr) +            output = self.res.GetOutput() +             +            # The expression output must match the oracle. +            self.expect(output, Msg(my_expr, val), exe=False, +                substrs = [val]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp new file mode 100644 index 000000000000..bed1422dcbdd --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp @@ -0,0 +1,113 @@ +#include <stdio.h> +#include <stdint.h> + +class A +{ +public: +    A () : m_pad ('c') {} + +    virtual ~A () {} +     +    virtual const char * a() +    { +        return __PRETTY_FUNCTION__; +    } + +    virtual const char * b() +    { +        return __PRETTY_FUNCTION__; +    } + +    virtual const char * c() +    { +        return __PRETTY_FUNCTION__; +    } +protected: +    char m_pad; +}; + +class AA +{ +public: +    AA () : m_pad('A') {} +    virtual ~AA () {} + +    virtual const char * aa() +    { +        return __PRETTY_FUNCTION__; +    } +   +protected: +    char m_pad; +}; + +class B : virtual public A, public AA +{ +public: +    B () : m_pad ('c')  {} + +    virtual ~B () {} +     +    virtual const char * a() +    { +        return __PRETTY_FUNCTION__; +    } + +    virtual const char * b() +    { +        return __PRETTY_FUNCTION__; +    } +protected: +    char m_pad; +}; + +class C : public B, virtual public A +{ +public: +    C () : m_pad ('c') {} + +    virtual ~C () {} +     +    virtual const char * a() +    { +        return __PRETTY_FUNCTION__; +    } +protected: +    char m_pad; +}; + +int main (int argc, char const *argv[], char const *envp[]) +{ +    A *a_as_A = new A(); +    B *b_as_B = new B(); +    A *b_as_A = b_as_B; +    C *c_as_C = new C(); +    A *c_as_A = c_as_C; + +    printf ("a_as_A->a() = '%s'\n", a_as_A->a()); +    printf ("a_as_A->b() = '%s'\n", a_as_A->b()); +    printf ("a_as_A->c() = '%s'\n", a_as_A->c()); +    printf ("b_as_A->a() = '%s'\n", b_as_A->a()); +    printf ("b_as_A->b() = '%s'\n", b_as_A->b()); +    printf ("b_as_A->c() = '%s'\n", b_as_A->c()); +    printf ("b_as_B->aa() = '%s'\n", b_as_B->aa()); +    printf ("c_as_A->a() = '%s'\n", c_as_A->a()); +    printf ("c_as_A->b() = '%s'\n", c_as_A->b()); +    printf ("c_as_A->c() = '%s'\n", c_as_A->c()); +    printf ("c_as_C->aa() = '%s'\n", c_as_C->aa()); +    puts("");// Set first breakpoint here. +    // then evaluate: +    // expression a_as_A->a() +    // expression a_as_A->b() +    // expression a_as_A->c() +    // expression b_as_A->a() +    // expression b_as_A->b() +    // expression b_as_A->c() +    // expression b_as_B->aa() +    // expression c_as_A->a() +    // expression c_as_A->b() +    // expression c_as_A->c() +    // expression c_as_C->aa() +     +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/wchar_t/.categories b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/.categories new file mode 100644 index 000000000000..fe1da0247c62 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/.categories @@ -0,0 +1 @@ +dataformatters diff --git a/packages/Python/lldbsuite/test/lang/cpp/wchar_t/Makefile b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/Makefile new file mode 100644 index 000000000000..fe27980afe9b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS := -g -O0 + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/wchar_t/TestCxxWCharT.py b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/TestCxxWCharT.py new file mode 100644 index 000000000000..f9cdbca16e55 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/TestCxxWCharT.py @@ -0,0 +1,74 @@ +#coding=utf8 +""" +Test that C++ supports wchar_t correctly. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class CxxWCharTTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break for main.cpp. +        self.source = 'main.cpp' +        self.line = line_number(self.source, '// Set break point at this line.') + +    def test(self): +        """Test that C++ supports wchar_t correctly.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        # Break on the struct declration statement in main.cpp. +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        if not process: +            self.fail("SBTarget.Launch() failed") + +        # Check that we correctly report templates on wchar_t +        self.expect("frame variable foo_y", +            substrs = ['(Foo<wchar_t>) foo_y = ']) + +        # Check that we correctly report templates on int +        self.expect("frame variable foo_x", +            substrs = ['(Foo<int>) foo_x = ']) + +        # Check that we correctly report wchar_t +        self.expect("frame variable foo_y.object", +            substrs = ['(wchar_t) foo_y.object = ']) + +        # Check that we correctly report int +        self.expect("frame variable foo_x.object", +            substrs = ['(int) foo_x.object = ']) + +        # Check that we can run expressions that return wchar_t +        self.expect("expression L'a'",substrs = ['(wchar_t) $',"L'a'"]) + +        # Mazel Tov if this works! +        self.expect("frame variable mazeltov", +            substrs = ['(const wchar_t *) mazeltov = ','L"מזל טוב"']) + +        self.expect("frame variable ws_NULL",substrs = ['(wchar_t *) ws_NULL = 0x0']) +        self.expect("frame variable ws_empty",substrs = [' L""']) + +        self.expect("frame variable array",substrs = ['L"Hey, I\'m a super wchar_t string']) +        self.expect("frame variable array",substrs = ['[0]'], matching=False) +         +        self.expect('frame variable wchar_zero', substrs=["L'\\0'"]) +        self.expect('expression wchar_zero', substrs=["L'\\0'"]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/wchar_t/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/main.cpp new file mode 100644 index 000000000000..e249c37b678f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/wchar_t/main.cpp @@ -0,0 +1,35 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> + +template <typename T> +class Foo +{ +public: +    Foo () : object() {} +    Foo (T x) : object(x) {} +    T getObject() { return object; } +private: +    T object; +}; + + +int main (int argc, char const *argv[]) +{ +    Foo<int> foo_x('a'); +    Foo<wchar_t> foo_y(L'a'); +    const wchar_t *mazeltov = L"מזל טוב"; +    wchar_t *ws_NULL = nullptr; +    wchar_t *ws_empty = L""; +  	wchar_t array[200], * array_source = L"Hey, I'm a super wchar_t string, éõñž"; +    wchar_t wchar_zero = (wchar_t)0; +  	memcpy(array, array_source, 39 * sizeof(wchar_t)); +    return 0; // Set break point at this line. +}  | 
