diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -1004,7 +1004,8 @@ case CompletionMode::Normal: { std::string to_add = completion.GetCompletion(); to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); - if (request.GetParsedArg().IsQuoted()) + // Terminate the current argument with a quote if it started with a quote. + if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted()) to_add.push_back(request.GetParsedArg().GetQuoteChar()); to_add.push_back(' '); el_insertstr(m_editline, to_add.c_str()); diff --git a/lldb/test/API/commands/expression/multiline-completion/TestMultilineCompletion.py b/lldb/test/API/commands/expression/multiline-completion/TestMultilineCompletion.py --- a/lldb/test/API/commands/expression/multiline-completion/TestMultilineCompletion.py +++ b/lldb/test/API/commands/expression/multiline-completion/TestMultilineCompletion.py @@ -11,6 +11,21 @@ mydir = TestBase.compute_mydir(__file__) + def start_expression_editor(self): + """ Starts the multiline expression editor. """ + self.child.send("expression\n") + self.child.expect_exact("terminate with an empty line to evaluate") + + def exit_expression_editor(self): + """ Exits the multiline expression editor. """ + # Send a newline to finish the current line. The second newline will + # finish the new empty line which will exit the editor. The space at the + # start prevents that the first newline already exits the editor (in + # case the current line of the editor is already empty when this + # function is called). + self.child.send(" \n\n") + self.expect_prompt() + # PExpect uses many timeouts internally and doesn't play well # under ASAN on a loaded machine.. @skipIfAsan @@ -21,14 +36,23 @@ self.launch(executable=self.getBuildArtifact("a.out"), dimensions=(100,500)) self.expect("b main", substrs=["Breakpoint 1", "address ="]) - self.expect("run", substrs=["stop reason ="]) + self.expect("run", substrs=["stop reason = breakpoint 1"]) - self.child.sendline("expr") - self.child.expect_exact("terminate with an empty line to evaluate") + self.start_expression_editor() self.child.send("to_\t") self.child.expect_exact("to_complete") - - self.child.send("\n\n") - self.expect_prompt() + self.exit_expression_editor() + + # Check that completion empty input in a function with only one + # local variable works. + self.expect("breakpoint set -p 'break in single_local_func'", + substrs=["Breakpoint 2"]) + self.expect("continue", substrs=["stop reason = breakpoint 2"]) + self.start_expression_editor() + self.child.send("\t") + # Only one local, so this will directly insert 'only_local' with a + # trailing space to signal a final completion. + self.child.expect_exact("only_local ") + self.exit_expression_editor() self.quit() diff --git a/lldb/test/API/commands/expression/multiline-completion/main.c b/lldb/test/API/commands/expression/multiline-completion/main.c --- a/lldb/test/API/commands/expression/multiline-completion/main.c +++ b/lldb/test/API/commands/expression/multiline-completion/main.c @@ -1,4 +1,11 @@ +int single_local_func() { + // This function should always only have a single local variable and no + // parameters. + int only_local = 3; + return only_local; // break in single_local_func +} + int main(int argc, char **argv) { int to_complete = 0; - return to_complete; + return to_complete + single_local_func(); }