aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/eval.c6
-rw-r--r--src/nvim/eval/typval.c2
-rw-r--r--src/nvim/ex_cmds.c8
-rw-r--r--src/nvim/ex_getln.c3
-rw-r--r--src/nvim/func_attr.h11
-rw-r--r--src/nvim/macros.h18
-rw-r--r--src/nvim/normal.c1
-rw-r--r--src/nvim/os_unix.c2
-rw-r--r--src/nvim/regexp_nfa.c5
-rw-r--r--src/nvim/shada.c2
-rw-r--r--src/nvim/testdir/runtest.vim2
-rw-r--r--test/functional/ex_cmds/script_spec.lua75
-rw-r--r--test/functional/helpers.lua14
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua12
-rw-r--r--test/functional/provider/python3_spec.lua8
-rw-r--r--test/functional/provider/python_spec.lua8
-rw-r--r--test/functional/provider/ruby_spec.lua6
20 files changed, 170 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 44784b042f..b8c6c6055c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -221,6 +221,11 @@ else()
add_definitions(-Wall -Wextra -pedantic -Wno-unused-parameter
-Wstrict-prototypes -std=gnu99)
+ check_c_compiler_flag(-Wimplicit-fallthrough HAS_WIMPLICIT_FALLTHROUGH_FLAG)
+ if(HAS_WIMPLICIT_FALLTHROUGH_FLAG)
+ add_definitions(-Wimplicit-fallthrough)
+ endif()
+
# On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang
# 3.4.1 used there.
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index f54979eb1e..e3897e3929 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -3607,6 +3607,7 @@ int build_stl_str_hl(
case STL_OFFSET_X:
base = kNumBaseHexadecimal;
+ // fallthrough
case STL_OFFSET:
{
long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
@@ -3617,6 +3618,7 @@ int build_stl_str_hl(
}
case STL_BYTEVAL_X:
base = kNumBaseHexadecimal;
+ // fallthrough
case STL_BYTEVAL:
num = byteval;
if (num == NL)
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 678fa851eb..bfdec90a32 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -4916,14 +4916,17 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len)
if (ctrl_x_mode == CTRL_X_DICTIONARY
|| ctrl_x_mode == CTRL_X_THESAURUS)
break;
+ // fallthrough
case '~':
if (!p_magic) /* quote these only if magic is set */
break;
+ // fallthrough
case '\\':
if (ctrl_x_mode == CTRL_X_DICTIONARY
|| ctrl_x_mode == CTRL_X_THESAURUS)
break;
- case '^': /* currently it's not needed. */
+ // fallthrough
+ case '^': // currently it's not needed.
case '$':
m++;
if (dest != NULL)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 56a6632fad..31e5ae8806 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -9596,13 +9596,15 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (from) {
break;
}
- case kCdScopeTab: // FALLTHROUGH
+ // fallthrough
+ case kCdScopeTab:
assert(tp);
from = tp->tp_localdir;
if (from) {
break;
}
- case kCdScopeGlobal: // FALLTHROUGH
+ // fallthrough
+ case kCdScopeGlobal:
if (globaldir) { // `globaldir` is not always set.
from = globaldir;
} else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD.
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 786b766689..19d9d56058 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -1869,7 +1869,7 @@ void tv_free(typval_T *tv)
}
case VAR_FUNC: {
func_unref(tv->vval.v_string);
- // FALLTHROUGH
+ FALLTHROUGH;
}
case VAR_STRING: {
xfree(tv->vval.v_string);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 018a228843..a528a65abb 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -4878,8 +4878,9 @@ void fix_help_buffer(void)
continue;
e1 = vim_strrchr(t1, '.');
e2 = vim_strrchr(path_tail(f2), '.');
- if (e1 == NUL || e2 == NUL)
+ if (e1 == NULL || e2 == NULL) {
continue;
+ }
if (fnamecmp(e1, ".txt") != 0
&& fnamecmp(e1, fname + 4) != 0) {
/* Not .txt and not .abx, remove it. */
@@ -5949,9 +5950,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// :sign define {name} {args}... {last}=
// | |
// last p
- if (p == NUL)
- {
- /* Expand last argument name (before equal sign). */
+ if (p == NULL) {
+ // Expand last argument name (before equal sign).
xp->xp_pattern = last;
switch (cmd_idx)
{
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index fe45ba4568..0c14bf4255 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1268,6 +1268,7 @@ static int command_line_handle_key(CommandLineState *s)
}
return command_line_changed(s);
}
+ // fallthrough
case K_UP:
case K_DOWN:
@@ -5401,7 +5402,7 @@ char *script_get(exarg_T *const eap, size_t *const lenp)
if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) {
*lenp = STRLEN(eap->arg);
- return xmemdupz(eap->arg, *lenp);
+ return eap->skip ? NULL : xmemdupz(eap->arg, *lenp);
}
garray_T ga = { .ga_data = NULL, .ga_len = 0 };
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index 9146a1a8ea..cc94a41f80 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -89,6 +89,10 @@
# undef FUNC_ATTR_NONNULL_RET
#endif
+#ifdef FUNC_ATTR_NORETURN
+# undef FUNC_ATTR_NORETURN
+#endif
+
#ifndef DID_REAL_ATTR
# define DID_REAL_ATTR
# ifdef __GNUC__
@@ -107,6 +111,7 @@
# define REAL_FATTR_UNUSED __attribute__((unused))
# define REAL_FATTR_NONNULL_ALL __attribute__((nonnull))
# define REAL_FATTR_NONNULL_ARG(...) __attribute__((nonnull(__VA_ARGS__)))
+# define REAL_FATTR_NORETURN __attribute__((noreturn))
# ifdef __clang__
// clang only
@@ -176,6 +181,10 @@
# ifndef REAL_FATTR_NONNULL_RET
# define REAL_FATTR_NONNULL_RET
# endif
+
+# ifndef REAL_FATTR_NORETURN
+# define REAL_FATTR_NORETURN
+# endif
#endif
#ifdef DEFINE_FUNC_ATTRIBUTES
@@ -196,6 +205,7 @@
# define FUNC_ATTR_NONNULL_ALL REAL_FATTR_NONNULL_ALL
# define FUNC_ATTR_NONNULL_ARG(...) REAL_FATTR_NONNULL_ARG(__VA_ARGS__)
# define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET
+# define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN
#elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
# define FUNC_ATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x)
@@ -209,4 +219,5 @@
# define FUNC_ATTR_NONNULL_ALL
# define FUNC_ATTR_NONNULL_ARG(...)
# define FUNC_ATTR_NONNULL_RET
+# define FUNC_ATTR_NORETURN
#endif
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index 214af82422..9ab6dc5d2b 100644
--- a/src/nvim/macros.h
+++ b/src/nvim/macros.h
@@ -153,4 +153,22 @@
#define STR_(x) #x
#define STR(x) STR_(x)
+#ifndef __has_attribute
+# define NVIM_HAS_ATTRIBUTE(x) 0
+#elif defined(__clang__) && __clang__ == 1 \
+ && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ <= 5))
+// Starting in Clang 3.6, __has_attribute was fixed to only report true for
+// GNU-style attributes. Prior to that, it reported true if _any_ backend
+// supported the attribute.
+# define NVIM_HAS_ATTRIBUTE(x) 0
+#else
+# define NVIM_HAS_ATTRIBUTE __has_attribute
+#endif
+
+#if NVIM_HAS_ATTRIBUTE(fallthrough)
+# define FALLTHROUGH __attribute__((fallthrough))
+#else
+# define FALLTHROUGH
+#endif
+
#endif // NVIM_MACROS_H
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index f73e3079b9..050020d79d 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1861,6 +1861,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
bangredo = true; // do_bang() will put cmd in redo buffer.
}
+ // fallthrough
case OP_INDENT:
case OP_COLON:
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index c5a42204be..7cf0d7817c 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -133,7 +133,7 @@ void mch_free_acl(vim_acl_T aclent)
}
#endif
-void mch_exit(int r)
+void mch_exit(int r) FUNC_ATTR_NORETURN
{
exiting = true;
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 85fae9d82e..24c156d2ba 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -634,6 +634,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
config |= CLASS_o7;
break;
}
+ return FAIL;
case 'a':
if (*(p + 2) == 'z') {
config |= CLASS_az;
@@ -642,6 +643,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
config |= CLASS_af;
break;
}
+ return FAIL;
case 'A':
if (*(p + 2) == 'Z') {
config |= CLASS_AZ;
@@ -650,7 +652,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
config |= CLASS_AF;
break;
}
- /* FALLTHROUGH */
+ return FAIL;
default:
return FAIL;
}
@@ -4194,6 +4196,7 @@ skip_add:
subs = addstate(l, state->out, subs, pim, off_arg);
break;
}
+ // fallthrough
case NFA_MCLOSE1:
case NFA_MCLOSE2:
case NFA_MCLOSE3:
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index a6d8cb6563..e1879ca8c0 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -2047,7 +2047,7 @@ static inline ShaDaWriteResult shada_read_when_writing(
}
case kSDReadStatusNotShaDa: {
ret = kSDWriteReadNotShada;
- // fallthrough
+ FALLTHROUGH;
}
case kSDReadStatusReadError: {
return ret;
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 64ad0f0103..6832622cdf 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -134,7 +134,7 @@ else
endif
" Names of flaky tests.
-let s:flaky = ['Test_with_partial_callback']
+let s:flaky = ['Test_with_partial_callback()']
" Locate Test_ functions and execute them.
set nomore
diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua
new file mode 100644
index 0000000000..4e57d2755d
--- /dev/null
+++ b/test/functional/ex_cmds/script_spec.lua
@@ -0,0 +1,75 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local eq = helpers.eq
+local neq = helpers.neq
+local meths = helpers.meths
+local clear = helpers.clear
+local dedent = helpers.dedent
+local source = helpers.source
+local exc_exec = helpers.exc_exec
+local missing_provider = helpers.missing_provider
+
+before_each(clear)
+
+describe('script_get-based command', function()
+ local garbage = ')}{+*({}]*[;(+}{&[]}{*])('
+
+ local function test_garbage_exec(cmd, check_neq)
+ describe(cmd, function()
+ it('works correctly when skipping oneline variant', function()
+ eq(true, pcall(source, (dedent([[
+ if 0
+ %s %s
+ endif
+ ]])):format(cmd, garbage)))
+ eq('', meths.command_output('messages'))
+ if check_neq then
+ neq(0, exc_exec(dedent([[
+ %s %s
+ ]])):format(cmd, garbage))
+ end
+ end)
+ it('works correctly when skipping HEREdoc variant', function()
+ eq(true, pcall(source, (dedent([[
+ if 0
+ %s << EOF
+ %s
+ EOF
+ endif
+ ]])):format(cmd, garbage)))
+ eq('', meths.command_output('messages'))
+ if check_neq then
+ eq(true, pcall(source, (dedent([[
+ let g:exc = 0
+ try
+ %s << EOF
+ %s
+ EOF
+ catch
+ let g:exc = v:exception
+ endtry
+ ]])):format(cmd, garbage)))
+ neq(0, meths.get_var('exc'))
+ end
+ end)
+ end)
+ end
+
+ clear()
+
+ -- Built-in scripts
+ test_garbage_exec('lua', true)
+
+ -- Provider-based scripts
+ test_garbage_exec('ruby', not missing_provider('ruby'))
+ test_garbage_exec('python', not missing_provider('python'))
+ test_garbage_exec('python3', not missing_provider('python3'))
+
+ -- Missing scripts
+ test_garbage_exec('tcl', false)
+ test_garbage_exec('mzscheme', false)
+ test_garbage_exec('perl', false)
+
+ -- Not really a script
+ test_garbage_exec('xxxinvalidlanguagexxx', true)
+end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 1be70f917c..b03840b3fe 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -566,6 +566,19 @@ local function get_pathsep()
return funcs.fnamemodify('.', ':p'):sub(-1)
end
+local function missing_provider(provider)
+ if provider == 'ruby' then
+ local prog = funcs['provider#' .. provider .. '#Detect']()
+ return prog == '' and (provider .. ' not detected') or false
+ elseif provider == 'python' or provider == 'python3' then
+ local py_major_version = (provider == 'python3' and 3 or 2)
+ local errors = funcs['provider#pythonx#Detect'](py_major_version)[2]
+ return errors ~= '' and errors or false
+ else
+ assert(false, 'Unknown provider: ' .. provider)
+ end
+end
+
local module = {
prepend_argv = prepend_argv,
clear = clear,
@@ -632,6 +645,7 @@ local module = {
meth_pcall = meth_pcall,
NIL = mpack.NIL,
get_pathsep = get_pathsep,
+ missing_provider = missing_provider,
}
return function(after_each)
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
index 110f7dd852..38e8145d1c 100644
--- a/test/functional/legacy/036_regexp_character_classes_spec.lua
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -275,4 +275,16 @@ describe('character classes in regexp', function()
diff(sixlines(string.sub(punct1, 1)..digits..punct2..upper..punct3..
lower..punct4..ctrl2..iso_text))
end)
+ it('does not convert character class ranges to an incorrect class', function()
+ source([[
+ 1 s/\%#=0[0-z]//g
+ 2 s/\%#=1[0-z]//g
+ 3 s/\%#=2[0-z]//g
+ 4 s/\%#=0[^0-z]//g
+ 5 s/\%#=1[^0-z]//g
+ 6 s/\%#=2[^0-z]//g
+ ]])
+ diff(string.rep(ctrl1..punct1..punct4..ctrl2..iso_text..'\n', 3)
+ ..string.rep(digits..punct2..upper..punct3..lower..'\n', 3))
+ end)
end)
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index 89a546675f..aa50f53451 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -3,14 +3,14 @@ local eval, command, feed = helpers.eval, helpers.command, helpers.feed
local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
local expect, write_file = helpers.expect, helpers.write_file
local feed_command = helpers.feed_command
+local missing_provider = helpers.missing_provider
do
clear()
- command('let [g:interp, g:errors] = provider#pythonx#Detect(3)')
- local errors = eval('g:errors')
- if errors ~= '' then
+ local err = missing_provider('python3')
+ if err then
pending(
- 'Python 3 (or the Python 3 neovim module) is broken or missing:\n' .. errors,
+ 'Python 3 (or the Python 3 neovim module) is broken or missing:\n' .. err,
function() end)
return
end
diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua
index 94dfa90ea8..25f5e0a6d0 100644
--- a/test/functional/provider/python_spec.lua
+++ b/test/functional/provider/python_spec.lua
@@ -12,14 +12,14 @@ local command = helpers.command
local exc_exec = helpers.exc_exec
local write_file = helpers.write_file
local curbufmeths = helpers.curbufmeths
+local missing_provider = helpers.missing_provider
do
clear()
- command('let [g:interp, g:errors] = provider#pythonx#Detect(2)')
- local errors = meths.get_var('errors')
- if errors ~= '' then
+ local err = missing_provider('python')
+ if err then
pending(
- 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors,
+ 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. err,
function() end)
return
end
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index 7b0e17688d..9f5ef3b3fc 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -10,13 +10,11 @@ local expect = helpers.expect
local command = helpers.command
local write_file = helpers.write_file
local curbufmeths = helpers.curbufmeths
+local missing_provider = helpers.missing_provider
do
clear()
- command('let g:prog = provider#ruby#Detect()')
- local prog = meths.get_var('prog')
-
- if prog == '' then
+ if missing_provider('ruby') then
pending(
"Cannot find the neovim RubyGem. Try :CheckHealth",
function() end)