aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--evaluate.c32
-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
7 files changed, 156 insertions, 0 deletions
diff --git a/evaluate.c b/evaluate.c
index edace120..7d2dc516 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");
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
+ */