aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2016-03-01 02:25:15 +0300
committerZyX <kp-pav@yandex.ru>2016-04-18 02:48:20 +0300
commit6a35f2ac8bd7a3a0e8c9b988b85237424bc10e73 (patch)
tree85f051eb281ee06389fd7a84963b6c7cba8ac3aa
parent942e0b338c9bff1dfdcb59e8308160449f1f38b4 (diff)
downloadrneovim-6a35f2ac8bd7a3a0e8c9b988b85237424bc10e73.tar.gz
rneovim-6a35f2ac8bd7a3a0e8c9b988b85237424bc10e73.tar.bz2
rneovim-6a35f2ac8bd7a3a0e8c9b988b85237424bc10e73.zip
eval: Do not break when VimVarIndex and vimvars order mismatches
Also makes sure that compiler will error out when new name is longer then vv_filler.
-rw-r--r--src/nvim/assert.h101
-rw-r--r--src/nvim/eval.c165
-rw-r--r--src/nvim/eval.h2
3 files changed, 161 insertions, 107 deletions
diff --git a/src/nvim/assert.h b/src/nvim/assert.h
index 3a900aca65..0ce48e4766 100644
--- a/src/nvim/assert.h
+++ b/src/nvim/assert.h
@@ -8,17 +8,32 @@
// defined(__has_feature) && __has_feature(...). Therefore we define Clang's
// __has_feature and __has_extension macro's before referring to them.
#ifndef __has_feature
- #define __has_feature(x) 0
+# define __has_feature(x) 0
#endif
#ifndef __has_extension
- #define __has_extension __has_feature
+# define __has_extension __has_feature
#endif
-/// STATIC_ASSERT(condition, message) - assert at compile time if !cond
+/// @def STATIC_ASSERT
+/// @brief Assert at compile time if condition is not satisfied.
///
-/// example:
-/// STATIC_ASSERT(sizeof(void *) == 8, "need 64-bits mode");
+/// Should be put on its own line, followed by a semicolon.
+///
+/// Example:
+///
+/// STATIC_ASSERT(sizeof(void *) == 8, "Expected 64-bit mode");
+///
+/// @param[in] condition Condition to check, should be an integer constant
+/// expression.
+/// @param[in] message Message which will be given if check fails.
+
+/// @def STATIC_ASSERT_EXPR
+/// @brief Like #STATIC_ASSERT, but can be used where expressions are used.
+///
+/// STATIC_ASSERT_EXPR may be put in brace initializer lists. Error message
+/// given in this case is not very nice with the current implementation though
+/// and `message` argument is ignored.
// define STATIC_ASSERT as C11's _Static_assert whenever either C11 mode is
// detected or the compiler is known to support it. Note that Clang in C99
@@ -29,50 +44,74 @@
// clearer messages we get from _Static_assert, we suppress the warnings
// temporarily.
+#define STATIC_ASSERT_PRAGMA_START
+#define STATIC_ASSERT_PRAGMA_END
+#define STATIC_ASSERT(...) \
+ do { \
+ STATIC_ASSERT_PRAGMA_START \
+ STATIC_ASSERT_STATEMENT(__VA_ARGS__); \
+ STATIC_ASSERT_PRAGMA_END \
+ } while (0)
+
// the easiest case, when the mode is C11 (generic compiler) or Clang
// advertises explicit support for c_static_assert, meaning it won't warn.
#if __STDC_VERSION__ >= 201112L || __has_feature(c_static_assert)
- #define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
+# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
// if we're dealing with gcc >= 4.6 in C99 mode, we can still use
// _Static_assert but we need to suppress warnings, this is pretty ugly.
#elif (!defined(__clang__) && !defined(__INTEL_COMPILER)) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
- #define STATIC_ASSERT(cond, msg) \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-pedantic\"") \
- _Static_assert(cond, msg); \
- _Pragma("GCC diagnostic pop") \
+
+# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
+
+# undef STATIC_ASSERT_PRAGMA_START
+# define STATIC_ASSERT_PRAGMA_START \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-pedantic\"") \
+
+# undef STATIC_ASSERT_PRAGMA_END
+# define STATIC_ASSERT_PRAGMA_END \
+ _Pragma("GCC diagnostic pop") \
// the same goes for clang in C99 mode, but we suppress a different warning
#elif defined(__clang__) && __has_extension(c_static_assert)
- #define STATIC_ASSERT(cond, msg) \
- _Pragma("clang diagnostic push") \
- _Pragma("clang diagnostic ignored \"-Wc11-extensions\"") \
- _Static_assert(cond, msg); \
- _Pragma("clang diagnostic pop") \
+
+# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
+
+# undef STATIC_ASSERT_PRAGMA_START
+# define STATIC_ASSERT_PRAGMA_START \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wc11-extensions\"") \
+
+# undef STATIC_ASSERT_PRAGMA_END
+# define STATIC_ASSERT_PRAGMA_END \
+ _Pragma("clang diagnostic pop") \
// TODO(aktau): verify that this works, don't have MSVC on hand.
#elif _MSC_VER >= 1600
- #define STATIC_ASSERT(cond, msg) static_assert(cond, msg)
+
+# define STATIC_ASSERT_STATEMENT(cond, msg) static_assert(cond, msg)
// fallback for compilers that don't support _Static_assert or static_assert
// not as pretty but gets the job done. Credit goes to Pádraig Brady and
// contributors.
#else
- #define ASSERT_CONCAT_(a, b) a##b
- #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
- // These can't be used after statements in c89.
- #ifdef __COUNTER__
- #define STATIC_ASSERT(e,m) \
- { enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }; }
- #else
- // This can't be used twice on the same line so ensure if using in headers
- // that the headers are not included twice (by wrapping in #ifndef...#endif)
- // Note it doesn't cause an issue when used on same line of separate modules
- // compiled with gcc -combine -fwhole-program.
- #define STATIC_ASSERT(e,m) \
- { enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }; }
- #endif
+# define STATIC_ASSERT_STATEMENT STATIC_ASSERT_EXPR
+#endif
+
+#define ASSERT_CONCAT_(a, b) a##b
+#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
+// These can't be used after statements in c89.
+#ifdef __COUNTER__
+# define STATIC_ASSERT_EXPR(e, m) \
+ ((enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }) 0)
+#else
+// This can't be used twice on the same line so ensure if using in headers
+// that the headers are not included twice (by wrapping in #ifndef...#endif)
+// Note it doesn't cause an issue when used on same line of separate modules
+// compiled with gcc -combine -fwhole-program.
+# define STATIC_ASSERT_EXPR(e, m) \
+ ((enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }) 0)
#endif
#endif // NVIM_ASSERT_H
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index c23613aeab..8fcb570525 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -282,7 +282,21 @@ typedef enum {
#define VV_RO 2 /* read-only */
#define VV_RO_SBX 4 /* read-only in the sandbox */
-#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}, {0}
+#define VV(idx, name, type, flags) \
+ [idx] = { \
+ .vv_name = name, \
+ .vv_di = { \
+ .di_tv = { .v_type = type }, \
+ .di_flags = 0, \
+ }, \
+ .vv_filler = {( \
+ STATIC_ASSERT_EXPR( \
+ (sizeof(name) - 1 <= sizeof(vimvars[0].vv_filler)), \
+ "Vim variable name is too long, adjust vv_filler size"), \
+ 0 \
+ )}, \
+ .vv_flags = flags, \
+ }
// Array to hold the value of v: variables.
// The value is in a dictitem, so that it can also be used in the v: scope.
@@ -295,80 +309,83 @@ static struct vimvar {
char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX.
} vimvars[] =
{
- /*
- * The order here must match the VV_ defines in eval.h!
- * Initializing a union does not work, leave tv.vval empty to get zero's.
- */
- { VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO },
- { VV_NAME("count1", VAR_NUMBER), VV_RO },
- { VV_NAME("prevcount", VAR_NUMBER), VV_RO },
- { VV_NAME("errmsg", VAR_STRING), VV_COMPAT },
- { VV_NAME("warningmsg", VAR_STRING), 0 },
- { VV_NAME("statusmsg", VAR_STRING), 0 },
- { VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO },
- { VV_NAME("this_session", VAR_STRING), VV_COMPAT },
- { VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO },
- { VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX },
- { VV_NAME("termresponse", VAR_STRING), VV_RO },
- { VV_NAME("fname", VAR_STRING), VV_RO },
- { VV_NAME("lang", VAR_STRING), VV_RO },
- { VV_NAME("lc_time", VAR_STRING), VV_RO },
- { VV_NAME("ctype", VAR_STRING), VV_RO },
- { VV_NAME("charconvert_from", VAR_STRING), VV_RO },
- { VV_NAME("charconvert_to", VAR_STRING), VV_RO },
- { VV_NAME("fname_in", VAR_STRING), VV_RO },
- { VV_NAME("fname_out", VAR_STRING), VV_RO },
- { VV_NAME("fname_new", VAR_STRING), VV_RO },
- { VV_NAME("fname_diff", VAR_STRING), VV_RO },
- { VV_NAME("cmdarg", VAR_STRING), VV_RO },
- { VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX },
- { VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX },
- { VV_NAME("folddashes", VAR_STRING), VV_RO_SBX },
- { VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX },
- { VV_NAME("progname", VAR_STRING), VV_RO },
- { VV_NAME("servername", VAR_STRING), VV_RO },
- { VV_NAME("dying", VAR_NUMBER), VV_RO },
- { VV_NAME("exception", VAR_STRING), VV_RO },
- { VV_NAME("throwpoint", VAR_STRING), VV_RO },
- { VV_NAME("register", VAR_STRING), VV_RO },
- { VV_NAME("cmdbang", VAR_NUMBER), VV_RO },
- { VV_NAME("insertmode", VAR_STRING), VV_RO },
- { VV_NAME("val", VAR_UNKNOWN), VV_RO },
- { VV_NAME("key", VAR_UNKNOWN), VV_RO },
- { VV_NAME("profiling", VAR_NUMBER), VV_RO },
- { VV_NAME("fcs_reason", VAR_STRING), VV_RO },
- { VV_NAME("fcs_choice", VAR_STRING), 0 },
- { VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO },
- { VV_NAME("beval_winnr", VAR_NUMBER), VV_RO },
- { VV_NAME("beval_lnum", VAR_NUMBER), VV_RO },
- { VV_NAME("beval_col", VAR_NUMBER), VV_RO },
- { VV_NAME("beval_text", VAR_STRING), VV_RO },
- { VV_NAME("scrollstart", VAR_STRING), 0 },
- { VV_NAME("swapname", VAR_STRING), VV_RO },
- { VV_NAME("swapchoice", VAR_STRING), 0 },
- { VV_NAME("swapcommand", VAR_STRING), VV_RO },
- { VV_NAME("char", VAR_STRING), 0 },
- { VV_NAME("mouse_win", VAR_NUMBER), 0 },
- { VV_NAME("mouse_lnum", VAR_NUMBER), 0 },
- { VV_NAME("mouse_col", VAR_NUMBER), 0 },
- { VV_NAME("operator", VAR_STRING), VV_RO },
- { VV_NAME("searchforward", VAR_NUMBER), 0 },
- { VV_NAME("hlsearch", VAR_NUMBER), 0 },
- { VV_NAME("oldfiles", VAR_LIST), 0 },
- { VV_NAME("windowid", VAR_NUMBER), VV_RO },
- { VV_NAME("progpath", VAR_STRING), VV_RO },
- { VV_NAME("command_output", VAR_STRING), 0 },
- { VV_NAME("completed_item", VAR_DICT), VV_RO },
- { VV_NAME("option_new", VAR_STRING), VV_RO },
- { VV_NAME("option_old", VAR_STRING), VV_RO },
- { VV_NAME("option_type", VAR_STRING), VV_RO },
- { VV_NAME("errors", VAR_LIST), 0 },
- { VV_NAME("msgpack_types", VAR_DICT), VV_RO },
- { VV_NAME("event", VAR_DICT), VV_RO },
- { VV_NAME("false", VAR_SPECIAL), VV_RO },
- { VV_NAME("true", VAR_SPECIAL), VV_RO },
- { VV_NAME("null", VAR_SPECIAL), VV_RO },
+ // VV_ tails differing from upcased string literals:
+ // VV_CC_FROM "charconvert_from"
+ // VV_CC_TO "charconvert_to"
+ // VV_SEND_SERVER "servername"
+ // VV_REG "register"
+ // VV_OP "operator"
+ VV(VV_COUNT, "count", VAR_NUMBER, VV_COMPAT+VV_RO),
+ VV(VV_COUNT1, "count1", VAR_NUMBER, VV_RO),
+ VV(VV_PREVCOUNT, "prevcount", VAR_NUMBER, VV_RO),
+ VV(VV_ERRMSG, "errmsg", VAR_STRING, VV_COMPAT),
+ VV(VV_WARNINGMSG, "warningmsg", VAR_STRING, 0),
+ VV(VV_STATUSMSG, "statusmsg", VAR_STRING, 0),
+ VV(VV_SHELL_ERROR, "shell_error", VAR_NUMBER, VV_COMPAT+VV_RO),
+ VV(VV_THIS_SESSION, "this_session", VAR_STRING, VV_COMPAT),
+ VV(VV_VERSION, "version", VAR_NUMBER, VV_COMPAT+VV_RO),
+ VV(VV_LNUM, "lnum", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_TERMRESPONSE, "termresponse", VAR_STRING, VV_RO),
+ VV(VV_FNAME, "fname", VAR_STRING, VV_RO),
+ VV(VV_LANG, "lang", VAR_STRING, VV_RO),
+ VV(VV_LC_TIME, "lc_time", VAR_STRING, VV_RO),
+ VV(VV_CTYPE, "ctype", VAR_STRING, VV_RO),
+ VV(VV_CC_FROM, "charconvert_from", VAR_STRING, VV_RO),
+ VV(VV_CC_TO, "charconvert_to", VAR_STRING, VV_RO),
+ VV(VV_FNAME_IN, "fname_in", VAR_STRING, VV_RO),
+ VV(VV_FNAME_OUT, "fname_out", VAR_STRING, VV_RO),
+ VV(VV_FNAME_NEW, "fname_new", VAR_STRING, VV_RO),
+ VV(VV_FNAME_DIFF, "fname_diff", VAR_STRING, VV_RO),
+ VV(VV_CMDARG, "cmdarg", VAR_STRING, VV_RO),
+ VV(VV_FOLDSTART, "foldstart", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_FOLDEND, "foldend", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_FOLDDASHES, "folddashes", VAR_STRING, VV_RO_SBX),
+ VV(VV_FOLDLEVEL, "foldlevel", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_PROGNAME, "progname", VAR_STRING, VV_RO),
+ VV(VV_SEND_SERVER, "servername", VAR_STRING, VV_RO),
+ VV(VV_DYING, "dying", VAR_NUMBER, VV_RO),
+ VV(VV_EXCEPTION, "exception", VAR_STRING, VV_RO),
+ VV(VV_THROWPOINT, "throwpoint", VAR_STRING, VV_RO),
+ VV(VV_REG, "register", VAR_STRING, VV_RO),
+ VV(VV_CMDBANG, "cmdbang", VAR_NUMBER, VV_RO),
+ VV(VV_INSERTMODE, "insertmode", VAR_STRING, VV_RO),
+ VV(VV_VAL, "val", VAR_UNKNOWN, VV_RO),
+ VV(VV_KEY, "key", VAR_UNKNOWN, VV_RO),
+ VV(VV_PROFILING, "profiling", VAR_NUMBER, VV_RO),
+ VV(VV_FCS_REASON, "fcs_reason", VAR_STRING, VV_RO),
+ VV(VV_FCS_CHOICE, "fcs_choice", VAR_STRING, 0),
+ VV(VV_BEVAL_BUFNR, "beval_bufnr", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_WINNR, "beval_winnr", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_LNUM, "beval_lnum", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_COL, "beval_col", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_TEXT, "beval_text", VAR_STRING, VV_RO),
+ VV(VV_SCROLLSTART, "scrollstart", VAR_STRING, 0),
+ VV(VV_SWAPNAME, "swapname", VAR_STRING, VV_RO),
+ VV(VV_SWAPCHOICE, "swapchoice", VAR_STRING, 0),
+ VV(VV_SWAPCOMMAND, "swapcommand", VAR_STRING, VV_RO),
+ VV(VV_CHAR, "char", VAR_STRING, 0),
+ VV(VV_MOUSE_WIN, "mouse_win", VAR_NUMBER, 0),
+ VV(VV_MOUSE_LNUM, "mouse_lnum", VAR_NUMBER, 0),
+ VV(VV_MOUSE_COL, "mouse_col", VAR_NUMBER, 0),
+ VV(VV_OP, "operator", VAR_STRING, VV_RO),
+ VV(VV_SEARCHFORWARD, "searchforward", VAR_NUMBER, 0),
+ VV(VV_HLSEARCH, "hlsearch", VAR_NUMBER, 0),
+ VV(VV_OLDFILES, "oldfiles", VAR_LIST, 0),
+ VV(VV_WINDOWID, "windowid", VAR_NUMBER, VV_RO),
+ VV(VV_PROGPATH, "progpath", VAR_STRING, VV_RO),
+ VV(VV_COMMAND_OUTPUT, "command_output", VAR_STRING, 0),
+ VV(VV_COMPLETED_ITEM, "completed_item", VAR_DICT, VV_RO),
+ VV(VV_OPTION_NEW, "option_new", VAR_STRING, VV_RO),
+ VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
+ VV(VV_OPTION_TYPE, "option_type", VAR_STRING, VV_RO),
+ VV(VV_ERRORS, "errors", VAR_LIST, 0),
+ VV(VV_MSGPACK_TYPES, "msgpack_types", VAR_DICT, VV_RO),
+ VV(VV_EVENT, "event", VAR_DICT, VV_RO),
+ VV(VV_FALSE, "false", VAR_SPECIAL, VV_RO),
+ VV(VV_TRUE, "true", VAR_SPECIAL, VV_RO),
+ VV(VV_NULL, "null", VAR_SPECIAL, VV_RO),
};
+#undef VV
/* shorthand */
#define vv_type vv_di.di_tv.v_type
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 9d45b780a9..f81eb5d063 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -52,8 +52,6 @@ EXTERN ufunc_T dumuf;
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
/// Defines for Vim variables
-///
-/// Order must match order in vimvars[] table in eval.c.
typedef enum {
VV_COUNT,
VV_COUNT1,