// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // designations.c -- // // Author : Rob Schluntz // Created On : Thu Jun 29 15:26:36 2017 // Last Modified By : Peter A. Buhr // Last Modified On : Thu Jul 27 11:46:35 2017 // Update Count : 3 // // Note: this test case has been crafted so that it compiles with both cfa and with gcc without any modifications. // In particular, since the syntax for designations in Cforall differs from that of C, preprocessor substitution // is used for the designation syntax #ifdef __cforall #define DES : #else int printf(const char *, ...); #define DES = #endif const int indentAmt = 2; void indent(int level) { for (int i = 0; i < level; ++i) { printf(" "); } } // A contains fields with different types (int vs. int *) struct A { int x, y; int * ptr; }; void printA(struct A a, int level) { indent(level); printf("(A){ %d %d %p }\n", a.x, a.y, a.ptr); } // B contains struct members struct B { struct A a0, a1; }; void printB(struct B b, int level) { indent(level); printf("(B){\n"); printA(b.a0, level+indentAmt); printA(b.a1, level+indentAmt); indent(level); printf("}\n"); } // C contains an array - tests that after 3 ints, the members of B are initialized. struct C { int arr[3]; struct B b; }; void printC(struct C c, int level) { indent(level); printf("(C){\n"); indent(level+indentAmt); printf("(int[]{ %d %d %d }\n", c.arr[0], c.arr[1], c.arr[2]); printB(c.b, level+indentAmt); indent(level); printf("}\n"); } // D contains an unnamed aggregate - tests that this doesn't interfere with initialization. struct D { struct { int x; }; }; void printD(struct D d, int level) { indent(level); printf("(D){ %d }\n", d.x); } // E tests unions union E { struct A a; struct B b; struct C c; struct D d; int i; }; struct Fred { double i[3]; int j; struct Mary { struct Jane { double j; } j; double i; } m; }; struct Fred s1 @= { .m.j : 3 }; struct Fred s2 @= { .i : { [2] : 2 } }; int main() { // simple designation case - starting from beginning of structure, leaves ptr default-initialized (zero) struct A y0 = { .x DES 2, .y DES 3 }; // simple initializaiton case - initialize all elements explicitly with no designations struct A y1 = { 2, 3, 0 }; // use designation to move to member y, leaving x default-initialized (zero) struct A y2 = { .y DES 3, 0 }; #if ERROR struct A yErr0 = { {} // error - empty scalar initializer is illegal }; #endif printf("=====A=====\n"); printA(y0, 0); printA(y1, 0); printA(y2, 0); printf("=====A=====\n\n"); // initialize only first element (z0.a.x), leaving everything else default-initialized (zero), no nested curly-braces struct B z0 = { 5 }; // some nested curly braces, use designation to 'jump around' within structure, leaving some members default-initialized struct B z1 = { { 3 }, // z1.a0 { 4 }, // z1.a1 .a0 DES { 5 }, // z1.a0 { 6 }, // z1.a1 .a0.y DES 2, // z1.a0.y 0, // z1.a0.ptr }; // z2.a0.y and z2.a0.ptr default-initialized, everything else explicit struct B z2 = { { 1 }, { 2, 3, 0 } }; // initialize every member, omitting nested curly braces struct B z3 = { 1, 2, 0, 4, 5, 0 }; // no initializer - legal C, but garbage values - don't print this one struct B z4; // no curly braces - initialize with object of same type struct B z5 = z2; // z6.a0.y and z6.a0.ptr default-initialized, everything else explicit. // no curly braces on z6.a1 initializers struct B z6 = { { 1 }, 2, 3, 0 }; printf("=====B=====\n"); printB(z0, 0); printB(z1, 0); printB(z2, 0); printB(z3, 0); printB(z5, 0); printB(z6, 0); printf("=====B=====\n\n"); // TODO: what about extra things in a nested init? are empty structs skipped?? // test that initializing 'past array bound' correctly moves to next member. struct C c1 = { 2, 3, 4, // arr 5, 6, 0, // b.a0 7, 8, 0, // b.a1 }; printf("=====C=====\n"); printC(c1, 0); printf("=====C=====\n\n"); #if ERROR // nested initializer can't refer to same type in C struct C cErr0 = { c1 }; // must use curly braces to initialize members struct C cErr1 = 2; // can't initialize with array compound literal struct C cErr2 = { (int[3]) { 1, 2, 3 } // error: array initialized from non-constant array expression }; #endif #if WARNING // can't initialize array with array - converts to int* int cWarn0_arr[3] = { 1, 2, 3 }; struct C cWarn0 = { cWarn0_arr // warning: initialization makes integer from ptr without cast }; #endif // array designation int i[2] = { [1] : 3 }; // allowed to have 'too many' initialized lists - essentially they are ignored. int i1 = { 3 }; // doesn't work yet. // designate unnamed object's members // struct D d = { .x DES 3 }; #if ERROR struct D d1 = { .y DES 3 }; #endif // simple union initialization - initialized first member (e0.a) union E e0 = { y0 }; // simple union initialization - initializes first member (e1.a) - with nested initializer list union E e1 = { { 2, 3, 0 } }; // simple union initialization - initializes first member (e2.a) - without nested initializer list union E e2 = { 2, 3, 0 }; // move cursor to e4.b.a0.x and initialize until e3.b.a1.ptr inclusive union E e3 = { .b.a0.x DES 2, 3, 0, 5, 6, 0 }; printf("=====E=====\n"); printA(e0.a, 0); printA(e1.a, 0); printA(e2.a, 0); printB(e3.b, 0); printf("=====E=====\n\n"); // special case of initialization: char[] can be initialized with a string literal const char * str0 = "hello"; char str1[] = "hello"; const char c1[] = "abc"; const char c2[] = { 'a', 'b', 'c' }; const char c3[][2] = { { 'a', 'b' }, { 'c', 'd'}, { 'c', 'd'} }; } // Local Variables: // // tab-width: 4 // // End: //