[Clang] Add C++26 approved in the Poland WG21 meeting
[llvm-project.git] / lldb / test / API / functionalities / rerun_and_expr_dylib / TestRerunAndExprDylib.py
blob74e7c895c0fabef0661d84137df6ea2ca62f22c2
1 """
2 Test that re-running a process from within the same target
3 after rebuilding the a dynamic library flushes the scratch
4 TypeSystems tied to that process.
5 """
7 import lldb
8 from lldbsuite.test.lldbtest import *
9 from lldbsuite.test import lldbutil
10 from lldbsuite.test.decorators import *
13 def isUbuntu18_04():
14 """
15 Check if the host OS is Ubuntu 18.04.
16 Derived from `platform.freedesktop_os_release` in Python 3.10.
17 """
18 for path in ("/etc/os-release", "/usr/lib/os-release"):
19 if os.path.exists(path):
20 with open(path) as f:
21 contents = f.read()
22 if "Ubuntu 18.04" in contents:
23 return True
25 return False
28 class TestRerunExprDylib(TestBase):
29 @skipTestIfFn(isUbuntu18_04, bugnumber="rdar://103831050")
30 @skipIfWindows
31 def test(self):
32 """
33 Tests whether re-launching a process without destroying
34 the owning target keeps invalid ASTContexts in the
35 scratch AST's importer.
37 We test this by:
38 1. Evaluating an expression to import 'struct Foo' into
39 the scratch AST
40 2. Change the definition of 'struct Foo' and rebuild the dylib
41 3. Re-launch the process
42 4. Evaluate the same expression in (1). We expect to have only
43 the latest definition of 'struct Foo' in the scratch AST.
44 """
46 DYLIB_NAME = "foo"
47 FULL_DYLIB_NAME = "libfoo.dylib" if self.platformIsDarwin() else "libfoo.so"
49 # Build libfoo.dylib
50 self.build(
51 dictionary={
52 "DYLIB_CXX_SOURCES": "lib.cpp",
53 "DYLIB_ONLY": "YES",
54 "DYLIB_NAME": DYLIB_NAME,
55 "USE_LIBDL": "1",
56 "LD_EXTRAS": "-L.",
60 # Build a.out
61 self.build(
62 dictionary={
63 "EXE": "a.out",
64 "CXX_SOURCES": "main.cpp",
65 "USE_LIBDL": "1",
66 "CXXFLAGS_EXTRAS": f'-DLIB_NAME=\\"{FULL_DYLIB_NAME}\\"',
67 "LD_EXTRAS": "-L.",
71 exe = self.getBuildArtifact("a.out")
72 target = self.dbg.CreateTarget(exe)
73 target.BreakpointCreateBySourceRegex("dlclose", lldb.SBFileSpec("main.cpp"))
74 target.BreakpointCreateBySourceRegex("return", lldb.SBFileSpec("main.cpp"))
75 process = target.LaunchSimple(None, None, self.get_process_working_directory())
77 self.expect_expr(
78 "*foo",
79 result_type="Foo",
80 result_children=[ValueCheck(name="m_val", value="42")],
83 # Delete the dylib to force make to rebuild it.
84 remove_file(self.getBuildArtifact(FULL_DYLIB_NAME))
86 # Re-build libfoo.dylib
87 self.build(
88 dictionary={
89 "DYLIB_CXX_SOURCES": "rebuild.cpp",
90 "DYLIB_ONLY": "YES",
91 "DYLIB_NAME": DYLIB_NAME,
92 "USE_LIBDL": "1",
93 "LD_EXTRAS": "-L.",
97 # Rerun program within the same target
98 process.Continue()
99 process.Destroy()
100 process = target.LaunchSimple(None, None, self.get_process_working_directory())
102 self.expect_expr(
103 "*foo",
104 result_type="Foo",
105 result_children=[
106 ValueCheck(
107 name="Base", children=[ValueCheck(name="m_base_val", value="42")]
109 ValueCheck(name="m_derived_val", value="137"),
113 self.filecheck("target module dump ast", __file__)
115 # The new definition 'struct Foo' is in the scratch AST
116 # CHECK: |-CXXRecordDecl {{.*}} struct Foo definition
117 # CHECK: | |-public 'Base'
118 # CHECK-NEXT: | `-FieldDecl {{.*}} m_derived_val 'int'
119 # CHECK-NEXT: `-CXXRecordDecl {{.*}} struct Base definition
120 # CHECK: `-FieldDecl {{.*}} m_base_val 'int'
122 # ...but the original definition of 'struct Foo' is not in the scratch AST anymore
123 # CHECK-NOT: FieldDecl {{.*}} m_val 'int'