aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2009-10-11 22:51:56 +0000
committerChristopher <sparse@chrisli.org>2010-03-28 17:51:36 -0700
commitf09699fa80b3b15b94b3e1878ac6cdfdb48f43ac (patch)
treee29fe5fb76dbba97a7dad2eda54de4a694c53a51 /validation
parentRename -Wall to Wsparse-all, so it doesn't get turned on unintentionally (diff)
downloadsparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.tar.gz
sparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.tar.bz2
sparse-f09699fa80b3b15b94b3e1878ac6cdfdb48f43ac.zip
New attribute designated_init: mark a struct as requiring designated init
Some structure types provide a set of fields of which most users will only initialize the subset they care about. Users of these types should always use designated initializers, to avoid relying on the specific structure layout. Examples of this type of structure include the many *_operations structures in Linux, which contain a set of function pointers; these structures occasionally gain a new field, lose an obsolete field, or change the function signature for a field. Add a new attribute designated_init; when used on a struct, it tells Sparse to warn on any positional initialization of a field in that struct. The new flag -Wdesignated-init controls these warnings. Since these warnings only fire for structures explicitly tagged with the attribute, enable the warning by default. Includes documentation and test case. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Signed-off-by: Christopher Li <sparse@chrisli.org>
Diffstat (limited to 'validation')
-rw-r--r--validation/designated-init.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/validation/designated-init.c b/validation/designated-init.c
new file mode 100644
index 0000000..23423e9
--- /dev/null
+++ b/validation/designated-init.c
@@ -0,0 +1,195 @@
+struct s1 {
+ int x;
+ int y;
+};
+
+struct s2 {
+ int x;
+ int y;
+} __attribute__((designated_init));
+
+struct nest1 {
+ struct s1 s1;
+ struct s2 s2;
+};
+
+struct nest2 {
+ struct s1 s1;
+ struct s2 s2;
+} __attribute__((designated_init));
+
+static struct s1 s1_positional = { 5, 10 };
+static struct s1 s1_designated = { .x = 5, .y = 10 };
+static struct s2 s2_positional = { 5, 10 };
+static struct s2 s2_designated = { .x = 5, .y = 10 };
+static struct nest1 nest1_positional = {
+ { 5, 10 },
+ { 5, 10 },
+};
+static struct nest1 nest1_designated_outer = {
+ .s1 = { 5, 10 },
+ .s2 = { 5, 10 },
+};
+static struct nest1 nest1_designated_inner = {
+ { .x = 5, .y = 10 },
+ { .x = 5, .y = 10 },
+};
+static struct nest1 nest1_designated_both = {
+ .s1 = { .x = 5, .y = 10 },
+ .s2 = { .x = 5, .y = 10 },
+};
+static struct nest2 nest2_positional = {
+ { 5, 10 },
+ { 5, 10 },
+};
+static struct nest2 nest2_designated_outer = {
+ .s1 = { 5, 10 },
+ .s2 = { 5, 10 },
+};
+static struct nest2 nest2_designated_inner = {
+ { .x = 5, .y = 10 },
+ { .x = 5, .y = 10 },
+};
+static struct nest2 nest2_designated_both = {
+ .s1 = { .x = 5, .y = 10 },
+ .s2 = { .x = 5, .y = 10 },
+};
+
+static struct {
+ int x;
+ int y;
+} __attribute__((designated_init))
+ anon_positional = { 5, 10 },
+ anon_designated = { .x = 5, .y = 10};
+
+static struct s1 s1_array[] = {
+ { 5, 10 },
+ { .x = 5, .y = 10 },
+};
+
+static struct s2 s2_array[] = {
+ { 5, 10 },
+ { .x = 5, .y = 10 },
+};
+
+static struct s1 ret_s1_positional(void)
+{
+ return ((struct s1){ 5, 10 });
+}
+
+static struct s1 ret_s1_designated(void)
+{
+ return ((struct s1){ .x = 5, .y = 10 });
+}
+
+static struct s2 ret_s2_positional(void)
+{
+ return ((struct s2){ 5, 10 });
+}
+
+static struct s2 ret_s2_designated(void)
+{
+ return ((struct s2){ .x = 5, .y = 10 });
+}
+
+static struct nest1 ret_nest1_positional(void)
+{
+ return ((struct nest1){
+ { 5, 10 },
+ { 5, 10 },
+ });
+}
+
+static struct nest1 ret_nest1_designated_outer(void)
+{
+ return ((struct nest1){
+ .s1 = { 5, 10 },
+ .s2 = { 5, 10 },
+ });
+}
+
+static struct nest1 ret_nest1_designated_inner(void)
+{
+ return ((struct nest1){
+ { .x = 5, .y = 10 },
+ { .x = 5, .y = 10 },
+ });
+}
+
+static struct nest1 ret_nest1_designated_both(void)
+{
+ return ((struct nest1){
+ .s1 = { .x = 5, .y = 10 },
+ .s2 = { .x = 5, .y = 10 },
+ });
+}
+
+static struct nest2 ret_nest2_positional(void)
+{
+ return ((struct nest2){
+ { 5, 10 },
+ { 5, 10 },
+ });
+}
+
+static struct nest2 ret_nest2_designated_outer(void)
+{
+ return ((struct nest2){
+ .s1 = { 5, 10 },
+ .s2 = { 5, 10 },
+ });
+}
+
+static struct nest2 ret_nest2_designated_inner(void)
+{
+ return ((struct nest2){
+ { .x = 5, .y = 10 },
+ { .x = 5, .y = 10 },
+ });
+}
+
+static struct nest2 ret_nest2_designated_both(void)
+{
+ return ((struct nest2){
+ .s1 = { .x = 5, .y = 10 },
+ .s2 = { .x = 5, .y = 10 },
+ });
+}
+/*
+ * check-name: designated_init attribute
+ *
+ * check-error-start
+designated-init.c:23:36: warning: in initializer for s2_positional: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:23:39: warning: in initializer for s2_positional: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:27:11: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:27:14: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:31:17: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:31:20: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:42:9: warning: in initializer for nest2_positional: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:43:9: warning: in initializer for nest2_positional: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:43:11: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:43:14: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:47:17: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:47:20: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:50:9: warning: in initializer for nest2_designated_inner: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:51:9: warning: in initializer for nest2_designated_inner: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:62:29: warning: in initializer for anon_positional: positional init of field in struct <noident>, declared with attribute designated_init
+designated-init.c:62:32: warning: in initializer for anon_positional: positional init of field in struct <noident>, declared with attribute designated_init
+designated-init.c:71:11: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:71:14: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:87:30: warning: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:87:33: warning: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:99:27: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:99:30: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:107:33: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:107:36: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:130:25: warning: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:131:25: warning: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:131:27: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:131:30: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:139:33: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:139:36: warning: in initializer for s2: positional init of field in struct s2, declared with attribute designated_init
+designated-init.c:146:25: warning: positional init of field in struct nest2, declared with attribute designated_init
+designated-init.c:147:25: warning: positional init of field in struct nest2, declared with attribute designated_init
+ * check-error-end
+ */