1""" 2Tests const static data members as specified by C++11 [class.static.data]p3. 3""" 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 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 produce 22 # 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 namespace 30 # 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 have 84 # 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-class 88 # definitions don't have valid addresses and the following code produces 89 # 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 that 102 # it does not crash. 103 self.expect("image lookup -t A") 104 105 # dsymutil strips the debug info for classes that only have const static 106 # 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 @skipIfWindows 147 # On linux this passes due to the manual index 148 @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 index 154 @expectedFailureDarwin 155 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 only 159 # constexpr members when dsymutil is enabled 160 @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 both 186 correctly determine the requested inline static variable 187 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 @skipIfWindows 201 # On linux this passes due to the manual index 202 @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 index 208 @expectedFailureDarwin 209 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