1
0
forked from aniani/vim

patch 8.2.3259: when 'indentexpr' causes an error did_throw may hang

Problem:    When 'indentexpr' causes an error the did_throw flag may remain
            set.
Solution:   Reset did_throw and show the error. (closes #8677)
This commit is contained in:
Bram Moolenaar
2021-07-31 21:32:31 +02:00
parent 78db17c6f3
commit 620c959c6c
4 changed files with 78 additions and 61 deletions

View File

@@ -1268,67 +1268,7 @@ do_cmdline(
* commands are executed.
*/
if (did_throw)
{
char *p = NULL;
msglist_T *messages = NULL;
/*
* If the uncaught exception is a user exception, report it as an
* error. If it is an error exception, display the saved error
* message now. For an interrupt exception, do nothing; the
* interrupt message is given elsewhere.
*/
switch (current_exception->type)
{
case ET_USER:
vim_snprintf((char *)IObuff, IOSIZE,
_("E605: Exception not caught: %s"),
current_exception->value);
p = (char *)vim_strsave(IObuff);
break;
case ET_ERROR:
messages = current_exception->messages;
current_exception->messages = NULL;
break;
case ET_INTERRUPT:
break;
}
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
current_exception->throw_lnum);
ESTACK_CHECK_SETUP
current_exception->throw_name = NULL;
discard_current_exception(); // uses IObuff if 'verbose'
suppress_errthrow = TRUE;
force_abort = TRUE;
if (messages != NULL)
{
do
{
msglist_T *next = messages->next;
int save_compiling = estack_compiling;
estack_compiling = messages->msg_compiling;
emsg(messages->msg);
vim_free(messages->msg);
vim_free(messages->sfile);
vim_free(messages);
messages = next;
estack_compiling = save_compiling;
}
while (messages != NULL);
}
else if (p != NULL)
{
emsg(p);
vim_free(p);
}
vim_free(SOURCING_NAME);
ESTACK_CHECK_NOW
estack_pop();
}
handle_did_throw();
/*
* On an interrupt or an aborting error not converted to an exception,
@@ -1448,6 +1388,73 @@ do_cmdline(
return retval;
}
/*
* Handle when "did_throw" is set after executing commands.
*/
void
handle_did_throw()
{
char *p = NULL;
msglist_T *messages = NULL;
/*
* If the uncaught exception is a user exception, report it as an
* error. If it is an error exception, display the saved error
* message now. For an interrupt exception, do nothing; the
* interrupt message is given elsewhere.
*/
switch (current_exception->type)
{
case ET_USER:
vim_snprintf((char *)IObuff, IOSIZE,
_("E605: Exception not caught: %s"),
current_exception->value);
p = (char *)vim_strsave(IObuff);
break;
case ET_ERROR:
messages = current_exception->messages;
current_exception->messages = NULL;
break;
case ET_INTERRUPT:
break;
}
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
current_exception->throw_lnum);
ESTACK_CHECK_SETUP
current_exception->throw_name = NULL;
discard_current_exception(); // uses IObuff if 'verbose'
suppress_errthrow = TRUE;
force_abort = TRUE;
if (messages != NULL)
{
do
{
msglist_T *next = messages->next;
int save_compiling = estack_compiling;
estack_compiling = messages->msg_compiling;
emsg(messages->msg);
vim_free(messages->msg);
vim_free(messages->sfile);
vim_free(messages);
messages = next;
estack_compiling = save_compiling;
}
while (messages != NULL);
}
else if (p != NULL)
{
emsg(p);
vim_free(p);
}
vim_free(SOURCING_NAME);
ESTACK_CHECK_NOW
estack_pop();
}
#ifdef FEAT_EVAL
/*
* Obtain a line when inside a ":while" or ":for" loop.

View File

@@ -1822,6 +1822,13 @@ get_expr_indent(void)
check_cursor();
State = save_State;
// Reset did_throw, unless 'debug' has "throw" and inside a try/catch.
if (did_throw && (vim_strchr(p_debug, 't') == NULL || trylevel == 0))
{
handle_did_throw();
did_throw = FALSE;
}
// If there is an error, just keep the current indent.
if (indent < 0)
indent = get_indent();

View File

@@ -3,6 +3,7 @@ void do_exmode(int improved);
int do_cmdline_cmd(char_u *cmd);
int do_cmd_argument(char_u *cmd);
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, int flags);
void handle_did_throw(void);
int getline_equal(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, char_u *(*func)(int, void *, int, getline_opt_T));
void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);

View File

@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
3259,
/**/
3258,
/**/