1 /* $NetBSD: lsym_tag.c,v 1.10 2023/06/17 22:09:24 rillig Exp $ */ 2 3 /* 4 * Tests for the token lsym_tag, which represents one of the keywords 5 * 'struct', 'union' or 'enum' that declare, define or use a tagged type. 6 */ 7 8 /* TODO: Add systematic tests for 'struct'. */ 9 /* TODO: Add systematic tests for 'union'. */ 10 /* TODO: Add systematic tests for 'enum'. */ 11 12 13 //indent input 14 int 15 indent_enum_constants(void) 16 { 17 enum color { 18 red, 19 green 20 }; 21 enum color colors[] = { 22 red, 23 red, 24 red, 25 }; 26 /* 27 * Ensure that the token sequence 'enum type {' only matches if there 28 * are no other tokens in between, to prevent statement continuations 29 * from being indented like enum constant declarations. 30 * 31 * See https://gnats.netbsd.org/55453. 32 */ 33 if (colors[0] == (enum color)1) { 34 return 1 35 + 2 36 + 3; 37 } 38 return 0; 39 } 40 //indent end 41 42 //indent run-equals-input -ci2 43 44 45 //indent input 46 struct stat { 47 mode_t st_mode; 48 }; 49 50 union variant { 51 enum { 52 } tag; 53 int v_int; 54 long v_long; 55 bool v_bool; 56 void *v_pointer; 57 }; 58 //indent end 59 60 //indent run-equals-input 61 62 63 /* See FreeBSD r303485. */ 64 //indent input 65 int f(struct x *a); 66 67 void 68 t(void) 69 { 70 static const struct { 71 int a; 72 int b; 73 } c[] = { 74 { D, E }, 75 { F, G } 76 }; 77 } 78 79 void u(struct x a) { 80 int b; 81 struct y c = (struct y *)&a; 82 } 83 //indent end 84 85 //indent run 86 int f(struct x *a); 87 88 void 89 t(void) 90 { 91 static const struct { 92 int a; 93 int b; 94 } c[] = { 95 {D, E}, 96 {F, G} 97 }; 98 } 99 100 void 101 u(struct x a) 102 { 103 int b; 104 struct y c = (struct y *)&a; 105 } 106 //indent end 107 108 109 /* Comment between 'struct' and the tag name; doesn't occur in practice. */ 110 //indent input 111 struct /* comment */ tag var; 112 //indent end 113 114 //indent run -di0 115 struct /* comment */ tag var; 116 //indent end 117 118 119 /* 120 * Ensure that the names of struct members are all indented the same. 121 * Before 2023-05-15, the indentation depended on their type name. 122 */ 123 //indent input 124 struct outer { 125 enum { 126 untagged_constant, 127 } untagged_member, 128 second_untagged_member; 129 enum tag_name { 130 tagged_constant, 131 } tagged_member, 132 second_tagged_member; 133 }; 134 //indent end 135 136 //indent run-equals-input -di0 137 138 139 /* 140 * The initializer of an enum constant needs to be indented like any other 141 * initializer, especially the continuation lines. 142 */ 143 //indent input 144 enum multi_line { 145 ml1 = 1 146 + 2 147 + offsetof(struct s, member) 148 + 3, 149 ml2 = 1 150 + 2 151 + offsetof(struct s, member) 152 + 3, 153 }; 154 //indent end 155 156 //indent run-equals-input -ci4 157 158 //indent run-equals-input -ci4 -nlp 159 160 161 /* 162 * When 'typedef' or a tag is followed by a name, that name marks a type and a 163 * following '*' marks a pointer type. 164 */ 165 //indent input 166 { 167 // $ Syntactically invalid but shows that '*' is not multiplication. 168 a = struct x * y; 169 a = (struct x * y)z; 170 } 171 //indent end 172 173 //indent run 174 { 175 // $ Everything before the '*' is treated as a declaration. 176 a = struct x *y; 177 a = (struct x *y)z; 178 } 179 //indent end 180