From 322e13b91aac23ab324c3dcbbcfe8e73894f4c28 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 7 Oct 2021 11:18:22 +0200 Subject: [PATCH] [lldb] Rewrite/expand TestCppTypedef and document a lookup bug. Just regrouping the checks for the same typedef together and also giving the different typedefs unique names. We might want to have a second test with identical names to see how LLDB handle the potential name conflict, but that should be a separate test and not part of the main typedef test. Also this test is actually unintentionally passing. LLDB can't lookup typedefs in a struct/class scope, but in the test the check passes as the local variable in the expression evaluation scope pulls in the typedef. I added a second check that makes it clear that this is not working right now. --- lldb/test/API/lang/cpp/typedef/TestCppTypedef.py | 94 +++++++++++++++--------- lldb/test/API/lang/cpp/typedef/main.cpp | 32 +++++--- 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py b/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py index 35a2fba..f3f54a8 100644 --- a/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py +++ b/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py @@ -1,63 +1,89 @@ """ -Test that we can retrieve typedefed types correctly +Test typedef types. """ - - import lldb import lldbsuite.test.lldbutil as lldbutil from lldbsuite.test.lldbtest import * from lldbsuite.test import decorators + class TestCppTypedef(TestBase): mydir = TestBase.compute_mydir(__file__) def test_typedef(self): """ - Test that we retrieve typedefed types correctly + Test that we retrieve typedefed types correctly """ - # Build and run until the breakpoint self.build() self.main_source_file = lldb.SBFileSpec("main.cpp") - (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( - self, "Set a breakpoint here", self.main_source_file) + lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") + ) - # Get the current frame - frame = thread.GetSelectedFrame() - # First of all, check that we can get a typedefed type correctly in a simple case + # First of all, check that we can get a typedefed type correctly in a simple case. + expr_result = self.expect_expr( + "(GlobalTypedef)s", + result_type="GlobalTypedef", + result_children=[ValueCheck(value="0.5")], + ) - expr_result = self.expect_expr("(SF)s", result_children=[ValueCheck(value="0.5")]) - self.expect_expr("(ns::SF)s", result_children=[ValueCheck(value="0.5")]) - self.expect_expr("(ST::SF)s", result_children=[ValueCheck(value="0.5")]) - - self.filecheck("image dump ast a.out", __file__, "--strict-whitespace") -# CHECK: {{^}}|-TypedefDecl {{.*}} SF 'S' -# CHECK: {{^}}|-NamespaceDecl {{.*}} ns -# CHECK-NEXT: {{^}}| `-TypedefDecl {{.*}} SF 'S' -# CHECK: {{^}}`-CXXRecordDecl {{.*}} struct ST definition -# CHECK: {{^}} `-TypedefDecl {{.*}} SF 'S' - - typedef_type = expr_result.GetType(); - self.assertTrue(typedef_type.IsValid(), "Can't get `SF` type of evaluated expression") - self.assertTrue(typedef_type.IsTypedefType(), "Type `SF` should be a typedef") + # The type should be a typedef. + typedef_type = expr_result.GetType() + self.assertTrue(typedef_type.IsValid()) + self.assertTrue(typedef_type.IsTypedefType()) + # The underlying type should be S. typedefed_type = typedef_type.GetTypedefedType() - self.assertTrue(typedefed_type.IsValid(), "Can't get `SF` typedefed type") - self.assertEqual(typedefed_type.GetName(), "S", "Got invalid `SF` typedefed type") + self.assertTrue(typedefed_type.IsValid()) + self.assertEqual(typedefed_type.GetName(), "S") + # Check that we can get a typedefed type correctly in the case # when an elaborated type is created during the parsing + expr_result = self.expect_expr( + "(GlobalTypedef::V)s.value", result_type="GlobalTypedef::V" + ) - expr_result = frame.EvaluateExpression("(SF::V)s.value") - self.assertTrue(expr_result.IsValid(), "Expression failed with: " + str(expr_result.GetError())) - - typedef_type = expr_result.GetType(); - self.assertTrue(typedef_type.IsValid(), "Can't get `SF::V` type of evaluated expression") - self.assertTrue(typedef_type.IsTypedefType(), "Type `SF::V` should be a typedef") + # The type should be a typedef. + typedef_type = expr_result.GetType() + self.assertTrue(typedef_type.IsValid()) + self.assertTrue(typedef_type.IsTypedefType()) + # The underlying type should be float. typedefed_type = typedef_type.GetTypedefedType() - self.assertTrue(typedefed_type.IsValid(), "Can't get `SF::V` typedefed type") - self.assertEqual(typedefed_type.GetName(), "float", "Got invalid `SF::V` typedefed type") + self.assertTrue(typedefed_type.IsValid()) + self.assertEqual(typedefed_type.GetName(), "float") + + + # Try accessing a typedef inside a namespace. + self.expect_expr( + "(ns::NamespaceTypedef)s", result_children=[ValueCheck(value="0.5")] + ) + + + # Try accessing a typedef inside a struct/class. + # FIXME: This doesn't actually work. StructTypedef just gets injected + # by the local variable in the expression evaluation context. + self.expect_expr( + "(ST::StructTypedef)s", result_children=[ValueCheck(value="0.5")] + ) + # This doesn't work for the reason above. There is no local variable + # injecting OtherStructTypedef so we will actually error here. + self.expect( + "expression -- (NonLocalVarStruct::OtherStructTypedef)1", + error=True, + substrs=["no member named 'OtherStructTypedef' in 'NonLocalVarStruct'"], + ) + + + # Check the generated Clang AST. + self.filecheck("image dump ast a.out", __file__, "--strict-whitespace") +# CHECK: {{^}}|-TypedefDecl {{.*}} GlobalTypedef 'S' +# CHECK: {{^}}|-NamespaceDecl {{.*}} ns +# CHECK-NEXT: {{^}}| `-TypedefDecl {{.*}} NamespaceTypedef 'S' +# CHECK: {{^}}|-CXXRecordDecl {{.*}} struct ST definition +# CHECK: {{^}}| `-TypedefDecl {{.*}} StructTypedef 'S' diff --git a/lldb/test/API/lang/cpp/typedef/main.cpp b/lldb/test/API/lang/cpp/typedef/main.cpp index 0575786..d4c2f51 100644 --- a/lldb/test/API/lang/cpp/typedef/main.cpp +++ b/lldb/test/API/lang/cpp/typedef/main.cpp @@ -1,22 +1,34 @@ -template -struct S { +template struct S { typedef T V; V value; }; -typedef S SF; +typedef S GlobalTypedef; namespace ns { -typedef S SF; +typedef S NamespaceTypedef; } + struct ST { - typedef S SF; + typedef S StructTypedef; +}; + +// Struct type that is not supposed to be a local variable in the test +// expression evaluation scope. Tests that typedef lookup can actually look +// inside class/struct scopes. +struct NonLocalVarStruct { + typedef int OtherStructTypedef; }; -int main (int argc, char const *argv[]) { - SF s{ .5 }; - ns::SF in_ns; - ST::SF in_struct; - return 0; // Set a breakpoint here +int otherFunc() { + NonLocalVarStruct::OtherStructTypedef i = 3; + return i; +} + +int main(int argc, char const *argv[]) { + GlobalTypedef s{.5}; + ns::NamespaceTypedef in_ns; + ST::StructTypedef in_struct; + return otherFunc(); // Set a breakpoint here } -- 2.7.4