source: tests/array-container/dimexpr-match.hfa @ 3bf9d10

Last change on this file since 3bf9d10 was 0f4ac10, checked in by Michael Brooks <mlbrooks@…>, 13 months ago

Add tests demonstrating CFA's treatment of C arrays, compared with GCC's.

These tests recognize two levels of CFA functionality: Classic and Preview. This commit shows that CFA Master implements Classic. Preview refers to Mike's forthcoming changes.

Only the CFA part runs in the nightly build. Under CFA Classic, a limitation is that only some rejection cases are exercised in the nightly build. A hand-driven testing script can access all the cases and CFA Preview will exercise all the cases in the nightly build.

test dimexpr-match-c: how CFA's treatment of C arrays compares with GCC's

test dimexpr-match-cfa: how CFA's treamtment of <containers/array.hfa>-arrays aligns with the above

  • Property mode set to 100644
File size: 12.4 KB
Line 
1
2
3//  Framework for the dimexpr-match tests.
4//
5//  These tests show whether an expression of type like `float (*)[25]`
6//  can be used in a context expecting a type like `float (*)[rand()]`.
7//
8//  A test includes this header and defines the function `runTests`.
9//  The `runTests` body is made with macros defined here.
10//
11//  Normally, drive a test either from test.py or ./dimexpr-match-detail.sh.
12//  Direct usage is for making small repro cases, while troubleshooting a problem.
13//
14//  Direct usage is:
15//
16//      compiler=gcc -x c           # pick one
17//      compiler=$fa
18//
19//      test=dimexpr-match-c.cfa    # pick one
20//      test=dimexpr-match-cfa.cfa
21//
22//      $compiler $test
23//      ./a.out
24//      ./a.out -cmd4skip | sed -E -n 's/skip.*\| *//p'
25//
26//  Expect the above compiler invocation to report success.
27//  Expect the first a.out invocation to print a mix of "done" and "skipped" messages.
28//  Assume the second a.out invocation (through sed) prints several compiler CLI invocations.  For each...
29//  Expect that running the current compiler invocation reports an error.
30//  So far, this is what dimexpr-match-detail.sh does.
31//
32//  The macro logic in here is hard to read.
33//  A specific test's TRY_COMPAT definition is easy to read.
34//
35//  An error message from an unexpected rejection is hard to read, because the message blames a macro.
36//  To diagnose one, first obtain the failing case's coordinates by ruuning:
37//      $compiler $test -E -P -DEMIT_COORDS > temp.cfa  # just preprocessor
38//      $compiler temp.cfa                              # will fail, want message
39//  Open temp.cfa and chase an error detail's line number, to find the failing code.
40//  Look at the pragma-message above the failing line, and read off the failure's -D coordinates.
41//  Isolate this case by running:                              ... copied from pragma message ...............................................................................................
42//      $compiler $test -E -P -DEMIT_MINIMAL -DINCLUDE_MINIMAL -DARRANGEMENT__OPTIN -DARRANGEMENT_PTRPARM_---- -DCASE_MANUAL -DCASE_FORMATION_L=--- -DCASE_FORMATION_R=--- -DCASE_EQUALITY=-- > mycase.cfa  # template
43//      $compiler $test -E -P -DEMIT_MINIMAL -DINCLUDE_MINIMAL -DARRANGEMENT__OPTIN -DARRANGEMENT_PTRPARM_CALL -DCASE_MANUAL -DCASE_FORMATION_L=LIT -DCASE_FORMATION_R=LIT -DCASE_EQUALITY=NE > mycase.cfa  # example
44//      $compiler mycase.cfa
45//  The content of mycase.cfa is easy to read.
46
47#ifdef __cforall
48    extern "C" {
49        int strcmp (const char* str1, const char* str2);
50    }
51    #define NULL 0p
52#else
53    #include <stdio.h>
54    #include <string.h>
55#endif
56
57#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
58#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
59
60#define DO_PRAGMA(x) _Pragma (#x)
61#define DO_MESSAGE(x) DO_PRAGMA(message #x)
62
63#ifdef EMIT_COORDS
64#define MAYPRINT(...)
65#define MAYDELIMIT( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ) \
66    DO_MESSAGE(-DARRANGEMENT__OPTIN -DARRANGEMENT_ ## ARR_NAME -DCASE_MANUAL -DCASE_FORMATION_L=KL -DCASE_FORMATION_R=KR -DCASE_EQUALITY=ISEQ)
67#else
68#define MAYPRINT(...) printf(__VA_ARGS__);
69#define MAYDELIMIT( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME )
70#endif
71
72#ifdef EMIT_MINIMAL
73#undef MAYPRINT
74#define MAYPRINT(...)
75#endif
76
77#define GRP_K_LIT STA
78#define GRP_K_ENU STA
79#define GRP_K_CPR DYN
80#define GRP_K_DIM DYN
81#define GRP_K_MUT UNS
82#define GRP_K( K ) GRP_K_ ## K
83
84#define MKV7_LIT 7
85#define MKV7_ENU enu7
86#define MKV7_CPR cpr7
87#define MKV7_DIM dim7
88#define MKV7_MUT mut7
89#define MKV7( K ) MKV7_ ## K
90
91#define MKV42_LIT 42
92#define MKV42_ENU enu42
93#define MKV42_CPR cpr42
94#define MKV42_DIM dim42
95#define MKV42_MUT mut42
96#define MKV42( K ) MKV42_ ## K
97
98#define MKLV( LK ) MKV7( LK )
99
100#define MKRV_EQ( KR ) MKV7(KR)
101#define MKRV_NE( KR ) MKV42(KR)
102#define MKRV( KR, ISEQ ) MKRV_ ## ISEQ( KR )
103
104#ifdef __cforall
105#define RULE_PFX RULE_CF_
106#else
107#define RULE_PFX RULE_C_
108#endif
109
110#define X_CASE_2( KL, KR, ISEQ, FL, FR, ARR_NAME ) \
111    MAY_TRY_COMPAT( \
112        CAT(CAT(CAT(CAT(CAT(RULE_PFX, ISEQ), _), FL), _), FR), \
113        MKLV( KL ), \
114        MKRV( KR, ISEQ ), \
115        KL, KR, FL, FR, ISEQ, ARR_NAME \
116    )
117
118#define X_CASE( KL, KR, ISEQ, ARR_NAME ) X_CASE_2( KL, KR, ISEQ, GRP_K(KL), GRP_K(KR), ARR_NAME )
119
120#ifdef ERRS
121#define MAY_TRY_COMPAT_REJ( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ) \
122    _Pragma("message \"Expect fail\"") \
123    MAY_TRY_COMPAT_ACC( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME )
124#else
125#define MAY_TRY_COMPAT_REJ( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ) \
126    MAYPRINT("skip %s %s %s, L=%s, R=%s",  #FL, #ISEQ, #FR, #LV, #RV ) \
127    if (cmd4skip) { \
128        MAYPRINT(" | -DERRS -Werror %s -DARRANGEMENT__OPTIN -DARRANGEMENT_%s -DCASE_MANUAL -DCASE_FORMATION_L=%s -DCASE_FORMATION_R=%s -DCASE_EQUALITY=%s",  __FILE__, #ARR_NAME, #KL, #KR, #ISEQ ) \
129    } \
130    MAYPRINT("\n")
131#endif
132
133#define MAY_TRY_COMPAT_ACC( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ) \
134    MAYDELIMIT( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ) \
135    TRY_COMPAT(LV, RV) \
136    MAYPRINT("done %s %s %s, L=%s, R=%s\n",  #FL, #ISEQ, #FR, #LV, #RV )
137
138#define MAY_TRY_COMPAT(EXPECT, LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME) \
139    CAT(MAY_TRY_COMPAT_, EXPECT( LV, RV, KL, KR, FL, FR, ISEQ, ARR_NAME ))
140
141#define TCXXX(Q) Q
142#define TCXX(Q) #Q
143
144#define QUOTE(str) #str
145#define EXPAND_AND_QUOTE(str) QUOTE(str)
146#define TRY_COMPAT_E EXPAND_AND_QUOTE(TRY_COMPAT(__L__,__R__))
147
148// Temporary: CFA is classic by default
149#if defined CFA_IS_PREVIEW && defined CFA_IS_CLASSIC
150#error Must not define both CFA_IS_CLASSIC, CFA_IS_PREVIEW
151#endif
152#if ! defined CFA_IS_PREVIEW && ! defined CFA_IS_CLASSIC
153#define CFA_IS_CLASSIC
154#endif
155
156#if ! defined __cforall
157#define SUPPRESS_FORALL_N
158#endif
159
160#if defined SUPPRESS_FORALL_N_ON_CLASSIC && defined CFA_IS_CLASSIC
161#define SUPPRESS_FORALL_N
162#endif
163
164/*
165
166RULE macros define the expected outcome:
167Given a compiler's functionality level and a  test case, do we expect the compiler to accept or reject the case?
168
169Group STA: Statically stable
170    - literal
171    - enumeration
172
173Group DYN: Dynamically stable
174    - parameter that is a constant
175    - static constant global
176
177Group UNS: potentially Unstable
178    - variable
179    - parameter that is a constant reference to constant
180    - function return
181    - extern constant (safe and annoying here; must be here if you can link it to something that changes)
182
183C rules
184    - Reject a pair from group STA if it has two different values
185    - otherwise, accept
186
187CFA "classic" rules (what CFA actually does, before Mike brings in CFA rules)
188    - same as C, except
189    - reject STA/non-STA crossing
190
191CFA rules ("preview" only)
192    - accept a pair from group STA if it has the same value
193    - accept a pair from group DYN if it is written out the same (e.g. refers to same variable)
194    - otherwise, reject
195        (notably, reject all group UNS)
196        (notably, reject any group crossing)
197
198The RULE_* definitions below encode the summary above into the test harness's format.
199This format is: tabled function to {ACC,REJ} from {STA,DYN,UNS}^2 x {EQ,NE}
200
201*/
202
203#define RULE_C_EQ_STA_STA  ACC
204#define RULE_C_EQ_STA_DYN  ACC
205#define RULE_C_EQ_STA_UNS  ACC
206#define RULE_C_EQ_DYN_STA  ACC
207#define RULE_C_EQ_DYN_DYN  ACC
208#define RULE_C_EQ_DYN_UNS  ACC
209#define RULE_C_EQ_UNS_STA  ACC
210#define RULE_C_EQ_UNS_DYN  ACC
211#define RULE_C_EQ_UNS_UNS  ACC
212
213#define RULE_C_NE_STA_STA  REJ
214#define RULE_C_NE_STA_DYN  ACC
215#define RULE_C_NE_STA_UNS  ACC
216#define RULE_C_NE_DYN_STA  ACC
217#define RULE_C_NE_DYN_DYN  ACC
218#define RULE_C_NE_DYN_UNS  ACC
219#define RULE_C_NE_UNS_STA  ACC
220#define RULE_C_NE_UNS_DYN  ACC
221#define RULE_C_NE_UNS_UNS  ACC
222
223#ifdef CFA_IS_CLASSIC
224
225#define RULE_CF_EQ_STA_STA  ACC
226#define RULE_CF_EQ_STA_DYN  REJ
227#define RULE_CF_EQ_STA_UNS  REJ
228#define RULE_CF_EQ_DYN_STA  REJ
229#define RULE_CF_EQ_DYN_DYN  ACC
230#define RULE_CF_EQ_DYN_UNS  ACC
231#define RULE_CF_EQ_UNS_STA  REJ
232#define RULE_CF_EQ_UNS_DYN  ACC
233#define RULE_CF_EQ_UNS_UNS  ACC
234
235#define RULE_CF_NE_STA_STA  REJ
236#define RULE_CF_NE_STA_DYN  REJ
237#define RULE_CF_NE_STA_UNS  REJ
238#define RULE_CF_NE_DYN_STA  REJ
239#define RULE_CF_NE_DYN_DYN  ACC
240#define RULE_CF_NE_DYN_UNS  ACC
241#define RULE_CF_NE_UNS_STA  REJ
242#define RULE_CF_NE_UNS_DYN  ACC
243#define RULE_CF_NE_UNS_UNS  ACC
244
245#else
246
247#define RULE_CF_EQ_STA_STA  ACC
248#define RULE_CF_EQ_STA_DYN  REJ
249#define RULE_CF_EQ_STA_UNS  REJ
250#define RULE_CF_EQ_DYN_STA  REJ
251#define RULE_CF_EQ_DYN_DYN  ACC
252#define RULE_CF_EQ_DYN_UNS  REJ
253#define RULE_CF_EQ_UNS_STA  REJ
254#define RULE_CF_EQ_UNS_DYN  REJ
255#define RULE_CF_EQ_UNS_UNS  REJ
256
257#define RULE_CF_NE_STA_STA  REJ
258#define RULE_CF_NE_STA_DYN  REJ
259#define RULE_CF_NE_STA_UNS  REJ
260#define RULE_CF_NE_DYN_STA  REJ
261#define RULE_CF_NE_DYN_DYN  REJ
262#define RULE_CF_NE_DYN_UNS  REJ
263#define RULE_CF_NE_UNS_STA  REJ
264#define RULE_CF_NE_UNS_DYN  REJ
265#define RULE_CF_NE_UNS_UNS  REJ
266
267#endif
268
269#ifndef ARRANGEMENT__OPTIN
270#define ARRANGEMENT_PTRVAR_INIT 1
271#define ARRANGEMENT_PTRPARM_CALL 1
272#define ARRANGEMENT_PTRVAR_ASGN 1
273#define ARRANGEMENT_REFVAR_INIT 1
274#define ARRANGEMENT_REFPARM_CALL 1
275#define ARRANGEMENT_REFVAR_ASGN 1
276#define ARRANGEMENT_CALLZIP 1
277#endif
278
279#define EMIT_SKIP( ARR_NAME ) \
280    MAYPRINT( "---- " #ARR_NAME " skipped\n" )
281
282#define MAY_EMIT_ARRANGEMENT_PTRVAR_INIT( ARR_NAME ) EMIT_SKIP( ARR_NAME )
283#define MAY_EMIT_ARRANGEMENT_PTRPARM_CALL( ARR_NAME ) EMIT_SKIP( ARR_NAME )
284#define MAY_EMIT_ARRANGEMENT_PTRVAR_ASGN( ARR_NAME ) EMIT_SKIP( ARR_NAME )
285#define MAY_EMIT_ARRANGEMENT_REFVAR_INIT( ARR_NAME ) EMIT_SKIP( ARR_NAME )
286#define MAY_EMIT_ARRANGEMENT_REFPARM_CALL( ARR_NAME ) EMIT_SKIP( ARR_NAME )
287#define MAY_EMIT_ARRANGEMENT_REFVAR_ASGN( ARR_NAME ) EMIT_SKIP( ARR_NAME )
288#define MAY_EMIT_ARRANGEMENT_CALLZIP( ARR_NAME ) EMIT_SKIP( ARR_NAME )
289
290#define MAY_EMIT_1( ARR_NAME ) \
291    MAYPRINT( "---- " #ARR_NAME ":   " TRY_COMPAT_E "\n" ) \
292    RUNCASES( ARR_NAME )
293
294#ifndef CASE_MANUAL
295  #define RUNCASES( ARR_NAME ) \
296    X_CASE( LIT, LIT, EQ, ARR_NAME ) \
297    X_CASE( LIT, LIT, NE, ARR_NAME ) \
298    X_CASE( LIT, ENU, EQ, ARR_NAME ) \
299    X_CASE( LIT, ENU, NE, ARR_NAME ) \
300    X_CASE( LIT, CPR, NE, ARR_NAME ) \
301    X_CASE( LIT, MUT, NE, ARR_NAME ) \
302    X_CASE( ENU, ENU, EQ, ARR_NAME ) \
303    X_CASE( ENU, ENU, NE, ARR_NAME ) \
304    X_CASE( ENU, LIT, EQ, ARR_NAME ) \
305    X_CASE( ENU, LIT, NE, ARR_NAME ) \
306    X_CASE( ENU, CPR, NE, ARR_NAME ) \
307    X_CASE( ENU, MUT, NE, ARR_NAME ) \
308    X_CASE( CPR, CPR, EQ, ARR_NAME ) \
309    X_CASE( CPR, CPR, NE, ARR_NAME ) \
310    X_CASE( CPR, LIT, NE, ARR_NAME ) \
311    X_CASE( CPR, ENU, NE, ARR_NAME ) \
312    X_CASE( CPR, MUT, NE, ARR_NAME ) \
313    X_CASE( MUT, MUT, EQ, ARR_NAME ) \
314    X_CASE( MUT, MUT, NE, ARR_NAME ) \
315    X_CASE( MUT, LIT, NE, ARR_NAME ) \
316    X_CASE( MUT, ENU, NE, ARR_NAME ) \
317    X_CASE( MUT, CPR, NE, ARR_NAME ) \
318    RUNCASES_FORALL_N( ARR_NAME )
319
320  #ifndef SUPPRESS_FORALL_N
321  #define RUNCASES_FORALL_N( ARR_NAME ) \
322    X_CASE( LIT, DIM, NE, ARR_NAME ) \
323    X_CASE( ENU, DIM, NE, ARR_NAME ) \
324    X_CASE( CPR, DIM, NE, ARR_NAME ) \
325    X_CASE( DIM, DIM, EQ, ARR_NAME ) \
326    X_CASE( DIM, DIM, NE, ARR_NAME ) \
327    X_CASE( DIM, LIT, NE, ARR_NAME ) \
328    X_CASE( DIM, ENU, NE, ARR_NAME ) \
329    X_CASE( DIM, CPR, NE, ARR_NAME ) \
330    X_CASE( DIM, MUT, NE, ARR_NAME ) \
331    X_CASE( MUT, DIM, NE, ARR_NAME )
332  #else
333  #define RUNCASES_FORALL_N( ARR_NAME )
334  #endif
335
336#else
337    #ifndef CASE_FORMATION_L
338    #error CASE_FORMATION_L not specified along with CASE_MANUAL
339    #endif
340    #ifndef CASE_FORMATION_R
341    #error CASE_FORMATION_R not specified along with CASE_MANUAL
342    #endif
343    #ifndef CASE_EQUALITY
344    #error CASE_EQUALITY not specified along with CASE_MANUAL
345    #endif
346    #define RUNCASES( ARR_NAME ) X_CASE( CASE_FORMATION_L, CASE_FORMATION_R, CASE_EQUALITY, ARR_NAME )
347#endif
348
349#define ARRANGEMENT( ARR_NAME ) CAT(MAY_EMIT_, CAT(ARRANGEMENT_, ARR_NAME)) ( ARR_NAME )
350
351
352#if defined SUPPRESS_FORALL_N
353
354    #define DECLN_runTests                   \
355        void runTests(                       \
356            const int cpr7, const int cpr42, \
357            int cmd4skip                     \
358        )
359#else
360
361    forall( [N] ) struct quicktag {};
362
363    #define DECLN_runTests                   \
364        forall( [dim7], [dim42] )            \
365        void runTests(                       \
366            const int cpr7, const int cpr42, \
367            quicktag(dim7), quicktag(dim42), \
368            int cmd4skip                     \
369        )
370#endif
371
372DECLN_runTests;
373
374int main(int argc, const char *argv[]) {
375
376    int cmd4skip = 0;
377
378    if (argc > 1 && strcmp("-cmd4skip", argv[1]) == 0) {
379        cmd4skip = 1;
380    }
381
382  #if defined SUPPRESS_FORALL_N
383    runTests(7, 42, cmd4skip);
384  #else
385    quicktag(7) tag7;
386    quicktag(42) tag42;
387    runTests(7, 42, tag7, tag42, cmd4skip);
388  #endif
389
390    return 0;
391}
Note: See TracBrowser for help on using the repository browser.