brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.6 KiB · bfe11f6 Raw
184 lines · python
1"""2Test calling an expression with errors that a FixIt can fix.3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbutil9 10 11class ExprCommandWithFixits(TestBase):12    def test_with_dummy_target(self):13        """Test calling expressions in the dummy target with errors that can be fixed by the FixIts."""14 15        # Enable fix-its as they were intentionally disabled by TestBase.setUp.16        self.runCmd("settings set target.auto-apply-fixits true")17 18        ret_val = lldb.SBCommandReturnObject()19        result = self.dbg.GetCommandInterpreter().HandleCommand(20            "expression ((1 << 16) - 1))", ret_val21        )22        self.assertEqual(23            result, lldb.eReturnStatusSuccessFinishResult, ret_val.GetError()24        )25        self.assertIn(26            "Evaluated this expression after applying Fix-It(s):", ret_val.GetError()27        )28 29    def test_with_target(self):30        """Test calling expressions with errors that can be fixed by the FixIts."""31        self.build()32        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(33            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")34        )35 36        options = lldb.SBExpressionOptions()37        options.SetAutoApplyFixIts(True)38 39        top_level_options = lldb.SBExpressionOptions()40        top_level_options.SetAutoApplyFixIts(True)41        top_level_options.SetTopLevel(True)42 43        frame = self.thread.GetFrameAtIndex(0)44 45        # Try with one error:46        value = frame.EvaluateExpression("my_pointer.first", options)47        self.assertTrue(value.IsValid())48        self.assertSuccess(value.GetError())49        self.assertEqual(value.GetValueAsUnsigned(), 10)50 51        # Try with one error in a top-level expression.52        # The Fix-It changes "ptr.m" to "ptr->m".53        expr = "struct MyTy { int m; }; MyTy x; MyTy *ptr = &x; int m = ptr.m;"54        value = frame.EvaluateExpression(expr, top_level_options)55        # A successfully parsed top-level expression will yield an56        # unknown error. If a parsing error would have happened we57        # would get a different error kind, so let's check the error58        # kind here.59        self.assertEqual(value.GetError().GetCString(), "unknown error")60 61        # Try with two errors:62        two_error_expression = "my_pointer.second->a"63        value = frame.EvaluateExpression(two_error_expression, options)64        self.assertTrue(value.IsValid())65        self.assertSuccess(value.GetError())66        self.assertEqual(value.GetValueAsUnsigned(), 20)67 68        # Try a Fix-It that is stored in the 'note:' diagnostic of an error.69        # The Fix-It here is adding parantheses around the ToStr parameters.70        fixit_in_note_expr = "#define ToStr(x) #x\nToStr(0 {, })"71        value = frame.EvaluateExpression(fixit_in_note_expr, options)72        self.assertTrue(value.IsValid())73        self.assertSuccess(value.GetError())74        self.assertEqual(value.GetSummary(), '"(0 {, })"')75 76        # Now turn off the fixits, and the expression should fail:77        options.SetAutoApplyFixIts(False)78        value = frame.EvaluateExpression(two_error_expression, options)79        self.assertTrue(value.IsValid())80        self.assertTrue(value.GetError().Fail())81        error_string = value.GetError().GetCString()82        self.assertNotEqual(83            error_string.find("fixed expression suggested:"), -1, "Fix was suggested"84        )85        self.assertNotEqual(86            error_string.find("my_pointer->second.a"), -1, "Fix was right"87        )88 89    def test_with_target_error_applies_fixit(self):90        """Check that applying a Fix-it which fails to execute correctly still91        prints that the Fix-it was applied."""92        self.build()93        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(94            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")95        )96        # Enable fix-its as they were intentionally disabled by TestBase.setUp.97        self.runCmd("settings set target.auto-apply-fixits true")98        ret_val = lldb.SBCommandReturnObject()99        result = self.dbg.GetCommandInterpreter().HandleCommand(100            "expression null_pointer.first", ret_val101        )102        self.assertEqual(result, lldb.eReturnStatusFailed, ret_val.GetError())103 104        self.assertIn(105            "Evaluated this expression after applying Fix-It(s):", ret_val.GetError()106        )107        self.assertIn("null_pointer->first", ret_val.GetError())108 109    @expectedFailureAll(110        archs=["aarch64"], oslist=["freebsd"], bugnumber="llvm.org/pr49407"111    )112    def test_with_multiple_retries(self):113        """Test calling expressions with errors that can be fixed by the FixIts."""114        self.build()115        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(116            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")117        )118 119        # Test repeatedly applying Fix-Its to expressions and reparsing them.120        multiple_runs_options = lldb.SBExpressionOptions()121        multiple_runs_options.SetAutoApplyFixIts(True)122        multiple_runs_options.SetTopLevel(True)123 124        frame = self.thread.GetFrameAtIndex(0)125 126        # An expression that needs two parse attempts with one Fix-It each127        # to be successfully parsed.128        two_runs_expr = """129        struct Data { int m; };130 131        template<typename T>132        struct S1 : public T {133          using T::TypeDef;134          int f() {135            Data data;136            data.m = 123;137            // The first error as the using above requires a 'typename '.138            // Will trigger a Fix-It that puts 'typename' in the right place.139            typename S1<T>::TypeDef i = &data;140            // i has the type "Data *", so this should be i.m.141            // The second run will change the . to -> via the Fix-It.142            return i.m;143          }144        };145 146        struct ClassWithTypeDef {147          typedef Data *TypeDef;148        };149 150        int test_X(int i) {151          S1<ClassWithTypeDef> s1;152          return s1.f();153        }154        """155 156        # Disable retries which will fail.157        multiple_runs_options.SetRetriesWithFixIts(0)158        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)159        errmsg = value.GetError().GetCString()160        self.assertIn("using declaration resolved to type without 'typename'", errmsg)161        self.assertIn("fixed expression suggested:", errmsg)162        self.assertIn("using typename T::TypeDef", errmsg)163        # The second Fix-It shouldn't be suggested here as Clang should have164        # aborted the parsing process.165        self.assertNotIn("i->m", errmsg)166 167        # Retry once, but the expression needs two retries.168        multiple_runs_options.SetRetriesWithFixIts(1)169        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)170        errmsg = value.GetError().GetCString()171        self.assertIn("fixed expression suggested:", errmsg)172        # Both our fixed expressions should be in the suggested expression.173        self.assertIn("using typename T::TypeDef", errmsg)174        self.assertIn("i->m", errmsg)175 176        # Retry twice, which will get the expression working.177        multiple_runs_options.SetRetriesWithFixIts(2)178        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)179        # This error signals success for top level expressions.180        self.assertEqual(value.GetError().GetCString(), "unknown error")181 182        # Test that the code above compiles to the right thing.183        self.expect_expr("test_X(1)", result_type="int", result_value="123")184