# Uncomment one of the next two lines to compile Vim with the
-# address sanitizer or with the undefined sanitizer. Works with gcc and
+# address sanitizer (asan) or with the undefined sanitizer. Works with gcc and
# clang. May make Vim twice as slow. Errors reported on stderr.
# More at: https://code.google.com/p/address-sanitizer/
+# Useful environment variables:
+# $ export ASAN_OPTIONS="print_stacktrace=1 log_path=asan"
+# $ export LSAN_OPTIONS="suppressions=$cwd/testdir/lsan-suppress.txt"
#SANITIZER_CFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer
#SANITIZER_CFLAGS = -g -O0 -fsanitize=undefined -fno-omit-frame-pointer
SANITIZER_LIBS = $(SANITIZER_CFLAGS)
if (cmdidx == CMD_const)
{
emsg(_(e_const_option));
- return NULL;
+ goto theend;
}
if (is_decl)
{
{
// cannot happen?
emsg(_(e_letunexp));
- return NULL;
+ goto theend;
}
cc = *p;
*p = NUL;
if (opt_type == -3)
{
semsg(_(e_unknown_option), arg);
- return NULL;
+ goto theend;
}
if (opt_type == -2 || opt_type == 0)
type = &t_string;
if (!valid_yank_reg(arg[1], TRUE))
{
emsg_invreg(arg[1]);
- return FAIL;
+ goto theend;
}
dest = dest_reg;
if (is_decl)
return scope;
}
+/*
+ * Free the current scope and go back to the outer scope.
+ */
+ static void
+drop_scope(cctx_T *cctx)
+{
+ scope_T *scope = cctx->ctx_scope;
+
+ if (scope == NULL)
+ {
+ iemsg("calling drop_scope() without a scope");
+ return;
+ }
+ cctx->ctx_scope = scope->se_outer;
+ vim_free(scope);
+}
+
/*
* Evaluate an expression that is a constant:
* has(arg)
return NULL;
}
ifscope = &scope->se_u.se_if;
- cctx->ctx_scope = scope->se_outer;
unwind_locals(cctx, scope->se_local_count);
if (scope->se_u.se_if.is_if_label >= 0)
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
cctx->ctx_skip = FALSE;
- vim_free(scope);
+ drop_scope(cctx);
return arg;
}
// Reserve a variable to store the loop iteration counter.
loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
if (loop_idx < 0)
+ {
+ drop_scope(cctx);
return NULL;
+ }
// Reserve a variable to store "var"
var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
if (var_idx < 0)
+ {
+ drop_scope(cctx);
return NULL;
+ }
generate_STORENR(cctx, loop_idx, -1);
// compile "expr", it remains on the stack until "endfor"
arg = p;
if (compile_expr1(&arg, cctx) == FAIL)
+ {
+ drop_scope(cctx);
return NULL;
+ }
// now we know the type of "var"
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (vartype->tt_type != VAR_LIST)
{
emsg(_("E1024: need a List to iterate over"));
+ drop_scope(cctx);
return NULL;
}
if (vartype->tt_member->tt_type != VAR_UNKNOWN)