1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define N_FIELDS 7 5 #define N_FUNCS 128 6 #define FUNCSPACING 20 7 #define N_STRUCTS 180 /* 1280 */ 8 #define N_BASES 6 9 #define COVARIANT 0 10 11 const char *simple_types[] = { "bool", "char", "short", "int", "float", 12 "double", "long double", "wchar_t", "void *", 13 "char *" 14 }; 15 16 void gl(const char *c) { 17 printf("%s\n", c); 18 } 19 20 void g(const char *c) { 21 printf("%s", c); 22 } 23 24 void g(int i) { 25 printf("%d", i); 26 } 27 28 int uuid = 0; 29 char base_present[N_STRUCTS][N_STRUCTS]; 30 31 // The return type for each function when doing covariant testcase generation. 32 short ret_types[N_STRUCTS][N_FUNCS*FUNCSPACING]; 33 34 bool is_ambiguous(int s, int base) { 35 for (int i = 0; i < N_STRUCTS; ++i) { 36 if ((base_present[base][i] & base_present[s][i]) == 1) 37 return true; 38 } 39 return false; 40 } 41 42 void add_bases(int s, int base) { 43 for (int i = 0; i < N_STRUCTS; ++i) 44 base_present[s][i] |= base_present[base][i]; 45 if (!COVARIANT) 46 return; 47 for (int i = 0; i < N_FUNCS*FUNCSPACING; ++i) { 48 if (!ret_types[base][i]) 49 continue; 50 if (!ret_types[s][i]) { 51 ret_types[s][i] = ret_types[base][i]; 52 continue; 53 } 54 if (base_present[ret_types[base][i]][ret_types[s][i]]) 55 // If the return type of the function from this base dominates 56 ret_types[s][i] = ret_types[base][i]; 57 if (base_present[ret_types[s][i]][ret_types[base][i]]) 58 // If a previous base dominates 59 continue; 60 // If neither dominates, we'll use this class. 61 ret_types[s][i] = s; 62 } 63 } 64 65 // This contains the class that has the final override for 66 // each class, for each function. 67 short final_override[N_STRUCTS][N_FUNCS*FUNCSPACING]; 68 69 void gs(int s) { 70 bool polymorphic = false; 71 72 static int bases[N_BASES]; 73 int i_bases = random() % (N_BASES*2); 74 if (i_bases >= N_BASES) 75 // PARAM: 1/2 of all clases should have no bases 76 i_bases = 0; 77 int n_bases = 0; 78 bool first_base = true; 79 80 // PARAM: 3/4 of all should be class, the rest are structs 81 if (random() % 4 == 0) 82 g("struct s"); 83 else 84 g("class s"); 85 g(s); 86 int old_base = -1; 87 if (s == 0 || s == 1) 88 i_bases = 0; 89 while (i_bases) { 90 --i_bases; 91 int base = random() % (s-1) + 1; 92 if (!base_present[s][base]) { 93 if (is_ambiguous(s, base)) 94 continue; 95 if (first_base) { 96 first_base = false; 97 g(": "); 98 } else 99 g(", "); 100 int base_type = 1; 101 if (random()%8 == 0) { 102 // PARAM: 1/8th the bases are virtual 103 g("virtual "); 104 // We have a vtable and rtti, but technically we're not polymorphic 105 // polymorphic = true; 106 base_type = 3; 107 } 108 // PARAM: 1/4 are public, 1/8 are privare, 1/8 are protected, the reset, default 109 int base_protection = 0; 110 if (!COVARIANT) 111 base_protection = random()%8; 112 switch (base_protection) { 113 case 0: 114 case 1: 115 g("public "); break; 116 case 2: 117 case 3: 118 case 4: 119 case 5: 120 break; 121 case 6: 122 g("private "); break; 123 case 7: 124 g("protected "); break; 125 } 126 g("s"); 127 add_bases(s, base); 128 bases[n_bases] = base; 129 base_present[s][base] = base_type; 130 ++n_bases; 131 g(base); 132 old_base = base; 133 } 134 } 135 gl(" {"); 136 137 /* Fields */ 138 int n_fields = N_FIELDS == 0 ? 0 : random() % (N_FIELDS*4); 139 // PARAM: 3/4 of all structs should have no members 140 if (n_fields >= N_FIELDS) 141 n_fields = 0; 142 for (int i = 0; i < n_fields; ++i) { 143 int t = random() % (sizeof(simple_types) / sizeof(simple_types[0])); 144 g(" "); g(simple_types[t]); g(" field"); g(i); gl(";"); 145 } 146 147 /* Virtual functions */ 148 static int funcs[N_FUNCS*FUNCSPACING]; 149 // PARAM: 1/2 of all structs should have no virtual functions 150 int n_funcs = random() % (N_FUNCS*2); 151 if (n_funcs > N_FUNCS) 152 n_funcs = 0; 153 int old_func = -1; 154 for (int i = 0; i < n_funcs; ++i) { 155 int fn = old_func + random() % FUNCSPACING + 1; 156 funcs[i] = fn; 157 int ret_type = 0; 158 if (COVARIANT) { 159 ret_type = random() % s + 1; 160 if (!base_present[s][ret_type] 161 || !base_present[ret_type][ret_types[s][fn]]) 162 if (ret_types[s][fn]) { 163 printf(" // Found one for s%d for s%d* fun%d.\n", s, 164 ret_types[s][fn], fn); 165 ret_type = ret_types[s][fn]; 166 } else 167 ret_type = s; 168 else 169 printf(" // Wow found one for s%d for fun%d.\n", s, fn); 170 ret_types[s][fn] = ret_type; 171 } 172 if (ret_type) { 173 g(" virtual s"); g(ret_type); g("* fun"); 174 } else 175 g(" virtual void fun"); 176 g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++uuid); 177 if (ret_type) 178 gl("); return 0; }"); 179 else 180 gl("); }"); 181 final_override[s][fn] = s; 182 old_func = fn; 183 } 184 185 // Add required overriders for correctness 186 for (int i = 0; i < n_bases; ++i) { 187 // For each base 188 int base = bases[i]; 189 for (int fn = 0; fn < N_FUNCS*FUNCSPACING; ++fn) { 190 // For each possible function 191 int new_base = final_override[base][fn]; 192 if (new_base == 0) 193 // If the base didn't have a final overrider, skip 194 continue; 195 196 int prev_base = final_override[s][fn]; 197 if (prev_base == s) 198 // Skip functions defined in this class 199 continue; 200 201 // If we don't want to change the info, skip 202 if (prev_base == new_base) 203 continue; 204 205 if (prev_base == 0) { 206 // record the final override 207 final_override[s][fn] = new_base; 208 continue; 209 } 210 211 if (base_present[prev_base][new_base]) { 212 // The previous base dominates the new base, no update necessary 213 printf(" // No override for fun%d in s%d as s%d dominates s%d.\n", 214 fn, s, prev_base, new_base); 215 continue; 216 } 217 218 if (base_present[new_base][prev_base]) { 219 // The new base dominates the old base, no override necessary 220 printf(" // No override for fun%d in s%d as s%d dominates s%d.\n", 221 fn, s, new_base, prev_base); 222 // record the final override 223 final_override[s][fn] = new_base; 224 continue; 225 } 226 227 printf(" // Found we needed override for fun%d in s%d.\n", fn, s); 228 229 // record the final override 230 funcs[n_funcs++] = fn; 231 if (n_funcs == (N_FUNCS*FUNCSPACING-1)) 232 abort(); 233 int ret_type = 0; 234 if (COVARIANT) { 235 if (!ret_types[s][fn]) { 236 ret_types[s][fn] = ret_type = s; 237 } else { 238 ret_type = ret_types[s][fn]; 239 if (ret_type != s) 240 printf(" // Calculated return type in s%d as s%d* fun%d.\n", 241 s, ret_type, fn); 242 } 243 } 244 if (ret_type) { 245 g(" virtual s"); g(ret_type); g("* fun"); 246 } else 247 g(" virtual void fun"); 248 g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++uuid); 249 if (ret_type) 250 gl("); return 0; }"); 251 else 252 gl("); }"); 253 final_override[s][fn] = s; 254 } 255 } 256 257 gl("public:"); 258 gl(" void calc(char *t) {"); 259 260 // mix in the type number 261 g(" mix(\"type num\", "); g(s); gl(");"); 262 // mix in the size 263 g(" mix(\"type size\", sizeof (s"); g(s); gl("));"); 264 // mix in the this offset 265 gl(" mix(\"subobject offset\", (char *)this - t);"); 266 if (n_funcs) 267 polymorphic = true; 268 if (polymorphic) { 269 // mix in offset to the complete object under construction 270 gl(" mix(\"real top v current top\", t - (char *)dynamic_cast<void*>(this));"); 271 } 272 273 /* check base layout and overrides */ 274 for (int i = 0; i < n_bases; ++i) { 275 g(" calc_s"); g(bases[i]); gl("(t);"); 276 } 277 278 if (polymorphic) { 279 /* check dynamic_cast to each direct base */ 280 for (int i = 0; i < n_bases; ++i) { 281 g(" if ((char *)dynamic_cast<s"); g(bases[i]); gl("*>(this))"); 282 g(" mix(\"base dyn cast\", t - (char *)dynamic_cast<s"); g(bases[i]); gl("*>(this));"); 283 g(" else mix(\"no dyncast\", "); g(++uuid); gl(");"); 284 } 285 } 286 287 /* check field layout */ 288 for (int i = 0; i < n_fields; ++i) { 289 g(" mix(\"field offset\", (char *)&field"); g(i); gl(" - (char *)this);"); 290 } 291 if (n_fields == 0) { 292 g(" mix(\"no fields\", "); g(++uuid); gl(");"); 293 } 294 295 /* check functions */ 296 for (int i = 0; i < n_funcs; ++i) { 297 g(" fun"); g(funcs[i]); gl("(t);"); 298 } 299 if (n_funcs == 0) { 300 g(" mix(\"no funcs\", "); g(++uuid); gl(");"); 301 } 302 303 gl(" }"); 304 305 // default ctor 306 g(" s"); g(s); g("() "); 307 first_base = true; 308 for (int i = 0; i < n_bases; ++i) { 309 if (first_base) { 310 g(": "); 311 first_base = false; 312 } else 313 g(", "); 314 g("s"); g(bases[i]); g("((char *)this)"); 315 } 316 gl(" { calc((char *)this); }"); 317 g(" ~s"); g(s); gl("() { calc((char *)this); }"); 318 319 // ctor with this to the complete object 320 g(" s"); g(s); gl("(char *t) { calc(t); }"); 321 g(" void calc_s"); g(s); gl("(char *t) { calc(t); }"); 322 g("} a"); g(s); gl(";"); 323 } 324 325 main(int argc, char **argv) { 326 unsigned seed = 0; 327 char state[16]; 328 if (argc > 1) 329 seed = atol(argv[1]); 330 331 initstate(seed, state, sizeof(state)); 332 gl("extern \"C\" int printf(const char *...);"); 333 gl(""); 334 gl("long long sum;"); 335 gl("void mix(const char *desc, long long i) {"); 336 // If this ever becomes too slow, we can remove this after we improve the 337 // mixing function 338 gl(" printf(\"%s: %lld\\n\", desc, i);"); 339 gl(" sum += ((sum ^ i) << 3) + (sum<<1) - i;"); 340 gl("}"); 341 gl(""); 342 // PARAM: Randomly size testcases or large testcases? 343 int n_structs = /* random() % */ N_STRUCTS; 344 for (int i = 1; i < n_structs; ++i) 345 gs(i); 346 gl("int main() {"); 347 gl(" printf(\"%llx\\n\", sum);"); 348 gl("}"); 349 return 0; 350 } 351