[Lldb-commits] [lldb] cda1450 - [lldb][NFC] Add some tests for function-local classes and document some bugs

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 9 05:12:50 PDT 2021


Author: Raphael Isemann
Date: 2021-09-09T14:12:02+02:00
New Revision: cda1450f1c771712718ef3585315f0ecbb708d8d

URL: https://github.com/llvm/llvm-project/commit/cda1450f1c771712718ef3585315f0ecbb708d8d
DIFF: https://github.com/llvm/llvm-project/commit/cda1450f1c771712718ef3585315f0ecbb708d8d.diff

LOG: [lldb][NFC] Add some tests for function-local classes and document some bugs

This feature doesn't seem to have any dedicated test. Instead some random tests
(e.g. the bitfield tests) are declaring function-local classes for some reason.
This adds a dedicated test so we can clean up those other tests.

Also add FIXME's for some basic stuff that doesn't work. The first FIXME is a
good beginner bug which just requires prepending the function name (in case we
decide to fix it instead of documenting this behaviour). The second FIXME is
caused by LLDB searching for definitions by name (which also seems to miss the
function name so there is a conflict with the outer type).

Some more things that should be tested (and might not work):
* Local classes with member functions with local classes.
* Classes in different functions with same name.
* Classes with the same name in different TUs with internal linkage functions of
  the same name.
* Empty classes are parsed by the DWARF parser in a fast path, so that requires
  dedicated tests.
* Repeat some of the tested logic for C.

Added: 
    lldb/test/API/lang/cpp/function-local-class/Makefile
    lldb/test/API/lang/cpp/function-local-class/TestCppFunctionLocalClass.py
    lldb/test/API/lang/cpp/function-local-class/main.cpp

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/lldb/test/API/lang/cpp/function-local-class/Makefile b/lldb/test/API/lang/cpp/function-local-class/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-local-class/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/lang/cpp/function-local-class/TestCppFunctionLocalClass.py b/lldb/test/API/lang/cpp/function-local-class/TestCppFunctionLocalClass.py
new file mode 100644
index 0000000000000..dfbbfb8ad04c5
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-local-class/TestCppFunctionLocalClass.py
@@ -0,0 +1,58 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @no_debug_info_test
+    def test(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp"))
+
+        m_val = self.expect_expr("m", result_type="WithMember", result_children=[
+            ValueCheck(name="i", value="1")
+        ])
+        # FIXME: The non-display name doesn't include the function, so users
+        # can't actually match specific classes by their name. Either document
+        # or fix this.
+        self.assertEqual(m_val.GetType().GetName(), "WithMember")
+        # Try accessing the type in the expression evaluator.
+        self.expect_expr("m.i", result_type="int", result_value="1")
+
+        self.expect_expr("typedef_unnamed", result_type="TypedefUnnamed", result_children=[
+            ValueCheck(name="a", value="2")
+        ])
+        self.expect_expr("typedef_unnamed2", result_type="TypedefUnnamed2", result_children=[
+            ValueCheck(name="b", value="3")
+        ])
+        self.expect_expr("unnamed", result_type="(unnamed struct)", result_children=[
+            ValueCheck(name="i", value="4")
+        ])
+        self.expect_expr("unnamed2", result_type="(unnamed struct)", result_children=[
+            ValueCheck(name="j", value="5")
+        ])
+
+        # Try a class that is only forward declared.
+        self.expect_expr("fwd", result_type="Forward *")
+        self.expect("expression -- fwd->i", error=True, substrs=[
+            "member access into incomplete type 'Forward'"
+        ])
+        self.expect("expression -- *fwd", error=True, substrs=[
+            "incomplete type 'Forward' where a complete type is required"
+        ])
+
+        # Try a class that has a name that matches a class in the global scope.
+        self.expect_expr("fwd_conflict", result_type="ForwardConflict *")
+        # FIXME: This pulls in the unrelated type with the same name from the
+        # global scope.
+        self.expect("expression -- fwd_conflict->i", error=True, substrs=[
+            # This should point out that ForwardConflict is incomplete.
+            "no member named 'i' in 'ForwardConflict'"
+        ])
+        self.expect("expression -- *fwd_conflict", error=True, substrs=[
+            # This should fail to parse instead.
+            "couldn't read its memory"
+        ])

diff  --git a/lldb/test/API/lang/cpp/function-local-class/main.cpp b/lldb/test/API/lang/cpp/function-local-class/main.cpp
new file mode 100644
index 0000000000000..4f492cc3cf85f
--- /dev/null
+++ b/lldb/test/API/lang/cpp/function-local-class/main.cpp
@@ -0,0 +1,44 @@
+// These declarations have intentionally the same name as the function-local
+// class. LLDB should never pull in these definitions as this test only inspects
+// the classes defined in the function below.
+struct WithMember {
+  float false_def;
+};
+typedef struct {
+  float false_def;
+} TypedefUnnamed;
+struct ForwardConflict {
+  float false_def;
+};
+ForwardConflict conflict1;
+WithMember conflict2;
+struct {
+  float false_def;
+} unnamed;
+
+int main() {
+  struct WithMember {
+    int i;
+  };
+  typedef struct {
+    int a;
+  } TypedefUnnamed;
+  typedef struct {
+    int b;
+  } TypedefUnnamed2;
+  struct Forward;
+  struct ForwardConflict;
+
+  WithMember m = {1};
+  TypedefUnnamed typedef_unnamed = {2};
+  TypedefUnnamed2 typedef_unnamed2 = {3};
+  struct {
+    int i;
+  } unnamed = {4};
+  struct {
+    int j;
+  } unnamed2 = {5};
+  Forward *fwd = nullptr;
+  ForwardConflict *fwd_conflict = nullptr;
+  return 0; // break here
+}


        


More information about the lldb-commits mailing list