aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--builtin.c9
-rw-r--r--evaluate.c34
-rw-r--r--lib.c24
-rw-r--r--lib.h2
-rw-r--r--linearize.c6
-rw-r--r--parse.c65
-rw-r--r--token.h1
-rw-r--r--tokenize.c1
-rw-r--r--validation/attr-context.c40
-rw-r--r--validation/check_byte_count-ice.c4
-rw-r--r--validation/context-stmt.c62
-rw-r--r--validation/error-at-eof.c10
-rw-r--r--validation/expand/builtin-expect.c101
-rw-r--r--validation/goto-reserved.c12
-rw-r--r--validation/integer-const-expr.c85
-rw-r--r--validation/vla-sizeof-ice.c19
-rw-r--r--validation/vla-sizeof0.c20
-rw-r--r--validation/vla-sizeof1.c21
-rw-r--r--validation/vla-sizeof2.c21
-rw-r--r--validation/vla-sizeof3.c21
-rw-r--r--validation/vla-sizeof4.c22
21 files changed, 523 insertions, 57 deletions
diff --git a/builtin.c b/builtin.c
index 2cafcbda..7f9ff358 100644
--- a/builtin.c
+++ b/builtin.c
@@ -82,13 +82,6 @@ error:
return 0;
}
-static int evaluate_expect(struct expression *expr)
-{
- /* Should we evaluate it to return the type of the first argument? */
- expr->ctype = &int_ctype;
- return 1;
-}
-
static int arguments_choose(struct expression *expr)
{
return eval_args(expr, 3);
@@ -198,7 +191,6 @@ static struct symbol_op warning_op = {
};
static struct symbol_op expect_op = {
- .evaluate = evaluate_expect,
.expand = expand_expect
};
@@ -354,6 +346,7 @@ void declare_builtins(void)
declare_builtin("__builtin_ctzl", &int_ctype, 0, &long_ctype, NULL);
declare_builtin("__builtin_ctzll", &int_ctype, 0, &llong_ctype, NULL);
declare_builtin("__builtin_exit", &void_ctype, 0, &int_ctype, NULL);
+ declare_builtin("__builtin_expect", &long_ctype, 0, &long_ctype ,&long_ctype, NULL);
declare_builtin("__builtin_extract_return_addr", &ptr_ctype, 0, &ptr_ctype, NULL);
declare_builtin("__builtin_fabs", &double_ctype, 0, &double_ctype, NULL);
declare_builtin("__builtin_ffs", &int_ctype, 0, &int_ctype, NULL);
diff --git a/evaluate.c b/evaluate.c
index edace120..0ff617b1 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -2211,6 +2211,38 @@ static struct symbol *evaluate_sizeof(struct expression *expr)
size = bits_in_char;
}
+ if (is_array_type(type) && size < 0) { // VLA, 1-dimension only
+ struct expression *base, *size;
+ struct symbol *base_type;
+
+ if (type->type == SYM_NODE)
+ type = type->ctype.base_type; // strip the SYM_NODE
+ base_type = get_base_type(type);
+ if (!base_type)
+ goto error;
+ if (base_type->bit_size <= 0) {
+ base = alloc_expression(expr->pos, EXPR_SIZEOF);
+ base->cast_type = base_type;
+ if (!evaluate_sizeof(base))
+ goto error;
+ } else {
+ base = alloc_expression(expr->pos, EXPR_VALUE);
+ base->value = bits_to_bytes(base_type->bit_size);
+ base->ctype = size_t_ctype;
+ }
+ size = alloc_expression(expr->pos, EXPR_CAST);
+ size->cast_type = size_t_ctype;
+ size->cast_expression = type->array_size;
+ if (!evaluate_expression(size))
+ goto error;
+ expr->left = size;
+ expr->right = base;
+ expr->type = EXPR_BINOP;
+ expr->op = '*';
+ return expr->ctype = size_t_ctype;
+ }
+
+error:
if ((size < 0) || (size & (bits_in_char - 1)))
expression_error(expr, "cannot size expression");
@@ -3593,7 +3625,7 @@ static void evaluate_goto_statement(struct statement *stmt)
{
struct symbol *label = stmt->goto_label;
- if (label && !label->stmt && !lookup_keyword(label->ident, NS_KEYWORD))
+ if (label && !label->stmt && label->ident && !lookup_keyword(label->ident, NS_KEYWORD))
sparse_error(stmt->pos, "label '%s' was not declared", show_ident(label->ident));
evaluate_expression(stmt->goto_expression);
diff --git a/lib.c b/lib.c
index 0be4548a..c451a88c 100644
--- a/lib.c
+++ b/lib.c
@@ -70,10 +70,10 @@ struct token *skip_to(struct token *token, int op)
return token;
}
+static struct token bad_token = { .pos.type = TOKEN_BAD };
struct token *expect(struct token *token, int op, const char *where)
{
if (!match_op(token, op)) {
- static struct token bad_token;
if (token != &bad_token) {
bad_token.next = token;
sparse_error(token->pos, "Expected %s %s", show_special(op), where);
@@ -86,6 +86,21 @@ struct token *expect(struct token *token, int op, const char *where)
return token->next;
}
+///
+// issue an error message on new parsing errors
+// @token: the current token
+// @errmsg: the error message
+// If the current token is from a previous error, an error message
+// has already been issued, so nothing more is done.
+// Otherwise, @errmsg is displayed followed by the current token.
+void unexpected(struct token *token, const char *errmsg)
+{
+ if (token == &bad_token)
+ return;
+ sparse_error(token->pos, "%s", errmsg);
+ sparse_error(token->pos, "got %s", show_token(token));
+}
+
unsigned int hexval(unsigned int c)
{
int retval = 256;
@@ -108,6 +123,10 @@ static void do_warn(const char *type, struct position pos, const char * fmt, va_
static char buffer[512];
const char *name;
+ /* Shut up warnings if position is bad_token.pos */
+ if (pos.type == TOKEN_BAD)
+ return;
+
vsprintf(buffer, fmt, args);
name = stream_name(pos.stream);
@@ -135,6 +154,9 @@ static void do_error(struct position pos, const char * fmt, va_list args)
static int errors = 0;
die_if_error = 1;
show_info = 1;
+ /* Shut up warnings if position is bad_token.pos */
+ if (pos.type == TOKEN_BAD)
+ return;
/* Shut up warnings after an error */
has_error |= ERROR_CURR_PHASE;
if (errors > 100) {
diff --git a/lib.h b/lib.h
index aea46741..d7bd3651 100644
--- a/lib.h
+++ b/lib.h
@@ -83,6 +83,8 @@ typedef struct pseudo *pseudo_t;
struct token *skip_to(struct token *, int);
struct token *expect(struct token *, int, const char *);
+void unexpected(struct token *, const char *errmsg);
+
#ifdef __GNUC__
#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
#define NORETURN_ATTR __attribute__ ((__noreturn__))
diff --git a/linearize.c b/linearize.c
index 88f6c094..6284d079 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1777,12 +1777,8 @@ static pseudo_t linearize_context(struct entrypoint *ep, struct statement *stmt)
{
struct instruction *insn = alloc_instruction(OP_CONTEXT, 0);
struct expression *expr = stmt->expression;
- int value = 0;
- if (expr->type == EXPR_VALUE)
- value = expr->value;
-
- insn->increment = value;
+ insn->increment = get_expression_value(expr);
insn->context_expr = stmt->context;
add_one_insn(ep, insn);
return VOID;
diff --git a/parse.c b/parse.c
index 1f5fa3a4..270ab7bf 100644
--- a/parse.c
+++ b/parse.c
@@ -1133,43 +1133,24 @@ static struct token *attribute_context(struct token *token, struct symbol *attr,
{
struct context *context = alloc_context();
struct expression *args[3];
- int argc = 0;
+ int idx = 0;
token = expect(token, '(', "after context attribute");
- while (!match_op(token, ')')) {
- struct expression *expr = NULL;
- token = conditional_expression(token, &expr);
- if (!expr)
- break;
- if (argc < 3)
- args[argc++] = expr;
- if (!match_op(token, ','))
- break;
+ token = conditional_expression(token, &args[0]);
+ token = expect(token, ',', "after context 1st argument");
+ token = conditional_expression(token, &args[1]);
+ if (match_op(token, ',')) {
token = token->next;
- }
-
- switch(argc) {
- case 0:
- sparse_error(token->pos, "expected context input/output values");
- break;
- case 1:
- context->in = get_expression_value(args[0]);
- break;
- case 2:
- context->in = get_expression_value(args[0]);
- context->out = get_expression_value(args[1]);
- break;
- case 3:
+ token = conditional_expression(token, &args[2]);
+ token = expect(token, ')', "after context 3rd argument");
context->context = args[0];
- context->in = get_expression_value(args[1]);
- context->out = get_expression_value(args[2]);
- break;
+ idx++;
+ } else {
+ token = expect(token, ')', "after context 2nd argument");
}
-
- if (argc)
- add_ptr_list(&ctx->ctype.contexts, context);
-
- token = expect(token, ')', "after context attribute");
+ context->in = get_expression_value(args[idx++]);
+ context->out = get_expression_value(args[idx++]);
+ add_ptr_list(&ctx->ctype.contexts, context);
return token;
}
@@ -2357,15 +2338,19 @@ static struct token *parse_goto_statement(struct token *token, struct statement
static struct token *parse_context_statement(struct token *token, struct statement *stmt)
{
stmt->type = STMT_CONTEXT;
- token = parse_expression(token->next, &stmt->expression);
- if (stmt->expression->type == EXPR_PREOP
- && stmt->expression->op == '('
- && stmt->expression->unop->type == EXPR_COMMA) {
- struct expression *expr;
- expr = stmt->expression->unop;
- stmt->context = expr->left;
- stmt->expression = expr->right;
+ token = token->next;
+ token = expect(token, '(', "after __context__ statement");
+ token = assignment_expression(token, &stmt->expression);
+ if (!stmt->expression)
+ unexpected(token, "expression expected after '('");
+ if (match_op(token, ',')) {
+ token = token->next;
+ stmt->context = stmt->expression;
+ token = assignment_expression(token, &stmt->expression);
+ if (!stmt->expression)
+ unexpected(token, "expression expected after ','");
}
+ token = expect(token, ')', "at end of __context__ statement");
return expect(token, ';', "at end of statement");
}
diff --git a/token.h b/token.h
index 847fdf4d..292db167 100644
--- a/token.h
+++ b/token.h
@@ -79,6 +79,7 @@ struct ident {
enum token_type {
TOKEN_EOF,
+ TOKEN_BAD,
TOKEN_ERROR,
TOKEN_IDENT,
TOKEN_ZERO_IDENT,
diff --git a/tokenize.c b/tokenize.c
index aa4dc184..1118786f 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -444,6 +444,7 @@ static struct token *mark_eof(stream_t *stream)
struct token *end;
end = alloc_token(stream);
+ eof_token_entry.pos = end->pos;
token_type(end) = TOKEN_STREAMEND;
end->pos.newline = 1;
diff --git a/validation/attr-context.c b/validation/attr-context.c
new file mode 100644
index 00000000..00e54c66
--- /dev/null
+++ b/validation/attr-context.c
@@ -0,0 +1,40 @@
+static void a(void) __attribute__((context)); // KO
+static void b(void) __attribute__((context())); // KO
+static void c(void) __attribute__((context 1)); // KO
+static void d(void) __attribute__((context 1,2)); // KO
+static void e(void) __attribute__((context (1))); // !!!!
+static void f(void) __attribute__((context(0))); // !!!!
+static void g(void) __attribute__((context(0,1,2,3))); // KO
+
+static void h(void) __attribute__((context (1,2))); // OK
+static void i(void) __attribute__((context(0,1))); // OK
+static void j(void) __attribute__((context(0,1,2))); // OK
+
+extern int u, v;
+static void x(void) __attribute__((context(0,1,v)));
+static void y(void) __attribute__((context(0,u,1)));
+static void z(void) __attribute__((context(0,u)));
+
+/*
+ * check-name: attr-context
+ *
+ * check-error-start
+attr-context.c:1:43: error: Expected ( after context attribute
+attr-context.c:1:43: error: got )
+attr-context.c:2:44: error: Expected , after context 1st argument
+attr-context.c:2:44: error: got )
+attr-context.c:3:44: error: Expected ( after context attribute
+attr-context.c:3:44: error: got 1
+attr-context.c:4:44: error: Expected ( after context attribute
+attr-context.c:4:44: error: got 1
+attr-context.c:5:46: error: Expected , after context 1st argument
+attr-context.c:5:46: error: got )
+attr-context.c:6:45: error: Expected , after context 1st argument
+attr-context.c:6:45: error: got )
+attr-context.c:7:49: error: Expected ) after context 3rd argument
+attr-context.c:7:49: error: got ,
+attr-context.c:14:48: error: bad constant expression
+attr-context.c:15:46: error: bad constant expression
+attr-context.c:16:46: error: bad constant expression
+ * check-error-end
+ */
diff --git a/validation/check_byte_count-ice.c b/validation/check_byte_count-ice.c
index 7b85b963..dae40c67 100644
--- a/validation/check_byte_count-ice.c
+++ b/validation/check_byte_count-ice.c
@@ -12,8 +12,8 @@ check_byte_count-ice.c:6:0: warning: Newline in string or character constant
check_byte_count-ice.c:5:23: warning: multi-character character constant
check_byte_count-ice.c:6:1: error: Expected ) in function call
check_byte_count-ice.c:6:1: error: got }
-builtin:0:0: error: Expected } at end of function
-builtin:0:0: error: got end-of-input
+check_byte_count-ice.c:20:0: error: Expected } at end of function
+check_byte_count-ice.c:20:0: error: got end-of-input
check_byte_count-ice.c:5:15: error: not enough arguments for function memset
* check-error-end
*/
diff --git a/validation/context-stmt.c b/validation/context-stmt.c
new file mode 100644
index 00000000..2884a8a2
--- /dev/null
+++ b/validation/context-stmt.c
@@ -0,0 +1,62 @@
+static void foo(int x)
+{
+ __context__(0); // OK
+ __context__(x, 0); // OK
+ __context__ (x, 1); // OK
+
+ __context__(x); // KO: no const expr
+ __context__(1,x); // KO: no const expr
+
+ __context__; // KO: no expression at all
+ __context__(; // KO: no expression at all
+
+ __context__ 0; // KO: need parens
+ __context__ x, 0; // KO: need parens
+ __context__(x, 0; // KO: unmatched parens
+ __context__ x, 0); // KO: unmatched parens
+ __context__(0; // KO: unmatched parens
+ __context__ 0); // KO: unmatched parens
+
+ __context__(); // KO: no expression at all
+ __context__(,0); // KO: no expression at all
+ __context__(x,); // KO: no expression at all
+ __context__(,); // KO: no expression at all
+}
+
+/*
+ * check-name: context-stmt
+ * check-command: sparse -Wno-context $file
+ *
+ * check-error-start
+context-stmt.c:10:20: error: Expected ( after __context__ statement
+context-stmt.c:10:20: error: got ;
+context-stmt.c:11:21: error: expression expected after '('
+context-stmt.c:11:21: error: got ;
+context-stmt.c:11:21: error: Expected ) at end of __context__ statement
+context-stmt.c:11:21: error: got ;
+context-stmt.c:13:21: error: Expected ( after __context__ statement
+context-stmt.c:13:21: error: got 0
+context-stmt.c:14:21: error: Expected ( after __context__ statement
+context-stmt.c:14:21: error: got x
+context-stmt.c:15:25: error: Expected ) at end of __context__ statement
+context-stmt.c:15:25: error: got ;
+context-stmt.c:16:21: error: Expected ( after __context__ statement
+context-stmt.c:16:21: error: got x
+context-stmt.c:17:22: error: Expected ) at end of __context__ statement
+context-stmt.c:17:22: error: got ;
+context-stmt.c:18:21: error: Expected ( after __context__ statement
+context-stmt.c:18:21: error: got 0
+context-stmt.c:20:21: error: expression expected after '('
+context-stmt.c:20:21: error: got )
+context-stmt.c:21:21: error: expression expected after '('
+context-stmt.c:21:21: error: got ,
+context-stmt.c:22:23: error: expression expected after ','
+context-stmt.c:22:23: error: got )
+context-stmt.c:23:21: error: expression expected after '('
+context-stmt.c:23:21: error: got ,
+context-stmt.c:23:22: error: expression expected after ','
+context-stmt.c:23:22: error: got )
+context-stmt.c:7:21: error: bad constant expression
+context-stmt.c:8:23: error: bad constant expression
+ * check-error-end
+ */
diff --git a/validation/error-at-eof.c b/validation/error-at-eof.c
new file mode 100644
index 00000000..7d933651
--- /dev/null
+++ b/validation/error-at-eof.c
@@ -0,0 +1,10 @@
+/*
+ * check-name: error-at-eof
+ *
+ * check-error-start
+error-at-eof.c:11:0: error: Expected ; at end of declaration
+error-at-eof.c:11:0: error: got end-of-input
+ * check-error-end
+ */
+
+int a
diff --git a/validation/expand/builtin-expect.c b/validation/expand/builtin-expect.c
new file mode 100644
index 00000000..a80176a5
--- /dev/null
+++ b/validation/expand/builtin-expect.c
@@ -0,0 +1,101 @@
+int flia(long a)
+{
+ return __builtin_expect(a, 1);
+}
+
+int flic(void)
+{
+ return __builtin_expect(1L << 32 | 1, 1);
+}
+
+long fila(int a)
+{
+ return __builtin_expect(a, 1);
+}
+
+long filc(void)
+{
+ return __builtin_expect(1L << 32 | 1, 1);
+}
+
+long filu(void)
+{
+ return __builtin_expect(0x80000000U, 1);
+}
+
+long fils(void)
+{
+ return __builtin_expect((int)0x80000000, 1);
+}
+
+void *fptr(void *a)
+{
+ return __builtin_expect(a, a);
+}
+
+/*
+ * check-name: builtin-expect
+ * check-command: test-linearize -m64 -Wno-decl $file
+ *
+ * check-output-start
+flia:
+.L0:
+ <entry-point>
+ scast.32 %r2 <- (64) %arg1
+ ret.32 %r2
+
+
+flic:
+.L2:
+ <entry-point>
+ ret.32 $1
+
+
+fila:
+.L4:
+ <entry-point>
+ scast.64 %r6 <- (32) %arg1
+ ret.64 %r6
+
+
+filc:
+.L6:
+ <entry-point>
+ ret.64 $0x100000001
+
+
+filu:
+.L8:
+ <entry-point>
+ ret.64 $0x80000000
+
+
+fils:
+.L10:
+ <entry-point>
+ ret.64 $0xffffffff80000000
+
+
+fptr:
+.L12:
+ <entry-point>
+ cast.64 %r12 <- (64) %arg1
+ scast.64 %r13 <- (64) %r12
+ ret.64 %r13
+
+
+ * check-output-end
+ *
+ * check-error-start
+expand/builtin-expect.c:33:33: warning: incorrect type in argument 1 (different base types)
+expand/builtin-expect.c:33:33: expected long [signed] <noident>
+expand/builtin-expect.c:33:33: got void *a
+expand/builtin-expect.c:33:36: warning: incorrect type in argument 2 (different base types)
+expand/builtin-expect.c:33:36: expected long [signed] <noident>
+expand/builtin-expect.c:33:36: got void *a
+expand/builtin-expect.c:33:32: warning: incorrect type in return expression (different base types)
+expand/builtin-expect.c:33:32: expected void *
+expand/builtin-expect.c:33:32: got long
+expand/builtin-expect.c:8:42: warning: cast truncates bits from constant value (100000001 becomes 1)
+ * check-error-end
+ */
diff --git a/validation/goto-reserved.c b/validation/goto-reserved.c
new file mode 100644
index 00000000..fbaf03e1
--- /dev/null
+++ b/validation/goto-reserved.c
@@ -0,0 +1,12 @@
+static void foo(void)
+{
+ goto return;
+}
+
+/*
+ * check-name: goto-reserved
+ *
+ * check-error-start
+goto-reserved.c:3:14: error: Trying to use reserved word 'return' as identifier
+ * check-error-end
+ */
diff --git a/validation/integer-const-expr.c b/validation/integer-const-expr.c
new file mode 100644
index 00000000..f41aa806
--- /dev/null
+++ b/validation/integer-const-expr.c
@@ -0,0 +1,85 @@
+extern void *malloc(unsigned long);
+
+static inline __attribute__((__const__)) unsigned squarec(unsigned n)
+{
+ return n*n;
+}
+
+static inline unsigned square(unsigned n)
+{
+ return n*n;
+}
+
+static inline unsigned long long bignum(void)
+{
+ return 1000000000000ULL;
+}
+
+static inline __attribute__((__const__)) unsigned long long bignumc(void)
+{
+ return 1000000000000ULL;
+}
+
+// test if x is an integer constant expression [C99,C11 6.6p6]
+#define ICE_P(x) \
+ (__builtin_types_compatible_p(typeof(0?((void*)((long)(x)*0l)):(int*)1),int*))
+
+#define CHX_P(X) __builtin_choose_expr(ICE_P(X), 1, 0)
+#define CST_P(X) __builtin_constant_p(ICE_P(X))
+
+#define TEST(R, X) _Static_assert(ICE_P(X) == R, "ICE_P(" #X ") => " #R); \
+ _Static_assert(ICE_P(ICE_P(X)), "ICE_P2(" #X ")"); \
+ _Static_assert(CHX_P(X) == R, "CHX_P(" #X ") => " #R); \
+ _Static_assert(CST_P(X) == 1, "CST_P(" #X ")")
+
+int main(int argc, char *argv[])
+{
+ char fla[3];
+ char vla[argc++];
+ char **p, **q;
+ int x = 5, y = 8;
+ void *v;
+
+ p = &argv[3];
+ q = &argv[6];
+
+ TEST(1, 4);
+ TEST(1, sizeof(long));
+ TEST(1, 5ull - 3u);
+ TEST(1, 3.2);
+ TEST(1, sizeof(fla));
+
+ TEST(0, square(2));
+ TEST(0, square(argc));
+ TEST(0, squarec(2));
+ TEST(0, squarec(argc));
+ TEST(0, 1+argc-argc);
+ TEST(0, 1+argc+argc+1-argc-argc);
+ TEST(0, bignum() - 1);
+ TEST(0, 0*bignum());
+ TEST(0, 0*bignumc());
+ TEST(0, sizeof(vla));
+ TEST(0, p);
+ TEST(0, p < q);
+ TEST(0, p++);
+ TEST(0, main);
+ TEST(0, malloc(8));
+ TEST(0, v = malloc(8));
+ TEST(0, v);
+ TEST(0, x++);
+ TEST(0, y++);
+ TEST(0, (3, 2, 1));
+ TEST(0, ({x++; 0; }));
+ TEST(0, ({square(y--); 0; }));
+ TEST(0, (square(x), 3));
+ TEST(0, (squarec(x), 3));
+ TEST(0, ({squarec(x); 3;}));
+ TEST(0, ({squarec(x);}));
+
+ return 0;
+}
+
+/*
+ * check-name: integer-const-expr
+ * check-command: sparse -Wno-vla $file
+ */
diff --git a/validation/vla-sizeof-ice.c b/validation/vla-sizeof-ice.c
new file mode 100644
index 00000000..472da6a4
--- /dev/null
+++ b/validation/vla-sizeof-ice.c
@@ -0,0 +1,19 @@
+// credit goes to Martin Uecker for the awesome ICE_P macro
+
+#define ICE_P(x) \
+ (__builtin_types_compatible_p(typeof(0?((void*)((long)(x)*0l)):(int*)1),int*))
+
+#define T(x) __builtin_choose_expr(ICE_P(x), 1, 0)
+#define TEST(x, r) _Static_assert(T(x) == r, #x " => " #r)
+
+static void test(int n)
+{
+ char foo[n++];
+
+ TEST(sizeof(foo), 0);
+}
+
+/*
+ * check-name: vla-sizeof-ice
+ * check-command: sparse -Wno-vla $file
+ */
diff --git a/validation/vla-sizeof0.c b/validation/vla-sizeof0.c
new file mode 100644
index 00000000..a58fd300
--- /dev/null
+++ b/validation/vla-sizeof0.c
@@ -0,0 +1,20 @@
+#define N 2
+#define T int
+
+static unsigned int foo(int x)
+{
+ T a[(1,N)];
+
+ return sizeof(a) == (N * sizeof(T));
+}
+
+/*
+ * check-name: vla-sizeof cte,cte
+ * check-command: test-linearize -Wvla $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\.32 *\\$1
+ *
+ * check-error-start
+ * check-error-end
+ */
diff --git a/validation/vla-sizeof1.c b/validation/vla-sizeof1.c
new file mode 100644
index 00000000..ed7f5d4e
--- /dev/null
+++ b/validation/vla-sizeof1.c
@@ -0,0 +1,21 @@
+#define N 2
+#define T int
+
+static unsigned int foo(int x)
+{
+ T a[(x,N)];
+
+ return sizeof(a) == (N * sizeof(T));
+}
+
+/*
+ * check-name: vla-sizeof var,cte
+ * check-command: test-linearize -Wvla $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\.32 *\\$1
+ *
+ * check-error-start
+vla-sizeof1.c:6:15: warning: Variable length array is used.
+ * check-error-end
+ */
diff --git a/validation/vla-sizeof2.c b/validation/vla-sizeof2.c
new file mode 100644
index 00000000..57927d16
--- /dev/null
+++ b/validation/vla-sizeof2.c
@@ -0,0 +1,21 @@
+#define N 2
+#define T int
+
+static unsigned long foo(int x)
+{
+ T a[x];
+
+ return sizeof(a) == (x * sizeof(T));
+}
+
+/*
+ * check-name: vla-sizeof var
+ * check-command: test-linearize -Wvla $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ *
+ * check-error-start
+vla-sizeof2.c:6:13: warning: Variable length array is used.
+ * check-error-end
+ */
diff --git a/validation/vla-sizeof3.c b/validation/vla-sizeof3.c
new file mode 100644
index 00000000..21edb007
--- /dev/null
+++ b/validation/vla-sizeof3.c
@@ -0,0 +1,21 @@
+#define N 2UL
+#define T int
+
+static unsigned long foo(int x)
+{
+ T a[x][N];
+
+ return sizeof(a) == (N * x * sizeof(T));
+}
+
+/*
+ * check-name: vla-sizeof var X cte
+ * check-command: test-linearize -Wvla $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ *
+ * check-error-start
+vla-sizeof3.c:6:13: warning: Variable length array is used.
+ * check-error-end
+ */
diff --git a/validation/vla-sizeof4.c b/validation/vla-sizeof4.c
new file mode 100644
index 00000000..e7478613
--- /dev/null
+++ b/validation/vla-sizeof4.c
@@ -0,0 +1,22 @@
+#define N 2
+#define T int
+
+static unsigned long foo(int x, int y)
+{
+ T a[x][y];
+
+ return sizeof(a) == (x * (y * sizeof(T)));
+}
+
+/*
+ * check-name: vla-sizeof var X var
+ * check-command: test-linearize -Wvla $file
+ *
+ * check-output-ignore
+ * check-output-contains: ret\\..*\\$1
+ *
+ * check-error-start
+vla-sizeof4.c:6:16: warning: Variable length array is used.
+vla-sizeof4.c:6:13: warning: Variable length array is used.
+ * check-error-end
+ */