All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nicolai Stange <nicstange@gmail.com>
To: linux-sparse@vger.kernel.org
Subject: [PATCH RFC 07/13] evaluate: check static storage duration objects' intializers' constness
Date: Thu, 23 Jul 2015 01:19:09 +0200	[thread overview]
Message-ID: <871tfzkcgi.fsf@gmail.com> (raw)

Initializers of static storage duration objects shall be constant
expressions [6.7.8(4)].

Warn if that requirement is not met.

Identify static storage duration objects by having either of
MOD_TOPLEVEL or MOD_STATIC set.

Check an initializer's constness at the lowest possible subobject
level, i.e. at the level of the "assignment-expression" production
in [6.7.8].

For compound objects, make handle_list_initializer() pass the
surrounding object's storage duration modifiers down to
handle_simple_initializer() at subobject initializer evaluation.

Signed-off-by: Nicolai Stange <nicstange@gmail.com>
---
 evaluate.c                  |  25 +++++++++-
 validation/constexpr-init.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 validation/constexpr-init.c

diff --git a/evaluate.c b/evaluate.c
index c38b893..a65cc0c 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -2466,6 +2466,7 @@ static void handle_list_initializer(struct expression *expr,
 {
 	struct expression *e, *last = NULL, *top = NULL, *next;
 	int jumped = 0;
+	unsigned long old_modifiers;
 
 	FOR_EACH_PTR(expr->expr_list, e) {
 		struct expression **v;
@@ -2520,8 +2521,21 @@ found:
 		else
 			v = &top->ident_expression;
 
-		if (handle_simple_initializer(v, 1, lclass, top->ctype))
+		/*
+		 * Temporarily copy storage modifiers down from
+		 * surrounding type such that
+		 * handle_simple_initializer() can check
+		 * initializations of subobjects with static storage
+		 * duration.
+		 */
+		old_modifiers = top->ctype->ctype.modifiers;
+		top->ctype->ctype.modifiers =
+			old_modifiers | (ctype->ctype.modifiers & MOD_STORAGE);
+		if (handle_simple_initializer(v, 1, lclass, top->ctype)) {
+			top->ctype->ctype.modifiers = old_modifiers;
 			continue;
+		}
+		top->ctype->ctype.modifiers = old_modifiers;
 
 		if (!(lclass & TYPE_COMPOUND)) {
 			warning(e->pos, "bogus scalar initializer");
@@ -2631,6 +2645,15 @@ static int handle_simple_initializer(struct expression **ep, int nested,
 		if (!evaluate_expression(e))
 			return 1;
 		compatible_assignment_types(e, ctype, ep, "initializer");
+		/*
+		 * Initializers for static storage duration objects
+		 * shall be constant expressions or a string literal [6.7.8(4)].
+		 */
+		if ((ctype->ctype.modifiers & (MOD_TOPLEVEL | MOD_STATIC)) &&
+			!(e->flags & (EXPR_FLAG_ARITH_CONST_EXPR
+					| EXPR_FLAG_ADDR_CONST_EXPR)))
+			warning(e->pos, "initializer for static storage duration object is not a constant expression");
+
 		return 1;
 	}
 
diff --git a/validation/constexpr-init.c b/validation/constexpr-init.c
new file mode 100644
index 0000000..6c412b8
--- /dev/null
+++ b/validation/constexpr-init.c
@@ -0,0 +1,109 @@
+static int a = 1;					// OK
+static int b[2] = {1, 1};				// OK
+static void c(void) {}
+
+static int *d = &a;					// OK
+static int *e = &b[1];					// OK
+static int *f = b;					// OK
+static void (*g)(void) = c;				// OK
+static void (*h)(void) = &c;				// OK
+static int *i = (int*)0;				// OK
+static int *j = d;					// KO
+static int *k = (int*)0 + 1;				// OK
+
+static int *l = &a + 1;				// OK
+static int *m = &b[1] + 1;				// OK
+static int *n = b + 1;					// OK
+static int *o = d + 1;					// KO
+
+static int *p = &*&a;					// OK
+static int *q = &*&b[1];				// OK
+static int *r = &*b;					// OK
+static int *s = &*d;					// KO
+
+static int *t = &*(&a + 1);				// OK
+static int *u = &*(&b[1] + 1);				// OK
+static int *v = &*(b + 1);				// OK
+static int *w = &*(d + 1);				// KO
+
+
+struct A {
+	int a;
+	int b[2];
+};
+
+struct B {
+	int c;
+	struct A d;
+};
+
+static struct B x= {1, {1, {1, 1}}};				// OK
+static struct B y= {a, {1, {1, 1}}};				// KO
+static struct B z= {1, {a, {1, 1}}};				// KO
+static struct B aa= {1, {1, {a, 1}}};				// KO
+static struct B ab= {1, {1, {1, a}}};				// KO
+static struct B ac= {.c = 1, .d = {.a = 1, .b = {1, 1}}};	// OK
+static struct B ad= {.c = a, .d = {.a = 1, .b = {1, 1}}};	// KO
+static struct B ae= {.c = 1, .d = {.a = a, .b = {1, 1}}};	// KO
+static struct B af= {.c = 1, .d = {.a = 1, .b = {a, 1}}};	// KO
+static struct B ag= {.c = 1, .d = {.a = 1, .b = {1, a}}};	// KO
+
+static int *ah = &x.d.a;		// OK
+static int *ai = &(&x.d)->a;		// OK
+static int *aj = x.d.b;		// OK
+static int *ak = (&x.d)->b;		// OK
+static int *al = &x.d.b[1];		// OK
+static int *am = &(&x.d)->b[1];	// OK
+
+static int an[] = {a, 1};				// KO
+static int ao[] = {1, a};				// KO
+static int ap[] = {[0] = a, [1] = 1};			// KO
+static int aq[] = {[0] = 1, [1] = a};			// KO
+
+static char *ar = "foobar";				// OK
+
+static void as(void) {
+	int a = 0;
+	int b = a;		// OK
+}
+
+static void at(void) {
+	int a = 1;
+	static int b = a;	// KO
+}
+
+static void au(void) {
+	int a = 1;
+	static int *b = &a;	// KO
+}
+
+static void av(void) {
+	static int a = 1;
+	static int *b = &a;	// OK
+}
+
+
+/*
+ * check-name: Static storage object initializer constness verification.
+ *
+ * check-error-start
+constexpr-init.c:11:17: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:17:19: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:22:19: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:27:22: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:41:21: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:42:25: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:43:30: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:44:33: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:46:27: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:47:41: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:48:50: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:49:53: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:58:20: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:59:23: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:60:26: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:61:35: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:72:24: warning: initializer for static storage duration object is not a constant expression
+constexpr-init.c:77:26: warning: initializer for static storage duration object is not a constant expression
+ * check-error-end
+ */
-- 
2.4.5


             reply	other threads:[~2015-07-22 23:19 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-22 23:19 Nicolai Stange [this message]
2016-01-09 18:04 ` [PATCH RFC 07/13] evaluate: check static storage duration objects' intializers' constness Luc Van Oostenryck
2016-01-09 22:28   ` Nicolai Stange
2016-01-11 18:02     ` Luc Van Oostenryck
2016-01-11 18:15       ` Nicolai Stange
2016-01-11 19:28         ` Josh Triplett
2016-12-08  4:48           ` [PATCH] Update maintainers in the manpage Luc Van Oostenryck
2016-12-08  5:43             ` Josh Triplett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=871tfzkcgi.fsf@gmail.com \
    --to=nicstange@gmail.com \
    --cc=linux-sparse@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.