217 lines · python
1"""2Tests const static data members as specified by C++11 [class.static.data]p3.3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbutil9 10 11class TestCase(TestBase):12 def test(self):13 self.build()14 lldbutil.run_to_source_breakpoint(15 self, "// break here", lldb.SBFileSpec("main.cpp")16 )17 18 # Test using a simple const static integer member.19 self.expect_expr("A::int_val", result_value="1")20 21 # Try accessing the int member via some expressions that still produce22 # an lvalue.23 self.expect_expr("a.int_val", result_value="1")24 self.expect_expr("(A::int_val)", result_value="1")25 self.expect_expr("+A::int_val", result_value="1")26 self.expect_expr("1,A::int_val", result_value="1")27 self.expect_expr("true ? A::int_val : A::int_val", result_value="1")28 29 # Test a simple integer member that was also defined in a namespace30 # scope and has an address.31 self.expect_expr("A::int_val_with_address", result_value="2")32 33 # Test a bool member.34 self.expect_expr("A::bool_val", result_value="true")35 36 # Test that minimum and maximum values for each data type are right.37 self.expect_expr("A::char_max == char_max", result_value="true")38 self.expect_expr("A::schar_max == schar_max", result_value="true")39 self.expect_expr("A::uchar_max == uchar_max", result_value="true")40 self.expect_expr("A::int_max == int_max", result_value="true")41 self.expect_expr("A::uint_max == uint_max", result_value="true")42 self.expect_expr("A::long_max == long_max", result_value="true")43 self.expect_expr("A::ulong_max == ulong_max", result_value="true")44 self.expect_expr("A::longlong_max == longlong_max", result_value="true")45 self.expect_expr("A::ulonglong_max == ulonglong_max", result_value="true")46 self.expect_expr("A::wchar_max == wchar_max", result_value="true")47 48 self.expect_expr("A::char_min == char_min", result_value="true")49 self.expect_expr("A::schar_min == schar_min", result_value="true")50 self.expect_expr("A::uchar_min == uchar_min", result_value="true")51 self.expect_expr("A::int_min == int_min", result_value="true")52 self.expect_expr("A::uint_min == uint_min", result_value="true")53 self.expect_expr("A::long_min == long_min", result_value="true")54 self.expect_expr("A::ulong_min == ulong_min", result_value="true")55 self.expect_expr("A::longlong_min == longlong_min", result_value="true")56 self.expect_expr("A::ulonglong_min == ulonglong_min", result_value="true")57 self.expect_expr("A::wchar_min == wchar_min", result_value="true")58 59 # Test an unscoped enum.60 self.expect_expr("A::enum_val", result_value="enum_case2")61 # Test an unscoped enum with bool as the underlying type.62 self.expect_expr("A::enum_bool_val", result_value="enum_bool_case1")63 64 # Test a scoped enum.65 self.expect_expr("A::scoped_enum_val", result_value="scoped_enum_case2")66 # Test an scoped enum with a value that isn't an enumerator.67 self.expect_expr(68 "A::not_enumerator_scoped_enum_val", result_value="scoped_enum_case1 | 0x4"69 )70 # This time with more than one enum value plus the extra.71 self.expect_expr(72 "A::not_enumerator_scoped_enum_val_2",73 result_value="scoped_enum_case1 | scoped_enum_case2 | 0x4",74 )75 76 # Test an enum with fixed underlying type.77 self.expect_expr("A::scoped_char_enum_val", result_value="case2")78 self.expect_expr("A::scoped_ll_enum_val_neg", result_value="case0")79 self.expect_expr("A::scoped_ll_enum_val", result_value="case2")80 81 # Test taking address.82 if lldbplatformutil.getPlatform() == "windows":83 # On Windows data members without the out-of-class definitions still have84 # valid adresses and the following expression works fine.85 self.expect_expr("const int *i = &A::int_val; *i", result_value="1")86 else:87 # On other platforms (Linux, macos) data members without the out-of-class88 # definitions don't have valid addresses and the following code produces89 # a linker error.90 self.expect(91 "expr const int *i = &A::int_val; *i",92 error=True,93 substrs=["Couldn't look up symbols:"],94 )95 96 # This should work on all platforms.97 self.expect_expr(98 "const int *i = &A::int_val_with_address; *i", result_value="2"99 )100 101 # Printing the whole type takes a slightly different code path. Check that102 # it does not crash.103 self.expect("image lookup -t A")104 105 # dsymutil strips the debug info for classes that only have const static106 # data members without locations.107 @expectedFailureAll(debug_info=["dsym"], dwarf_version=["<", "5"])108 def test_class_with_only_const_static(self):109 self.build()110 lldbutil.run_to_source_breakpoint(111 self, "// break here", lldb.SBFileSpec("main.cpp")112 )113 114 self.expect_expr("ClassWithOnlyConstStatic::member", result_value="3")115 116 def check_global_var(self, name: str, expect_type, expect_val):117 var_list = self.target().FindGlobalVariables(name, lldb.UINT32_MAX)118 self.assertGreaterEqual(len(var_list), 1)119 varobj = var_list[0]120 self.assertEqual(varobj.type.name, expect_type)121 self.assertEqual(varobj.value, expect_val)122 123 def check_inline_static_members(self, flags):124 self.build(dictionary={"CXXFLAGS_EXTRAS": flags})125 lldbutil.run_to_source_breakpoint(126 self, "// break here", lldb.SBFileSpec("main.cpp")127 )128 129 self.check_global_var("A::int_val", "const int", "1")130 self.check_global_var("A::int_val_with_address", "const int", "2")131 self.check_global_var("A::inline_int_val", "const int", "3")132 self.check_global_var("A::bool_val", "const bool", "true")133 self.check_global_var("A::enum_val", "Enum", "enum_case2")134 self.check_global_var("A::enum_bool_val", "EnumBool", "enum_bool_case1")135 self.check_global_var("A::scoped_enum_val", "ScopedEnum", "scoped_enum_case2")136 137 self.check_global_var("ClassWithOnlyConstStatic::member", "const int", "3")138 139 self.check_global_var("ClassWithConstexprs::member", "const int", "2")140 self.check_global_var("ClassWithConstexprs::enum_val", "Enum", "enum_case2")141 self.check_global_var(142 "ClassWithConstexprs::scoped_enum_val", "ScopedEnum", "scoped_enum_case2"143 )144 145 # Fails on Windows for unknown reasons.146 @skipIfWindows147 # On linux this passes due to the manual index148 @expectedFailureDarwin(debug_info=no_match(["dsym"]))149 @skipIf(debug_info=["dsym"], compiler=["clang"], compiler_version=["<", "19.0"])150 def test_inline_static_members_dwarf5(self):151 self.check_inline_static_members("-gdwarf-5")152 153 # On linux this passes due to the manual index154 @expectedFailureDarwin155 def test_inline_static_members_dwarf4(self):156 self.check_inline_static_members("-gdwarf-4")157 158 # With older versions of Clang, LLDB fails to evaluate classes with only159 # constexpr members when dsymutil is enabled160 @expectedFailureAll(161 debug_info=["dsym"], compiler=["clang"], compiler_version=["<", "14.0"]162 )163 def test_class_with_only_constexpr_static(self):164 self.build()165 lldbutil.run_to_source_breakpoint(166 self, "// break here", lldb.SBFileSpec("main.cpp")167 )168 169 # Test `constexpr static`.170 self.expect_expr("ClassWithConstexprs::member", result_value="2")171 self.expect_expr("ClassWithConstexprs::enum_val", result_value="enum_case2")172 self.expect_expr(173 "ClassWithConstexprs::scoped_enum_val", result_value="scoped_enum_case2"174 )175 176 # Test an aliased enum with fixed underlying type.177 self.expect_expr(178 "ClassWithEnumAlias::enum_alias", result_value="scoped_enum_case2"179 )180 self.expect_expr(181 "ClassWithEnumAlias::enum_alias_alias", result_value="scoped_enum_case1"182 )183 184 def check_shadowed_static_inline_members(self, flags):185 """Tests that the expression evaluator and SBAPI can both186 correctly determine the requested inline static variable187 in the presence of multiple variables of the same name."""188 189 self.build(dictionary={"CXXFLAGS_EXTRAS": flags})190 lldbutil.run_to_name_breakpoint(self, "bar")191 192 self.check_global_var("ns::Foo::mem", "const int", "10")193 194 self.expect_expr("mem", result_value="10")195 self.expect_expr("Foo::mem", result_value="10")196 self.expect_expr("ns::Foo::mem", result_value="10")197 self.expect_expr("::Foo::mem", result_value="-29")198 199 # Fails on Windows for unknown reasons.200 @skipIfWindows201 # On linux this passes due to the manual index202 @expectedFailureDarwin(debug_info=no_match(["dsym"]))203 @skipIf(debug_info=["dsym"], compiler=["clang"], compiler_version=["<", "19.0"])204 def test_shadowed_static_inline_members_dwarf5(self):205 self.check_shadowed_static_inline_members("-gdwarf-5")206 207 # On linux this passes due to the manual index208 @expectedFailureDarwin209 def test_shadowed_static_inline_members_dwarf4(self):210 self.check_shadowed_static_inline_members("-gdwarf-4")211 212 @expectedFailureAll(bugnumber="target var doesn't honour global namespace")213 def test_shadowed_static_inline_members_xfail(self):214 self.build()215 lldbutil.run_to_name_breakpoint(self, "bar")216 self.check_global_var("::Foo::mem", "const int", "-29")217