forked from aniani/vim
patch 9.0.2169: Vim9: builtin funcs may accept a non-value
Problem: Vim9: builtin funcs may accept a non-value Solution: Restrict builtin functions that accept `type` This PR finishes off detection and prevention of using a type as a value. It takes care of builtin functions. However there are some builtin functions, that need to be able to handle types as well as non-args: instanceof(), type(), typename(), string(). A "bit", FE_X, is added to funcentry_T; when set, the builtin function can handle a type (class or type-alias) in addition to a value. Noteworthy change: Discovered that in compile_call() the builtin add() is compiled inline instead of calling the builtin. Had to add a check there. closes: #13688 Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
df12e39b8b
commit
d8bf87c9fb
@@ -1651,7 +1651,7 @@ typedef struct
|
||||
char *f_name; // function name
|
||||
char f_min_argc; // minimal number of arguments
|
||||
char f_max_argc; // maximal number of arguments
|
||||
char f_argtype; // for method: FEARG_ values
|
||||
char f_argtype; // for method: FEARG_ values; bits FE_
|
||||
argcheck_T *f_argcheck; // list of functions to check argument types;
|
||||
// use "arg_any" (not NULL) to accept an
|
||||
// argument of any type
|
||||
@@ -1666,10 +1666,12 @@ typedef struct
|
||||
#define VARGS CHAR_MAX
|
||||
|
||||
// values for f_argtype; zero means it cannot be used as a method
|
||||
#define FEARG_1 1 // base is the first argument
|
||||
#define FEARG_2 2 // base is the second argument
|
||||
#define FEARG_3 3 // base is the third argument
|
||||
#define FEARG_4 4 // base is the fourth argument
|
||||
#define FEARG_1 0x01 // base is the first argument
|
||||
#define FEARG_2 0x02 // base is the second argument
|
||||
#define FEARG_3 0x03 // base is the third argument
|
||||
#define FEARG_4 0x04 // base is the fourth argument
|
||||
#define FEARG_MASK 0x0F // bits in f_argtype used as argument index
|
||||
#define FE_X 0x10 // builtin accepts a non-value (class, typealias)
|
||||
|
||||
#if defined(HAVE_MATH_H)
|
||||
# define MATH_FUNC(name) name
|
||||
@@ -2181,7 +2183,7 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_inputsecret},
|
||||
{"insert", 2, 3, FEARG_1, arg23_insert,
|
||||
ret_first_arg, f_insert},
|
||||
{"instanceof", 2, VARGS, FEARG_1, arg2_instanceof,
|
||||
{"instanceof", 2, VARGS, FEARG_1|FE_X, arg2_instanceof,
|
||||
ret_bool, f_instanceof},
|
||||
{"interrupt", 0, 0, 0, NULL,
|
||||
ret_void, f_interrupt},
|
||||
@@ -2659,7 +2661,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_strgetchar},
|
||||
{"stridx", 2, 3, FEARG_1, arg3_string_string_number,
|
||||
ret_number, f_stridx},
|
||||
{"string", 1, 1, FEARG_1, NULL,
|
||||
{"string", 1, 1, FEARG_1|FE_X, NULL,
|
||||
ret_string, f_string},
|
||||
{"strlen", 1, 1, FEARG_1, arg1_string_or_nr,
|
||||
ret_number, f_strlen},
|
||||
@@ -2821,7 +2823,7 @@ static funcentry_T global_functions[] =
|
||||
ret_void, f_test_option_not_set},
|
||||
{"test_override", 2, 2, FEARG_2, arg2_string_number,
|
||||
ret_void, f_test_override},
|
||||
{"test_refcount", 1, 1, FEARG_1, NULL,
|
||||
{"test_refcount", 1, 1, FEARG_1|FE_X, NULL,
|
||||
ret_number, f_test_refcount},
|
||||
{"test_setmouse", 2, 2, 0, arg2_number,
|
||||
ret_void, f_test_setmouse},
|
||||
@@ -2853,9 +2855,9 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_trim},
|
||||
{"trunc", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, f_trunc},
|
||||
{"type", 1, 1, FEARG_1, NULL,
|
||||
{"type", 1, 1, FEARG_1|FE_X, NULL,
|
||||
ret_number, f_type},
|
||||
{"typename", 1, 1, FEARG_1, NULL,
|
||||
{"typename", 1, 1, FEARG_1|FE_X, NULL,
|
||||
ret_string, f_typename},
|
||||
{"undofile", 1, 1, FEARG_1, arg1_string,
|
||||
ret_string, f_undofile},
|
||||
@@ -2927,6 +2929,15 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_xor},
|
||||
};
|
||||
|
||||
/*
|
||||
* Return true if specified function allows a type as an argument.
|
||||
*/
|
||||
static int
|
||||
func_allows_type(int idx)
|
||||
{
|
||||
return (global_functions[idx].f_argtype & FE_X) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function given to ExpandGeneric() to obtain the list of internal
|
||||
* or user defined function names.
|
||||
@@ -3059,6 +3070,15 @@ internal_func_check_arg_types(
|
||||
int argcount,
|
||||
cctx_T *cctx)
|
||||
{
|
||||
// Some internal functions accept types like Class as arguments. For other
|
||||
// functions, check the arguments are not types.
|
||||
if (!(func_allows_type(idx)))
|
||||
{
|
||||
for (int i = 0; i < argcount; ++i)
|
||||
if (check_type_is_value(types[i].type_curr) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
argcheck_T *argchecks = global_functions[idx].f_argcheck;
|
||||
|
||||
if (argchecks == NULL)
|
||||
@@ -3143,7 +3163,7 @@ check_internal_func(int idx, int argcount)
|
||||
else if (argcount > global_functions[idx].f_max_argc)
|
||||
res = FCERR_TOOMANY;
|
||||
else
|
||||
return global_functions[idx].f_argtype;
|
||||
return global_functions[idx].f_argtype & FEARG_MASK;
|
||||
|
||||
name = internal_func_name(idx);
|
||||
if (res == FCERR_TOOMANY)
|
||||
@@ -3153,6 +3173,24 @@ check_internal_func(int idx, int argcount)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some internal functions accept types like Class as arguments. For other
|
||||
* functions, check the arguments are not types.
|
||||
*
|
||||
* Return OK/FAIL.
|
||||
*/
|
||||
static int
|
||||
check_args_for_type(int idx, int argcount, typval_T *argvars)
|
||||
{
|
||||
if (!func_allows_type(idx))
|
||||
{
|
||||
for (int i = 0; i < argcount; ++i)
|
||||
if (check_typval_is_value(&argvars[i]) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
funcerror_T
|
||||
call_internal_func(
|
||||
char_u *name,
|
||||
@@ -3169,6 +3207,8 @@ call_internal_func(
|
||||
return FCERR_TOOFEW;
|
||||
if (argcount > global_functions[i].f_max_argc)
|
||||
return FCERR_TOOMANY;
|
||||
if (check_args_for_type(i, argcount, argvars) == FAIL)
|
||||
return FCERR_OTHER;
|
||||
argvars[argcount].v_type = VAR_UNKNOWN;
|
||||
global_functions[i].f_func(argvars, rettv);
|
||||
return FCERR_NONE;
|
||||
@@ -3200,14 +3240,16 @@ call_internal_method(
|
||||
fi = find_internal_func(name);
|
||||
if (fi < 0)
|
||||
return FCERR_UNKNOWN;
|
||||
if (global_functions[fi].f_argtype == 0)
|
||||
if ((global_functions[fi].f_argtype & FEARG_MASK) == 0)
|
||||
return FCERR_NOTMETHOD;
|
||||
if (argcount + 1 < global_functions[fi].f_min_argc)
|
||||
return FCERR_TOOFEW;
|
||||
if (argcount + 1 > global_functions[fi].f_max_argc)
|
||||
return FCERR_TOOMANY;
|
||||
if (check_args_for_type(fi, argcount, argvars) == FAIL)
|
||||
return FCERR_OTHER;
|
||||
|
||||
if (global_functions[fi].f_argtype == FEARG_2)
|
||||
if ((global_functions[fi].f_argtype & FEARG_MASK) == FEARG_2)
|
||||
{
|
||||
if (argcount < 1)
|
||||
return FCERR_TOOFEW;
|
||||
@@ -3218,7 +3260,7 @@ call_internal_method(
|
||||
for (int i = 1; i < argcount; ++i)
|
||||
argv[i + 1] = argvars[i];
|
||||
}
|
||||
else if (global_functions[fi].f_argtype == FEARG_3)
|
||||
else if ((global_functions[fi].f_argtype & FEARG_MASK) == FEARG_3)
|
||||
{
|
||||
if (argcount < 2)
|
||||
return FCERR_TOOFEW;
|
||||
@@ -3230,7 +3272,7 @@ call_internal_method(
|
||||
for (int i = 2; i < argcount; ++i)
|
||||
argv[i + 1] = argvars[i];
|
||||
}
|
||||
else if (global_functions[fi].f_argtype == FEARG_4)
|
||||
else if ((global_functions[fi].f_argtype & FEARG_MASK) == FEARG_4)
|
||||
{
|
||||
if (argcount < 3)
|
||||
return FCERR_TOOFEW;
|
||||
@@ -3252,6 +3294,9 @@ call_internal_method(
|
||||
}
|
||||
argv[argcount + 1].v_type = VAR_UNKNOWN;
|
||||
|
||||
if (check_args_for_type(fi, argcount + 1, argv) == FAIL)
|
||||
return FCERR_OTHER;
|
||||
|
||||
global_functions[fi].f_func(argv, rettv);
|
||||
return FCERR_NONE;
|
||||
}
|
||||
|
@@ -36,7 +36,6 @@ type_T *get_member_type_from_stack(int count, int skip, cctx_T *cctx);
|
||||
char *vartype_name(vartype_T type);
|
||||
char *type_name(type_T *type, char **tofree);
|
||||
void f_typename(typval_T *argvars, typval_T *rettv);
|
||||
int check_vartype_is_value(vartype_T typ);
|
||||
int check_typval_is_value(typval_T *tv);
|
||||
int check_type_is_value(type_T *type);
|
||||
/* vim: set ft=c : */
|
||||
|
@@ -5048,4 +5048,153 @@ def Test_writefile()
|
||||
v9.CheckDefExecAndScriptFailure(['writefile(["a"], "")'], 'E482: Can''t create file <empty>')
|
||||
enddef
|
||||
|
||||
def Test_passing_type_to_builtin()
|
||||
# type, typename, string, instanceof are allowed type argument
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
type T = number
|
||||
type U = C
|
||||
var x: any
|
||||
x = type(C)
|
||||
x = type(T)
|
||||
x = typename(C)
|
||||
x = typename(T)
|
||||
x = string(C)
|
||||
x = string(T)
|
||||
x = instanceof(C.new(), U, C)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# check argument to add at script level
|
||||
# Note: add() is special cased in compile_call in vim9expr
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
add([], C)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check argument to add in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
add([], C)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to add at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
[]->add(C)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to add in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
[]->add(C)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# Try "empty()" builtin
|
||||
# check argument to empty at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
empty(C)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check argument to empty in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
empty(C)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to empty at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
C->empty()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to empty in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
C->empty()
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# Try "abs()" builtin
|
||||
# check argument to abs at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
abs(C)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check argument to abs in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
abs(C)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to abs at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
C->abs()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
|
||||
# check member call argument to abs in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class C
|
||||
endclass
|
||||
def F()
|
||||
C->abs()
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
@@ -296,7 +296,7 @@ def Test_typealias()
|
||||
type A = list<string>
|
||||
var x = json_encode(A)
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1161: Cannot json encode a typealias', 3)
|
||||
v9.CheckSourceFailure(lines, 'E1403: Type alias "A" cannot be used as a value', 3)
|
||||
|
||||
# Comparing type alias with a number (script level)
|
||||
lines =<< trim END
|
||||
@@ -452,9 +452,9 @@ def Test_typealias_with_builtin_functions()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
type A = list<func>
|
||||
assert_equal(0, empty(A))
|
||||
var x = empty(A)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "A" cannot be used as a value', 3)
|
||||
|
||||
# Using a type alias with len()
|
||||
lines =<< trim END
|
||||
@@ -462,7 +462,7 @@ def Test_typealias_with_builtin_functions()
|
||||
type A = list<func>
|
||||
var x = len(A)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E701: Invalid type for len()', 3)
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "A" cannot be used as a value', 3)
|
||||
|
||||
# Using a type alias with len()
|
||||
lines =<< trim END
|
||||
@@ -473,7 +473,7 @@ def Test_typealias_with_builtin_functions()
|
||||
enddef
|
||||
Foo()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<any> but got typealias', 1)
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
|
||||
|
||||
# Using a type alias with eval()
|
||||
lines =<< trim END
|
||||
@@ -780,4 +780,134 @@ def Test_class_as_func_argument_or_return_value()
|
||||
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value', 1)
|
||||
enddef
|
||||
|
||||
def Test_passing_typealias_to_builtin()
|
||||
# type, typename, string, instanceof are allowed type argument
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
var x: any
|
||||
x = type(T)
|
||||
x = typename(T)
|
||||
x = string(T)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
# check argument to add at script level
|
||||
# Note: add() is special cased in compile_call in vim9expr
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
add([], T)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check argument to add in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
add([], T)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
|
||||
# check member call argument to add at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
[]->add(T)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check member call argument to add in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
[]->add(T)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
|
||||
# Try "empty()" builtin
|
||||
# check argument to empty at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
empty(T)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check argument to empty in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
empty(T)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
|
||||
# check member call argument to empty at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
T->empty()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check member call argument to empty in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
T->empty()
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
|
||||
# Try "abs()" builtin
|
||||
# check argument to abs at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
abs(T)
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check argument to abs in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
abs(T)
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
|
||||
# check member call argument to abs at script level
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
T->abs()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1403: Type alias "T" cannot be used as a value')
|
||||
|
||||
# check member call argument to abs in :def
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type T = number
|
||||
def F()
|
||||
T->abs()
|
||||
enddef
|
||||
F()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2169,
|
||||
/**/
|
||||
2168,
|
||||
/**/
|
||||
|
@@ -1143,6 +1143,8 @@ compile_call(
|
||||
if (STRCMP(name, "add") == 0 && argcount == 2)
|
||||
{
|
||||
type_T *type = get_decl_type_on_stack(cctx, 1);
|
||||
if (check_type_is_value(get_type_on_stack(cctx, 0)) == FAIL)
|
||||
goto theend;
|
||||
|
||||
// add() can be compiled to instructions if we know the type
|
||||
if (type->tt_type == VAR_LIST)
|
||||
|
@@ -1867,6 +1867,8 @@ f_typename(typval_T *argvars, typval_T *rettv)
|
||||
int
|
||||
check_typval_is_value(typval_T *tv)
|
||||
{
|
||||
if (tv == NULL)
|
||||
return OK;
|
||||
if (tv->v_type == VAR_CLASS)
|
||||
{
|
||||
semsg(_(e_using_class_as_value_str), tv->vval.v_class->class_name);
|
||||
@@ -1886,6 +1888,8 @@ check_typval_is_value(typval_T *tv)
|
||||
int
|
||||
check_type_is_value(type_T *type)
|
||||
{
|
||||
if (type == NULL)
|
||||
return OK;
|
||||
if (type->tt_type == VAR_CLASS)
|
||||
{
|
||||
semsg(_(e_using_class_as_value_str), type->tt_class->class_name);
|
||||
@@ -1893,27 +1897,8 @@ check_type_is_value(type_T *type)
|
||||
}
|
||||
else if (type->tt_type == VAR_TYPEALIAS)
|
||||
{
|
||||
// Not sure what could be done here to get a name
|
||||
// TODO: MAYBE AN OPTIONAL ARGUMENT
|
||||
emsg(_(e_using_typealias_as_var_val));
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as above, except check vartype_T.
|
||||
*/
|
||||
int
|
||||
check_vartype_is_value(vartype_T typ)
|
||||
{
|
||||
if (typ == VAR_CLASS)
|
||||
{
|
||||
emsg(_(e_using_class_as_var_val));
|
||||
return FAIL;
|
||||
}
|
||||
else if (typ == VAR_TYPEALIAS)
|
||||
{
|
||||
// TODO: Not sure what could be done here to get a name.
|
||||
// Maybe an optional argument?
|
||||
emsg(_(e_using_typealias_as_var_val));
|
||||
return FAIL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user