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.c1
-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/legacy/036_regexp_character_classes_spec.lua12
15 files changed, 70 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d1c0e8fd5..eb259bc983 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 f74086e45a..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:
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/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)