|
|
1.1 root 1: /* The Plum Hall Validation Suite for C
2: * Unpublished copyright (c) 1986-1991, Chiron Systems Inc and Plum Hall Inc.
3: * VERSION: 4
4: * DATE: 1993-01-01
5: * The "ANSI" mode of this suite corresponds to official ANSI C, X3.159-1989.
6: * As per your license agreement, your distribution is not to be moved or copied outside the Designated Site
7: * without specific permission from Plum Hall Inc.
8: */
9:
10: #include "flags.h"
11: #ifndef SKIP35
12: /*
13: * 3.5 - Declarations
14: */
15: #include "defs.h"
16:
17:
18:
19:
20: static void c3_5_1();
21: static void c3_5_2();
22: static void c3_5_2_1();
23: static void c3_5_2_2();
24: static void c3_5_2_3();
25: static void c3_5_3();
26: static void c3_5_4();
27: static void c3_5_4_1();
28: static void c3_5_4_2();
29: static void c3_5_4_3();
30: static void c3_5_5();
31: static void c3_5_6();
32: static void c3_5_7();
33: extern void bitfields();
34:
35: void c3_5()
36: {
37: Filename = "c35.c";
38: c3_5_1();
39: c3_5_2();
40: c3_5_2_1();
41: c3_5_2_2();
42: c3_5_2_3();
43: c3_5_3();
44: c3_5_4();
45: c3_5_4_1();
46: c3_5_4_2();
47: c3_5_4_3();
48: c3_5_5();
49: c3_5_6();
50: c3_5_7();
51: bitfields();
52: }
53:
54:
55: /*
56: * 3.5.1 - Storage-class specifiers
57: */
58: #if ANSI
59: extern void (*pc3_5_2)() = c3_5_2; /* extern allowed with initializer */
60: #else
61: void (*pc3_5_2)() = c3_5_2;
62: #endif
63: static void c3_5_1()
64: {
65: /* just check for existence of the keywords here */
66: auto int i;
67: register int j;
68: static int k;
69: extern int l;
70: typedef int M;
71: M m;
72:
73: i = j = k = l = m = 0;
74: checkthat(__LINE__, !(i || j || k || l || m));
75: checkthat(__LINE__, pc3_5_2 == c3_5_2);
76: }
77: int l = 0;
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103: /*
104: * 3.5.2 - Type specifiers
105: */
106: static void c3_5_2()
107: {
108: /* verify that all forms are handled */
109: int x1;
110: short int x2;
111: short x3;
112: long x4;
113: int long x5;
114: unsigned x6;
115: int unsigned x7;
116: char x8;
117: #if (ANSI || V7)
118: UCHAR x9;
119: USHORT x10;
120: int USHORT x11;
121: ULONG x12;
122: ULONG int x13;
123: #endif
124:
125: #if ANSI
126: typedef int INT;
127: typedef signed SIGNED;
128: {
129: signed char x14;
130: short signed x15;
131: short int signed x16;
132: signed long x17;
133: signed int long x18;
134: signed x19;
135: signed int x20;
136: double long x21;
137: const x22 = 22;
138: int short const x23 = 23;
139: volatile x24;
140: long volatile int x25;
141: const INT x26 = 26;
142: INT volatile x27;
143: INT const volatile x27a = 27;
144:
145: checkthat(__LINE__, sizeof(x24) == sizeof(int));
146: }
147: #endif /* ANSI */
148:
149:
150:
151:
152:
153: #if ANSI8712 /* 3.5.2 (cont.) */
154: #define COMPATIBLE(t1, t2) { t1 v1={0}, *p1=&v1; t2 v2={0}, *p2=&v2; p1=p2; \
155: checkthat(__LINE__, 0==mem_cmp((void *)p1, (void *)p2, sizeof(*p1))); }
156: #else
157: #define COMPATIBLE(t1, t2) { }
158: #endif
159: #if ANSI
160: {
161: struct s { int i:2; unsigned u:2; signed si:2; INT it:2; SIGNED st:2; } s = {-1, -1, -1, -1, -1};
162:
163: iequals(__LINE__, s.u, 3);
164: iequals(__LINE__, s.si, -1);
165: iequals(__LINE__, s.st, -1);
166: #if ANSI8804
167: if (s.i == 3) /* if "plain int" bitfield is unsigned */
168: iequals(__LINE__, s.it, 3);
169: else if (s.i == -1) /* else if "plain int" bitfield is signed */
170: iequals(__LINE__, s.it, -1);
171: else
172: complain(__LINE__); /* should take one of previous choices */
173: #endif /* ANSI8804 */
174:
175: COMPATIBLE(short, signed short);
176: COMPATIBLE(short, signed short int);
177: COMPATIBLE(unsigned short, unsigned short int);
178: COMPATIBLE(int, signed int);
179: COMPATIBLE(signed, signed int);
180: COMPATIBLE(unsigned, unsigned int);
181: COMPATIBLE(long, signed long);
182: COMPATIBLE(long, signed long int);
183: COMPATIBLE(unsigned long, unsigned long int);
184: COMPATIBLE(long unsigned, long int unsigned);
185: COMPATIBLE(short unsigned, unsigned int short);
186:
187: }
188: #endif /* ANSI */
189:
190: {
191: float x28;
192: double x29;
193: void (*x30)();
194: static x31 = 31;
195:
196: checkthat(__LINE__, sizeof(x31) == sizeof(int));
197: iequals(__LINE__, x31, 31);
198: }
199: } /* end c3_5_2 */
200:
201:
202:
203: /*
204: * 3.5.2.1 - Structure and union specifiers.
205: */
206: static void c3_5_2_1()
207: {
208: /* structures and unions have the same form */
209: struct S1
210: {
211: char a;
212: short b;
213: int c;
214: long d;
215: float e;
216: double f;
217: unsigned g:1;
218: } s;
219:
220: union U1
221: {
222: char u1_a;
223: short u1_b;
224: int u1_c;
225: unsigned u1_d;
226: long u1_e;
227: float u1_f;
228: double u1_g;
229: #if (ANSI || V7)
230: UCHAR u1_h;
231: USHORT u1_i;
232: ULONG u1_j;
233: #endif
234: #if ANSI
235: signed char u1_k;
236: long double u1_l;
237: #endif
238: } u, *pu = &u;
239:
240: #if (ANSI || UNIQ_MEMB_NAMES)
241: struct uniqnames
242: {
243: double a;
244: };
245: #endif
246:
247: struct
248: {
249: unsigned x:1;
250: } onefield;
251:
252:
253: /* 3.5.2.1 (cont.) */
254: struct
255: {
256: unsigned fa_f:1;
257: unsigned :0; /* break storage boundry */
258: unsigned fa_g:1;
259: } forcealign;
260: #if ANSI
261: union ufields
262: {
263: unsigned x1 : 1;
264: unsigned x3 : 2+1;
265: } uf1;
266: enum { ONE=1, TWO };
267: #endif /* ANSI */
268:
269: struct fields
270: {
271: unsigned x1:1;
272: unsigned x2:2;
273: unsigned x3:3;
274: unsigned :1; /* just because it can be done */
275: unsigned x4:4;
276: #if ANSI
277: int x5:'\2'; /* char-constant width */
278: signed int x6:TWO; /* enum width */
279: #endif /* ANSI */
280: } b, b2, *p = &b2;
281:
282: #if !ANSI
283: checkthat(__LINE__, sizeof(onefield) == sizeof(unsigned));
284: #endif
285:
286: #if ANSI
287: b.x6 = -1;
288: dequals(__LINE__, (double)b.x6, -1.);
289: #endif
290: b2.x4 = 0;
291: b.x1 = p->x1 = 1;
292: p->x2 = b.x1 + 2*p->x1;
293: b.x3 = p->x2 + 4*b.x1;
294: p->x4 += (b.x3 - b.x1) * p->x2; /* unsigned wraparound (3.2.1.1) */
295: iequals(__LINE__, b.x1, 1);
296: iequals(__LINE__, p->x2, 3);
297: iequals(__LINE__, b.x3, 7);
298: iequals(__LINE__, p->x4, 2);
299:
300:
301:
302:
303: /* any interactions? */ /* 3.5.2.1 (cont.) */
304: b.x2 = p->x3 = b.x4 = 0;
305: iequals(__LINE__, b.x1, 1);
306: iequals(__LINE__, p->x2, 3);
307: iequals(__LINE__, b.x3, 7);
308: iequals(__LINE__, p->x4, 2);
309:
310:
311: /* unsigned values convert modulo largest+1 */
312: b.x1 = 2;
313: b.x2 = 4;
314: b.x3 = 8;
315: b.x4 = 16;
316: iequals(__LINE__, b.x1, 0);
317: iequals(__LINE__, b.x2, 0);
318: iequals(__LINE__, b.x3, 0);
319: iequals(__LINE__, b.x4, 0);
320:
321: /* there are not very many things about fields that are not
322: * implementation dependent.
323: *
324: */
325: checkthat( - __LINE__, sizeof(forcealign) >= 2 * sizeof(onefield));
326:
327: /* size of union is size of greatest element (+ padding?) */
328: checkthat(__LINE__, sizeof(u) >= sizeof(double));
329: #if ANSI
330: checkthat(__LINE__, sizeof(u) >= sizeof(long double));
331: #endif
332: /* make sure all union members are accessible and have the right value */
333: #if SIGNED_CHAR
334: u.u1_a = -1;
335: iequals(__LINE__, u.u1_a, -1);
336: #else
337: u.u1_a = 255;
338: iequals(__LINE__, u.u1_a, 255);
339: #endif
340: pu->u1_b = -1;
341: iequals(__LINE__, u.u1_b, -1);
342: u.u1_c = -2;
343: iequals(__LINE__, u.u1_c, -2);
344: u.u1_d = MAX_UINT;
345: checkthat(__LINE__, u.u1_d == MAX_UINT);
346: u.u1_e = -1;
347: lequals(__LINE__, u.u1_e, -1L);
348: u.u1_f = 1.0;
349: dequals(__LINE__, u.u1_f, 1.0);
350: u.u1_g = 2.2;
351: dequals(__LINE__, u.u1_g, 2.2);
352:
353: /* 3.5.2.1 (cont.) */
354:
355:
356:
357:
358:
359:
360: #if ANSI
361: u.u1_h = MAX_UCHAR;
362: iequals(__LINE__, u.u1_h, MAX_UCHAR);
363: u.u1_i = MAX_USHORT;
364: checkthat(__LINE__, u.u1_i == MAX_USHORT);
365: u.u1_j = MAX_ULONG;
366: checkthat(__LINE__, u.u1_j == MAX_ULONG);
367:
368: u.u1_k = -1;
369: iequals(__LINE__, u.u1_k, -1);
370: u.u1_l = 3.3L;
371: ldequals(__LINE__, u.u1_l, 3.3L);
372:
373: #endif
374:
375: /* addresses of members must be monotonically increasing */
376: checkthat(__LINE__, (char *)&s.a < (char *)&s.b);
377: checkthat(__LINE__, (char *)&s.b < (char *)&s.c);
378: checkthat(__LINE__, (char *)&s.c < (char *)&s.d);
379: checkthat(__LINE__, (char *)&s.d < (char *)&s.e);
380: checkthat(__LINE__, (char *)&s.e < (char *)&s.f);
381:
382: /* also, the address of the first member is the address of the structure */
383: checkthat(__LINE__, (char *)&s.a == (char *)&s);
384:
385: /* structs and unions are padded, to allow array alignment */
386: {
387: struct S1 as[2];
388: union U1 au[2];
389:
390: checkthat(__LINE__, &as[1] == (struct S1 *)(sizeof(struct S1) + (char *)&as[0]));
391: checkthat(__LINE__, &au[1] == (union U1 *)(sizeof(union U1) + (char *)&au[0]));
392: }
393: } /* end c3_5_2_1 */
394:
395:
396:
397:
398:
399:
400:
401:
402:
403: /*
404: * 3.5.2.2 - Enumeration specifiers
405: */
406: static void c3_5_2_2()
407: {
408: int i;
409: #if (V7 || ANSI)
410: /* number from 0 */
411: enum a { a0, a1, a2, a3} aset;
412:
413: /* number explicitly, with the order picked up in the middle */
414: enum b { b2=2, b1=1, b0=0, b1a, b2a, b2b=2} bset, *pbset;
415:
416: /* check aset */
417: iequals(__LINE__, a0, 0);
418: iequals(__LINE__, a1, 1);
419: iequals(__LINE__, a2, 2);
420: iequals(__LINE__, a3, 3);
421:
422: /* check bset */
423: iequals(__LINE__, b2, 2);
424: iequals(__LINE__, b1, 1);
425: iequals(__LINE__, b0, 0);
426: iequals(__LINE__, b1a, 1);
427: iequals(__LINE__, b2a, 2);
428: iequals(__LINE__, b2b, 2);
429:
430: /* before ANSI the use of enums was limited */
431: bset = b2a;
432: pbset = &bset;
433: iequals(__LINE__, bset, b2a);
434: checkthat(__LINE__, bset==b2a);
435: checkthat(__LINE__, bset!=b1);
436: iequals(__LINE__, *pbset, bset);
437:
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453: /* 3.5.2.2 (cont.) */
454: /* with ANSI, enums can be used anywhere an int can be used */
455: #if ANSI
456: {
457: int a[b2b] = { 0, 1 };
458:
459: iequals(__LINE__, a[b0], ivalue(0));
460: switch (bset)
461: {
462: case b0:
463: i = 999;
464: break;
465: case b2:
466: i = 0;
467: break;
468: default :
469: i = 999;
470: break;
471: case a1:
472: /* not wise, but possible */
473: i = 999;
474: break;
475: }
476: iequals(__LINE__, i, 0);
477:
478: iequals(__LINE__, ++bset, 3);
479: checkthat(__LINE__, sizeof(aset) <= sizeof(int));
480: }
481: #endif /* ANSI */
482: #endif /* V& || ANSI */
483: } /* end c3_5_2_2 */
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503: /*
504: * 3.5.2.3 - Tags.
505: */
506:
507: /* mutually-referencing structures */
508: struct mutrefa /* mutrefa is "tag" */
509: { /* followed by "{ struct-decl-list }" */
510: struct mutrefb *refb; /* "incomplete structure spec" for ptr-to-struct */
511: int vala;
512: };
513: struct mutrefb
514: {
515: struct mutrefa *refa; /* uses previously-decl "tag" */
516: int valb;
517: };
518: #if ANSI
519: struct mutrefb strb; /* "tentative def" -- 3.7.2 */
520: #else
521: extern struct mutrefb strb; /* ordinary "extern" ref */
522: #endif
523: struct mutrefa stra = { &strb, 11};
524: struct mutrefb strb = { &stra, 13};
525: /* "incomplete structure spec" must work for typedefs */
526: typedef struct s2 S2; /* "incomplete structure spec" for typedef */
527: struct s2 /* must be "completed" before size is needed */
528: {
529: struct s2 * ps1; /* "incomplete spec" ok for ptr-to-struct */
530: S2 *ps2; /* so is the equivalent typedef */
531: int val;
532: } x1; /* "tentative def" of x1 */
533: S2 x2; /* "tentative def" of x2 */
534:
535: #if ANSI
536: /* "incomplete structure spec" must work for functions returning structures */
537: struct s3 rets3();
538: struct s3 /* "incomplete spec" must be completed before size is needed */
539: {
540: int s3_1, s3_2, s3_3, s3_4;
541: } R3 = {1, 2, 3, 4};
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553: /* 3.5.2.3 (cont.) */
554: /* watch out for nested scope in structure tag ... */
555: typedef struct nest NEST;
556: struct s3 rets3()
557: { /* introduces new block scope */
558: /* should be ignored by typedef NEST */
559: struct nest { int a, b;};
560:
561: /* use "vacuous structure spec" to disambiguate */
562: struct mutrefb; /* introduces new tag */
563: struct mutrefa
564: {
565: struct mutrefb *refb;
566: };
567: struct mutrefb
568: {
569: struct mutrefa *refa;
570: };
571: return R3;
572: }
573: struct nest /* completing the spec from typedef NEST */
574: {
575: int nest_1;
576: int nest_2;
577: } Nest = { 1, 2};
578: #endif
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603: /* 3.5.2.3 (cont.) */
604: /* mutually-referencing unions */
605: union mutrefua /* mutrefua is "tag" */
606: { /* followed by "{ union-decl-list }" */
607: union mutrefub *refub; /* "incomplete union spec" for ptr-to-union */
608: int vala;
609: };
610: union mutrefub
611: {
612: union mutrefua *refua; /* uses previously-decl "tag" */
613: int valb;
614: };
615: #if ANSI
616: union mutrefub unb; /* "tentative def" -- 3.7.2 */
617: union mutrefua una = { &unb };
618: union mutrefub unb = { &una };
619: #else
620: extern union mutrefub unb; /* ordinary "extern" ref */
621: union mutrefua una;
622: union mutrefub unb;
623: #endif
624: /* "incomplete union spec" must work for typedefs */
625: typedef union u2 U2; /* "incomplete union spec" for typedef */
626: union u2 /* must be "completed" before size is needed */
627: {
628: union u2 * pu1; /* "incomplete spec" ok for ptr-to-union */
629: U2 *pu2; /* so is the equivalent typedef */
630: int val;
631: } ux1; /* "tentative def" of ux1 */
632: U2 ux2; /* "tentative def" of ux2 */
633:
634: #if ANSI
635: /* "incomplete union spec" must work for functions returning unions */
636: union u3 retu3();
637: union u3 /* "incomplete spec" must be completed before size is needed */
638: {
639: int u3_1; char u3_2;
640: } U3 = {1};
641:
642:
643:
644:
645:
646:
647:
648:
649:
650:
651:
652:
653: /* 3.5.2.3 (cont.) */
654: /* watch out for nested scope in union tag ... */
655: typedef union unest UNEST;
656: union u3 retu3()
657: { /* introduces new block scope */
658: /* should be ignored by typedef UNEST */
659: union unest { int a, b;};
660:
661: /* use "vacuous union spec" to disambiguate */
662: union mutrefub; /* introduces new tag */
663: union mutrefua
664: {
665: union mutrefub *refub;
666: };
667: union mutrefub
668: {
669: union mutrefua *refua;
670: };
671: return U3;
672: }
673: union unest /* completing the spec from typedef UNEST */
674: {
675: int unest_1;
676: float unest_2;
677: } UNest = { 1 };
678: #endif /* ANSI */
679:
680:
681:
682:
683: /* 3.5.2.3 (cont.) */
684: static void c3_5_2_3()
685: {
686: char *p = 0; /* This ptr will be used to test ptr-to-struct cast */
687: /* make declarations using struct/union tags */
688: struct s1
689: {
690: int a, b, c; /* unique struct member name spaces were tested in 3.1.2.3; */
691: }; /* here we use K&R-compatible name rules */
692: struct s1 a, b, c;
693: union u1
694: {
695: int i;
696: double d;
697: };
698:
699:
700:
701:
702:
703: /* 3.5.2.3 (cont.) */
704: union u1 u1;
705:
706: auto struct astr /* test syntax of stor-cl with struct */
707: {
708: int a;
709: } astr;
710:
711: static struct astr sstr = {123};
712:
713: /* make sure that they exist */
714: a.a = 1;
715: iequals(__LINE__, a.a, 1); /* (auto) local struct holds proper value */
716: u1.i = 2;
717: iequals(__LINE__, u1.i, 2); /* (auto) local union holds proper value */
718:
719: /* make sure forward references work (see x1 and x2 on prev page) */
720: x1.val = 3;
721: x2.val = 4;
722: x2.ps1 = &x1;
723: x2.ps2 = &x2; /* points to itself !! */
724: iequals(__LINE__, x2.ps1->val, 3); /* ptr-to-struct in struct works */
725: iequals(__LINE__, x2.ps2->val, 4); /* ptr-to-struct in struct works */
726:
727: /* unions can accept and hold properly-typed values */
728: ux1.val = 3;
729: ux2.val = 4;
730: iequals(__LINE__, ux1.val, ivalue(3));
731: iequals(__LINE__, ux2.val, ivalue(4));
732: ux2.pu1 = &ux1;
733: aequals(__LINE__, (char *)ux2.pu1, (char *)avalue(&ux1));
734:
735: /* mutually-referencing structs */
736: iequals(__LINE__, stra.vala, 11);
737: iequals(__LINE__, strb.valb, 13);
738: iequals(__LINE__, stra.refb->valb, 13);
739: iequals(__LINE__, strb.refa->vala, 11);
740: #if ANSI
741: /* mutually-referencing unions */
742: aequals(__LINE__, (char *)una.refub, (char *)avalue(&unb));
743: aequals(__LINE__, (char *)unb.refua, (char *)avalue(&una));
744: #endif
745: /* astr and sstr are different */
746: astr.a = 1;
747: iequals(__LINE__, sstr.a, 123);
748:
749:
750:
751:
752:
753: /* 3.5.2.3 (cont.) */
754: #if ANSI
755: iequals(__LINE__, Nest.nest_2, 2); /* test that block-local "nest" was not */
756: iequals(__LINE__, rets3().s3_4, 4); /* seen outside its block */
757:
758: /* A cast (3.3.4) uses a "type-name" (3.5.5), which can decl a tag */
759: p = (char *)(struct incast { int a; int b; } * )p; /* decls tag "incast" */
760: checkthat(__LINE__, sizeof(struct incast) > 0); /* test that struct incast decl'ed properly */
761:
762: {
763: struct s1; /* new scope */
764: struct s1 { char c; } sc;
765:
766: sc.c = ivalue('a');
767: iequals(__LINE__, sc.c, 'a');
768: }
769:
770: #endif /* ANSI */
771: } /* end c3_5_2_3 */
772:
773:
774:
775:
776:
777:
778:
779:
780:
781:
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793:
794:
795:
796:
797:
798:
799:
800:
801:
802:
803: /*
804: * 3.5.3 - const and volatile
805: */
806: static void c3_5_3()
807: {
808: #if ANSI
809: const char c1;
810: const UCHAR c2;
811: const signed char c3;
812: const short c4;
813: const USHORT c5;
814: const int c6;
815: const unsigned int c7;
816: const long c8;
817: const ULONG c9;
818: const float c10;
819: const double c11;
820: const long double c12;
821: volatile char v1;
822: volatile UCHAR v2;
823: volatile signed char v3;
824: volatile short v4;
825: volatile USHORT v5;
826: volatile int v6;
827: volatile unsigned int v7;
828: volatile long v8;
829: volatile ULONG v9;
830: volatile float v10;
831: volatile double v11;
832: volatile long double v12;
833: volatile int * const cv1;
834: const int * volatile cv2;
835: int *pi;
836: int i;
837: const int *pci = &i; /* may be assigned */
838: volatile int *pvi = &i;
839: const struct sa { int i; } csa;
840: struct sa sa2; /* doesn't inherit const */
841:
842: pi = (int *)pci; /* ok with cast */
843: checkthat(__LINE__, pi == &i);
844: pi = (int *)pvi;
845: checkthat(__LINE__, pi == &i);
846: sa2.i = 1; /* ok, not const */
847: iequals(__LINE__, sa2.i, 1);
848: COMPATIBLE(volatile int, int volatile);
849: COMPATIBLE(signed volatile int, int volatile);
850: COMPATIBLE(short volatile, signed volatile short int);
851:
852: #endif /* ANSI */
853: } /* end c3_5_3 */
854:
855:
856: /*
857: * 3.5.4 - Declarators
858: */
859: typedef int INT;
860: int func1() { return 7;}
861: INT func2() { return 11;}
862: int (*fpfi1())(){return func1;} /* func ret ptr to func ret int */
863: typedef int (*PFI)(); /* ptr to func ret ptr to int */
864: PFI fpfi2(){return func2;} /* func ret ptr to func ret int */
865: static void c3_5_4()
866: {
867: /* 2d-arr of ptr to func ret ptr to func ret int */
868: int (*(*apfpfi1[2][3])())();
869: int i, j;
870: int *p1 = &i;
871: int (*p2);
872: int ((*p3)); /* declarator in parens is identical to unadorned */
873: int (func1)(); /* declarator in parens is identical to unadorned */
874:
875: /* try the same thing with typedefs */
876: typedef PFI (*PFPFI)(); /* ptr to func ret ptr to func ret int */
877: PFPFI apfpfi2[2][3];
878:
879: p2 = (int *)avalue(p1);
880: p3 = p2;
881: checkthat(__LINE__, p3 == p1);
882: apfpfi1[1][2] = fpfi1;
883: apfpfi2[1][2] = fpfi2;
884: i = 1, j = 2;
885: iequals(__LINE__, (*(*apfpfi1[i][j])())(), 7);
886: iequals(__LINE__, (*(*apfpfi2[i][j])())(), 11);
887:
888: #if ANSI
889: {
890: struct { int i1; const int i2; } x = { 1, 2 };
891:
892: x.i1 = ivalue(3); /* not const */
893: iequals(__LINE__, x.i1, 3);
894: }
895: #endif /* ANSI */
896: } /* end c3_5_4 */
897:
898:
899:
900:
901:
902:
903:
904: /*
905: * 3.5.4.1 - Pointer declarators
906: */
907: static void c3_5_4_1()
908: {
909: char c = 'x';
910: char *pc = &c;
911: char **ppc = &pc;
912: char ***pppc = &ppc;
913: char ****ppppc = &pppc;
914: char *****pppppc = &ppppc;
915: char ******ppppppc = &pppppc;
916: typedef char C;
917: typedef C *PC;
918: typedef PC *PPC;
919: typedef PPC *PPPC;
920: typedef PPPC *PPPPC;
921: typedef PPPPC *PPPPPC;
922: typedef PPPPPC *PPPPPPC;
923: C d = 'y';
924: PC pd = &d;
925: PPC ppd = &pd;
926: PPPC pppd = &ppd;
927: PPPPC ppppd = &pppd;
928: PPPPPC pppppd = &ppppd;
929: PPPPPPC ppppppd = &pppppd;
930:
931: #if ANSI
932: const char *pconst = "constant string literal";
933: char carray[] = "variable string literal"; char *const constp = carray;
934: volatile int *vp = 0;
935: const char * volatile * pvpconst = &pconst;
936:
937: ++pconst;
938: iequals(__LINE__, *pconst, 'o');
939: ++*constp;
940: iequals(__LINE__, *constp, 'v'+1);
941: vp;
942: iequals(__LINE__, **pvpconst, 'o');
943: { /* Now test that volatile int * and int signed volatile * are compatible... */
944: volatile int *v1={0}, **p1=&v1;
945: int signed volatile *v2={0}, **p2=&v2;
946: p1=p2;
947: checkthat(__LINE__, 0==mem_cmp((void *)p1, (void *)p2, sizeof(*p1)));
948: }
949: #endif
950: iequals(__LINE__, ******ppppppc, 'x');
951: iequals(__LINE__, ******ppppppd, 'y');
952: } /* end c3_5_4_1 */
953:
954: /*
955: * 3.5.4.2 - Array declarators
956: */
957: /* dimension can be omitted for first dimension on external */
958: extern int INTarray[][3][2][3]; /* links with INTarray on next page */
959:
960: static void check_array(iarray)
961: /* first dimension can be left off on formal parameter */
962: int iarray[][3][2][3];
963: {
964: int i, j, k, l, count;
965:
966: /* as initialized below, there are 36 sequential items in the array */
967: for (count=0, i=0; i < 2; ++i)
968: for (j = 0; j < 3; ++j)
969: for (k = 0; k < 2; ++k)
970: for (l = 0; l < 3; ++l, ++count)
971: iequals(__LINE__, iarray[i][j][k][l], count);
972: }
973:
974: static void c3_5_4_2()
975: {
976: double d[2], *dp[2];
977:
978: /* make sure that the first dimension gets handled correctly */
979: check_array(INTarray);
980:
981: /* array of doubles vs. array of pointers to doubles */
982: d[0] = 0.0;
983: d[1] = 2.0;
984: dp[0] = d;
985: dp[1] = d+1;
986: dequals(__LINE__, *dp[1], 2.0);
987:
988: /* just to be perverse */
989: *dp[0] = (d[0] && d[1]) ^ (d[0] || d[1]);
990: dequals(__LINE__, d[0], 1.0);
991: #if ANSI
992: {
993: void ckarr();
994:
995: ckarr();
996: }
997: #endif /* ANSI */
998: } /* end c3_5_4_2 */
999:
1000:
1001:
1002:
1003:
1004: /* 3.5.4.2 (cont.) */
1005: /* array with size is compatible to one lacking size */
1006: /* dimension can be omitted for first dimension if initialized */
1007: int INTarray[][3][2][3] =
1008: { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
1009: 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35};
1010:
1011: #if ANSI
1012: int arrfn1();
1013: int arrfn1 PARMS((int [][3][2][3]));
1014: #if NEW_STYLE_FN_DEF
1015: int arrfn1(int a[2][3][2][3])
1016: #else
1017: int arrfn1(a)
1018: int a[2][3][2][3];
1019: #endif /* NEW_STYLE_FN_DEF */
1020: {
1021: return (a[0][0][0][1]);
1022: }
1023: void ckarr()
1024: {
1025: int (*parf1)() = arrfn1;
1026: int (*parf2) PARMS((int (*a)[3][2][3])) = &arrfn1;
1027:
1028: iequals(__LINE__, arrfn1(INTarray), 1);
1029: iequals(__LINE__, parf1(INTarray), 1);
1030: iequals(__LINE__, (*parf2)(INTarray), 1);
1031: }
1032: #endif /* ANSI */
1033:
1034:
1035:
1036:
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054: /*
1055: * 3.5.4.3 - Function declarators
1056: */
1057:
1058: /* ANSI rules for compatible function types:
1059: First, convert parameters of type fn or array.
1060: Then, delete any qualifiers on top type of any parameter.
1061: Then, for all cases, return types must be compatible.
1062: Then, one of the following must be true, for compatible fn types:
1063:
1064: 1. Both fn types are old-style (no parameter information).
1065: 2. If both are prototypes, they agree in number of parms,
1066: they agree in use of ellipsis, and parms are compatible.
1067: 3. If one is prototype and other is old-style declaration (with
1068: empty parentheses), the prototype must not have ellipsis
1069: or non-default parm types.
1070: 4. Otherwise, one is a prototype and the other is an old-style
1071: function definition. The number of parms must agree, and
1072: each prototype parm must be compatible with the promoted(!)
1073: definition parm.
1074: */
1075:
1076: #if ANSI && HAS_PROTOTYPES
1077: int niladic(void) { return 99; }
1078: int fn_char(int);
1079: int fn_char(); /* ok by rule 3 */
1080: int fn_dbl(double);
1081:
1082: #if ANSI8703 /* now old-style fn parms are taken as widened before type-matching */
1083: int fn_char(c) char c; { return 98; } /* ok by rule 4 */
1084: int fn_dbl(f) float f; { return 97; } /* ok by rule 4 */
1085: #else
1086: int fn_char(c) int c; { return 98; }
1087: int fn_dbl(f) double f; { return 97; }
1088: #endif /* ANSI8703 */
1089: int proto(char, short const int, int, int volatile long, float, double, long double);
1090:
1091: static void c3_5_4_3()
1092: {
1093: int proto(char, const short, int, volatile long, float, double, register long double); /* ok by rule 2 */
1094:
1095: iequals(__LINE__, niladic(), 99);
1096: iequals(__LINE__, fn_char(1), 98);
1097: iequals(__LINE__, fn_dbl(0.), 97);
1098: iequals(__LINE__, proto(1L, 1.0, 1L, '\01', 1, 1, 1), 7);
1099:
1100:
1101:
1102:
1103:
1104: /* 3.5.4.3 (cont.) */
1105: #if ANSI8804
1106: {
1107: int arrfn1();
1108: signed int arrfn1(); /* ok by rule 1 */
1109:
1110: /* ambiguity of typedef vs identifier is always resolved to typedef */
1111: /* so, single typedef name in parentheses is taken as fn of one parm, */
1112: /* not as redundant parentheses on a new identifier */
1113: typedef int I;
1114: int fpfi(int (*)(I)); /* parm is ptr to function of int arg returning int */
1115: iequals(__LINE__, fpfi(fn_char), ivalue(98));
1116: }
1117: #endif /* ANSI8804 */
1118: } /* end c3_5_4_3 (ANSI version) */
1119:
1120: #if ANSI8804
1121: int fpfi(int pfi(int)) { return pfi(0); }
1122: #endif
1123:
1124:
1125: int arrfn1();
1126: signed int arrfn1(); /* ok by rule 1 */
1127:
1128: #if NEW_STYLE_FN_DEF
1129: int proto(char x1, const short x2, int x3, volatile long x4, float x5, double x6, long double x7)
1130: #else
1131: int proto(x1, x2, x3, x4, x5, x6, x7)
1132: char x1; const short x2; register int x3; volatile long x4; float x5; double x6; long double x7;
1133: #endif /* NEW_STYLE_FN_DEF */
1134: {
1135: return((int)(x1+x2+x3+x4+x5+x6+x7));
1136: }
1137: #else /* if !ANSI || !HAS_PROTOTYPES */
1138: static void c3_5_4_3()
1139: {
1140: /* nothing to test, if no prototypes */
1141: }
1142: #endif /* ANSI && HAS_PROTOTYPES */
1143:
1144:
1145:
1146:
1147:
1148:
1149:
1150:
1151:
1152:
1153:
1154: /*
1155: * 3.5.5 - Type names
1156: */
1157: static void c3_5_5()
1158: {
1159: /* these are tested all over, but a few extra ones here ... */
1160:
1161: #if ANSI
1162: char *(*(*pfpapc1)(int, ...))[10];
1163: char *(*(*pfpapc2)(char *(*)()))[11] = 0;
1164: iequals(__LINE__, sizeof( char *(*(*)(int, ...))[10]), sizeof pfpapc1);
1165: pfpapc1 = (char *(*(*)(int, ...))[10])pfpapc2;
1166: #else
1167: char *(*(*pfpapc1)())[10];
1168: char *(*(*pfpapc2)())[11] = 0;
1169: iequals(__LINE__, sizeof(char *(*(*)())[10]), sizeof pfpapc1);
1170: pfpapc1 = (char *(*(*)())[10])pfpapc2;
1171: #endif
1172: checkthat( - __LINE__, pfpapc1 == 0);
1173: }
1174:
1175:
1176:
1177:
1178:
1179:
1180:
1181:
1182:
1183:
1184:
1185:
1186:
1187:
1188:
1189:
1190:
1191:
1192:
1193:
1194:
1195:
1196:
1197:
1198:
1199:
1200:
1201:
1202:
1203:
1204: /*
1205: * 3.5.6 - Type definitions
1206: */
1207: static void c3_5_6()
1208: {
1209: /* typedef is not a new type, but rather a synonym. */
1210: struct x
1211: {
1212: unsigned a:1;
1213: unsigned b:2;
1214: };
1215: typedef struct x X;
1216: X x1;
1217: struct x x2;
1218: unsigned us1;
1219: typedef unsigned US;
1220: US us2;
1221:
1222: x1.a = 2;
1223: x2.a = 2;
1224: iequals(__LINE__, x1.a, 0);
1225: iequals(__LINE__, x2.a, 0);
1226: us1 = us2 = MAX_UINT;
1227: iequals(__LINE__, ++us1, 0);
1228: iequals(__LINE__, ++us2, 0);
1229:
1230: /* ambiguity of typedef vs identifier is always resolved to typedef */
1231: /* In this case, "type spec shall not be omitted" means that if a symbol */
1232: /* could be either a type-name on an un-named field, or an identifier naming a field, */
1233: /* then it must be the former. */
1234: #if ANSI8804
1235: {
1236: typedef int I;
1237: struct { const I : 2; int j : 2; } x = {1}; /* "const I" is the type of un-named field */
1238:
1239: iequals(__LINE__, x.j, 1);
1240: }
1241: #endif /* ANSI8804 */
1242:
1243:
1244:
1245:
1246:
1247:
1248:
1249:
1250:
1251:
1252:
1253:
1254: /* 3.5.6 (cont.) */
1255: #if ANSI
1256: {
1257: /* typedefs can be nested */
1258: typedef int X;
1259: X a = 0;
1260: iequals(__LINE__, a, 0);
1261: {
1262: /* and redefined in other nested contexts */
1263: X X = 3;
1264: iequals(__LINE__, X, 3);
1265: }
1266: /* also, they don't interfere with other name spaces */
1267: {
1268: #if TAG_AND_MEMB_SPACES
1269: static struct X { int X; } x = {7};
1270: static struct Y { int Y; } y = {8};
1271: #else
1272: static struct X { int X1; } x = {7};
1273: static struct Y { int Y1; } y = {8};
1274: #endif
1275: static enum Z { e0, e1, e2 = (X)3 } e;
1276: struct X *px = (struct X *)&y;
1277:
1278: e = e2;
1279: iequals(__LINE__, a, 0);
1280: iequals(__LINE__, e, 3);
1281: #if TAG_AND_MEMB_SPACES
1282: iequals(__LINE__, x.X, 7);
1283: iequals(__LINE__, (X) px->X, 8);
1284: #else
1285: iequals(__LINE__, x.X1, 7);
1286: iequals(__LINE__, (X) px->X1, 8);
1287: #endif
1288: }
1289: }
1290: #endif /* ANSI */
1291: } /* end c3_5_6 */
1292:
1293:
1294:
1295:
1296:
1297:
1298:
1299:
1300:
1301:
1302:
1303:
1304: /*
1305: * 3.5.7 - Initialization
1306: */
1307: static int sarray[5];
1308: static struct { int a, b;} st;
1309: static struct s1 {int a, b;} s1_init = {3, 4};
1310:
1311: struct
1312: {
1313: char *strings[2];
1314: struct
1315: {
1316: int a;
1317: int nums[2][3];
1318: }s;
1319: }x3[] =
1320: /* note that each explicit initializer list can have an extra comma */
1321: {{{"abc", "def", }, {1, {{2,3,4,},{5,6,7,},},},},
1322: {{"ghi", "jkl"}, {9, {{8,7,6},{5,4,3}}}}},
1323: #if ANSI /* very strict about the "Ritchie" rules */
1324: x4[] = {"abc", "def", 1,2,3,4,5,6,7, {"ghi", "jkl", {9, {8,7,6,{5,4,3}}}}};
1325: int a1[2][2][2] = { 0, 1, 2, 3, {4, 5, 6, 7}};
1326: #else /* other compilers, e.g. PCC, vary, so use full braces */
1327: x4[] = {{{"abc", "def", }, {1, {{2,3,4,},{5,6,7,},},},}, {{"ghi", "jkl"}, {9, {{8,7,6},{5,4,3}}}}};
1328: int a1[2][2][2] = { 0, 1, 2, 3, 4, 5, 6, 7};
1329: #endif
1330: int a2[2][2][2] = { 0, 1, 2, 3, 4, 5, 6, 7};
1331:
1332: /* special case of a string literal */
1333: char s1[] = "abc";
1334: char s2[] = {'a', 'b', 'c', 0};
1335: #if ANSI
1336: char s3[3] = { "def" } ; /* optional braces */
1337: #else
1338: char s3[3] = "de";
1339: #endif
1340: #if ANSI8712 && WIDE_CHARS
1341: wchar_t s4[] = L"abc"; /* "wide-char" string */
1342: #endif
1343:
1344: /* if there are not enough initializers, close off the aggregate with 0 */
1345: int a3[2][2][2] =
1346: {{{99}}, {{98}}};
1347: struct
1348: {
1349: struct { int a, b;} sm1;
1350: struct { int a, b;} sm2;
1351: } s =
1352: {{11},{13}};
1353:
1354:
1355: /* 3.5.7 (cont.) */
1356: #if ANSI
1357: /* unions can be intiialized to their first element */
1358: union
1359: {
1360: double d;
1361: int i;
1362: } u1 = {2.2};
1363: #endif
1364:
1365: static void c3_5_7()
1366: {
1367: int i = {2};
1368: int j, k, count;
1369: /* auto variables can be initialized to arbitrary expressions */
1370: int a = {1}, b = a*3, c = ivalue(5); /* braces optional on single scalar */
1371:
1372: #if ANSI
1373: union
1374: {
1375: double d;
1376: int i;
1377: } u2 = {3.3};
1378: /* aggregates can be initialized */
1379: int aarray[4] = {0, 1, 2, 3};
1380: struct { int a[3], b; } w[] = { {1}, 2 }; /* "inconsistent-braces" example from 3.5.7 */
1381:
1382: for (i = 0; i < 4; ++i)
1383: iequals(__LINE__, aarray[i], i);
1384: iequals(__LINE__, w[0].a[0], 1);
1385: iequals(__LINE__, w[1].a[0], 2);
1386: iequals(__LINE__, w[0].a[1], 0);
1387: iequals(__LINE__, w[1].a[1], 0);
1388: iequals(__LINE__, w[0].b, 0);
1389: #endif /* ANSI */
1390:
1391: #if ANSI
1392: /* initialize one structure with another */
1393: {
1394: struct s1 x = s1_init;
1395: iequals(__LINE__, x.a, 3);
1396: iequals(__LINE__, x.b, 4);
1397: }
1398: #endif
1399:
1400:
1401:
1402:
1403:
1404: /* 3.5.7 (cont.) */
1405: iequals(__LINE__, a, 1);
1406: iequals(__LINE__, b, 3);
1407: iequals(__LINE__, c, 5);
1408:
1409: /* static items without initializers are initialized to 0 */
1410: for (i = 0; i < 5; ++i)
1411: iequals(__LINE__, sarray[i], 0);
1412: iequals(__LINE__, st.a, 0);
1413: iequals(__LINE__, st.b, 0);
1414:
1415: /* x3 used the explicit form for sub aggregates */
1416: checkthat(__LINE__, 0 == str_cmp(x3[1].strings[1], "jkl"));
1417: iequals(__LINE__, x3[0].s.nums[0][0], 2);
1418: iequals(__LINE__, x3[0].s.nums[1][2], 7);
1419: iequals(__LINE__, x3[1].s.nums[0][0], 8);
1420: iequals(__LINE__, x3[1].s.nums[1][2], 3);
1421:
1422: /* x4 left out some of them , but should look the same */
1423: checkthat(__LINE__, 0 == str_cmp(x4[1].strings[1], "jkl"));
1424: iequals(__LINE__, x4[0].s.nums[0][0], 2);
1425: iequals(__LINE__, x4[0].s.nums[1][2], 7);
1426: iequals(__LINE__, x4[1].s.nums[0][0], 8);
1427: iequals(__LINE__, x4[1].s.nums[1][2], 3);
1428:
1429: /* the two should be identical */
1430: checkthat(__LINE__, sizeof x3 == sizeof x4);
1431:
1432: /* elision of braces */
1433: for (i = 0, count = 0; i < 2; ++i)
1434: for (j = 0; j < 2; ++j)
1435: for (k = 0; k < 2; ++k, ++count)
1436: iequals(__LINE__, a1[i][j][k], count);
1437: for (i = 0, count = 0; i < 2; ++i)
1438: for (j = 0; j < 2; ++j)
1439: for (k = 0; k < 2; ++k, ++count)
1440: iequals(__LINE__, a2[i][j][k], count);
1441:
1442: /* special forms using string literal initialization */
1443: checkthat(__LINE__, !str_cmp(s1, s2));
1444: iequals(__LINE__, s3[0], 'd');
1445: iequals(__LINE__, s3[1], 'e');
1446: iequals(__LINE__, s3[2], ANSI ? 'f' : '\0');
1447:
1448:
1449:
1450:
1451:
1452:
1453:
1454: /* 3.5.7 (cont.) */
1455: /* partial intialization fills with 0 */
1456: for (i = 0, count = 0; i < 2; ++i)
1457: for (j = 0; j < 2; ++j)
1458: for (k = 0; k < 2; ++k, ++count)
1459: if (count == 0)
1460: iequals(__LINE__, a3[i][j][k], 99);
1461: else if (count == 4)
1462: iequals(__LINE__, a3[i][j][k], 98);
1463: else
1464: iequals(__LINE__, a3[i][j][k], 0);
1465: iequals(__LINE__, s.sm1.a, 11);
1466: iequals(__LINE__, s.sm1.b, 0);
1467: iequals(__LINE__, s.sm2.a, 13);
1468: iequals(__LINE__, s.sm2.b, 0);
1469:
1470: #if ANSI
1471: /* check union initialization */
1472: dequals(__LINE__, u1.d, 2.2);
1473: dequals(__LINE__, u2.d, 3.3);
1474:
1475: /* auto aggregates are zero-padded */
1476: {
1477: auto int a[10] = {1};
1478: int i;
1479:
1480: for (i = 1; i < 10; ++i)
1481: iequals(__LINE__, a[i], 0);
1482: }
1483: /* full-expr in initializer is sequence point */
1484: {
1485: int a = ivalue(1), b = a++, c = ++b;
1486:
1487: iequals(__LINE__, a, ivalue(2));
1488: iequals(__LINE__, b, ivalue(2));
1489: iequals(__LINE__, c, ivalue(2));
1490: }
1491:
1492: #endif /* ANSI */
1493:
1494:
1495:
1496:
1497:
1498:
1499:
1500:
1501:
1502:
1503:
1504: /* 3.5.7 (cont.) */
1505: #if ANSI8804
1506: /* un-named members are ignored during initialization */
1507: {
1508: struct s1
1509: {
1510: unsigned m1:2;
1511: unsigned :2;
1512: unsigned m2:2;
1513: unsigned m3:2;
1514: } s1 = { 1, 2 };
1515: iequals(__LINE__, s1.m1, 1);
1516: iequals(__LINE__, s1.m2, 2);
1517: iequals(__LINE__, s1.m3, 0);
1518: }
1519: #endif /* ANSI8804 */
1520:
1521: } /* end c3_5_7 */
1522:
1523: #else /* if SKIP35 */
1524: void c3_5() { pr_skip("c3_5: SKIPPED ENTIRELY\n"); }
1525: #endif /* SKIP35 */
1526:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.