Index: packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py =================================================================== --- packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py +++ packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py @@ -18,13 +18,15 @@ mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + def setUp(self): # Call super's setUp(). TestBase.setUp(self) # Find the line number to break for main.c. self.source_name = 'main.m' - + @skipUnlessDarwin @add_test_categories(['pyapi']) def test_objc_checker(self): @@ -77,3 +79,16 @@ # Make sure the error is helpful: err_string = expr_error.GetCString() self.assertTrue("selector" in err_string) + + # + # Check that we correctly insert the checker for an + # ObjC method with the struct return convention. + # Getting this wrong would cause us to call the checker + # with the wrong arguments, and the checker would crash + # So I'm just checking "expression runs successfully" here: + # + expr_value = frame.EvaluateExpression("[my_simple getBigStruct]", False) + expr_error = expr_value.GetError() + + self.assertTrue(expr_error.Success()) + Index: packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m =================================================================== --- packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m +++ packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m @@ -1,11 +1,19 @@ #import +// This should be a big enough struct that it will force +// the struct return convention: +typedef struct BigStruct { + float a, b, c, d, e, f, g, h, i, j, k, l; +} BigStruct; + + @interface Simple : NSObject { int _value; } - (int) value; - (void) setValue: (int) newValue; +- (BigStruct) getBigStruct; @end @implementation Simple @@ -18,6 +26,13 @@ { _value = newValue; } + +- (BigStruct) getBigStruct +{ + BigStruct big_struct = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, 10.0, 11.0, 12.0}; + return big_struct; +} @end int main () Index: source/Expression/IRDynamicChecks.cpp =================================================================== --- source/Expression/IRDynamicChecks.cpp +++ source/Expression/IRDynamicChecks.cpp @@ -424,8 +424,15 @@ switch (msgSend_types[inst]) { case eMsgSend: case eMsgSend_fpret: - target_object = call_inst->getArgOperand(0); - selector = call_inst->getArgOperand(1); + // On arm64, clang uses objc_msgSend for scalar and struct return + // calls. The call instruction will record which was used. + if (call_inst->hasStructRetAttr()) { + target_object = call_inst->getArgOperand(1); + selector = call_inst->getArgOperand(2); + } else { + target_object = call_inst->getArgOperand(0); + selector = call_inst->getArgOperand(1); + } break; case eMsgSend_stret: target_object = call_inst->getArgOperand(1);