@@ -1802,6 +1802,13 @@ static void parse(void)
1802
1802
case tFORWARD :
1803
1803
funcstub (FALSE);
1804
1804
break ;
1805
+ case t__STATIC_ASSERT :
1806
+ case t__STATIC_CHECK : {
1807
+ int use_warning = (tok == t__STATIC_CHECK );
1808
+ do_static_check (use_warning );
1809
+ needtoken (';' );
1810
+ break ;
1811
+ } /* case */
1805
1812
case '}' :
1806
1813
error (54 ); /* unmatched closing brace */
1807
1814
break ;
@@ -8530,3 +8537,96 @@ SC_FUNC void pragma_nodestruct(symbol *sym)
8530
8537
if (sym -> ident == iVARIABLE || sym -> ident == iARRAY )
8531
8538
sym -> usage |= uNODESTRUCT ;
8532
8539
}
8540
+
8541
+ /* do_static_check()
8542
+ * Checks compile-time assertions and triggers an error/warning.
8543
+ *
8544
+ * The 'use_warning' parameter is set to TRUE if warnings are to be
8545
+ * used instead of errors to notify assertion failures.
8546
+ */
8547
+ SC_FUNC cell do_static_check (int use_warning )
8548
+ {
8549
+ int already_staging ,didalloc ,optmsg ;
8550
+ int ident ,index ;
8551
+ int bck_litidx ;
8552
+ int exprstartfline ,exprendfline ;
8553
+ cell cidx ,val ;
8554
+ char * str ;
8555
+ const unsigned char * exprstart ,* exprend ;
8556
+
8557
+ str = NULL ;
8558
+ didalloc = optmsg = FALSE;
8559
+ index = 0 ;
8560
+ cidx = 0 ;
8561
+
8562
+ needtoken ('(' );
8563
+ already_staging = stgget (& index ,& cidx );
8564
+ if (!already_staging ) {
8565
+ stgset (TRUE); /* start stage-buffering */
8566
+ errorset (sEXPRMARK ,0 );
8567
+ } /* if */
8568
+ exprstart = lptr ;
8569
+ exprstartfline = fline ;
8570
+ ident = expression (& val ,NULL ,NULL ,FALSE);
8571
+ if (ident != iCONSTEXPR )
8572
+ error (8 ); /* must be constant expression */
8573
+ exprend = lptr ;
8574
+ exprendfline = fline ;
8575
+ stgdel (index ,cidx ); /* scratch generated code */
8576
+ if (!already_staging ) {
8577
+ errorset (sEXPRRELEASE ,0 );
8578
+ stgset (FALSE); /* stop stage-buffering */
8579
+ } /* if */
8580
+
8581
+ /* don't bother allocating space and copying the message
8582
+ * if the expression is true */
8583
+ if (val == 0 ) {
8584
+ if (exprstartfline == exprendfline ) {
8585
+ /* skip leading whitespaces */
8586
+ while (* exprstart == ' ' )
8587
+ exprstart ++ ;
8588
+ /* strip the trailing ',' or ')'. as well as the whitespaces */
8589
+ exprend -- ;
8590
+ if (* exprend == ')' || * exprend == ',' ) {
8591
+ while (* (exprend - 1 )== ' ' )
8592
+ exprend -- ;
8593
+ } /* if */
8594
+ /* copy the expression string */
8595
+ str = malloc ((exprend - exprstart + 1 )* sizeof (char ));
8596
+ if (str == NULL )
8597
+ error (103 ); /* insufficient memory */
8598
+ memcpy (str ,exprstart ,exprend - exprstart );
8599
+ str [exprend - exprstart ]= '\0' ;
8600
+ didalloc = TRUE;
8601
+ } else {
8602
+ /* Currently there's no reliable way to capture multiline expressions,
8603
+ * as the lexer would only keep the contents of the line the expression
8604
+ * ends at, so try to print "-epression-" instead. Not the prefect
8605
+ * solution, but at least it's better than not printing anything. */
8606
+ str = "-expression-" ;
8607
+ } /* if */
8608
+ } /* if */
8609
+
8610
+ /* read the optional message */
8611
+ if (matchtoken (',' )) {
8612
+ if (didalloc ) {
8613
+ free (str );
8614
+ didalloc = FALSE;
8615
+ } /* if */
8616
+ optmsg = TRUE;
8617
+ str = parsestringparam (val != 0 ,& bck_litidx );
8618
+ } /* if */
8619
+
8620
+ if (val == 0 ) {
8621
+ int errnum = use_warning ? 249 /* check failed */
8622
+ : 110 ; /* assertion failed */
8623
+ error (errnum ,(str != NULL ) ? str : "" );
8624
+ if (didalloc )
8625
+ free (str );
8626
+ else if (optmsg && str != NULL )
8627
+ litidx = bck_litidx ; /* remove the string from the literal queue */
8628
+ } /* if */
8629
+
8630
+ needtoken (')' );
8631
+ return !!val ;
8632
+ }
0 commit comments