From 6f2eb301e59dc1116c14da167601deecf9b4934a Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sat, 4 Jan 2020 00:59:23 -0600 Subject: [PATCH] Implement C11 _Static_assert mechanism. This allows code to contain static assertions (checked at compile time). --- CC.pas | 3 ++- ORCACDefs/assert.h | 11 ++++++++-- Parser.pas | 51 +++++++++++++++++++++++++++++++++++----------- Scanner.pas | 1 + 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CC.pas b/CC.pas index fdb587f..3099ab5 100644 --- a/CC.pas +++ b/CC.pas @@ -113,7 +113,8 @@ while token.kind <> eofsy do begin {compile the program} unsignedsy,signedsy,intsy,longsy,charsy,shortsy, floatsy,doublesy,compsy,extendedsy,enumsy, structsy,unionsy,typedef,voidsy,inlinesy,volatilesy, - constsy,ident,asmsy,pascalsy,asmsy,segmentsy]) + constsy,ident,asmsy,pascalsy,asmsy,segmentsy, + _Static_assertsy]) then DoDeclaration(false, false) else begin diff --git a/ORCACDefs/assert.h b/ORCACDefs/assert.h index 8a9ec39..7c04dbc 100644 --- a/ORCACDefs/assert.h +++ b/ORCACDefs/assert.h @@ -14,10 +14,17 @@ #undef assert #endif -extern void __assert(char *, int, char *); - #ifndef NDEBUG #define assert(expression) (expression) ? ((void) 0) : (__assert(__FILE__, __LINE__, #expression)) #else #define assert(expression) ((void) 0) #endif + +#ifndef __assert__ +#define __assert__ + +extern void __assert(char *, int, char *); + +#define static_assert _Static_assert + +#endif diff --git a/Parser.pas b/Parser.pas index 566d601..5fdf32c 100644 --- a/Parser.pas +++ b/Parser.pas @@ -607,7 +607,7 @@ var and (token.kind in [autosy,registersy,unsignedsy,signedsy,intsy,longsy, charsy,shortsy,floatsy,doublesy,compsy,extendedsy,enumsy, structsy,unionsy,typedef,voidsy,volatilesy,constsy, - externsy,staticsy,typedefsy]) then begin + externsy,staticsy,typedefsy,_Static_assertsy]) then begin DoDeclaration(false, true) end {if} else if token.kind <> semicolonch then begin @@ -2513,6 +2513,25 @@ useGlobalPool := luseGlobalPool; {restore useGlobalPool} end; {Initializer} +procedure DoStaticAssert; + +{ process a static assertion } + +begin {DoStaticAssert} +NextToken; +Match(lparench, 13); +Expression(arrayExpression, [commach]); +if (expressionType = nil) or (expressionType^.kind <> scalarType) then + Error(18) +else if expressionValue = 0 then + Error(132); +Match(commach, 86); +Match(stringconst, 83); +Match(rparench, 12); +Match(semicolonch, 22); +end; {DoStaticAssert} + + procedure TypeSpecifier {doingFieldList,isConstant: boolean}; { handle a type specifier } @@ -2551,7 +2570,9 @@ var { } { parameters } { tp - place to store the type pointer } - + + label 1; + var bitDisp: integer; {current bit disp} disp: longint; {current byte disp} @@ -2575,15 +2596,14 @@ var maxDisp := 0; didFlexibleArray := false; fl := nil; {nothing in the field list, yet} - {check for no declarations} - if not (token.kind in [unsignedsy,signedsy,intsy,longsy,charsy,shortsy, - floatsy,doublesy,compsy,extendedsy,enumsy,structsy,unionsy,typedefsy, - typedef,voidsy,constsy,volatilesy]) then - Error(26); {while there are entries in the field list...} - while token.kind in [unsignedsy,signedsy,intsy,longsy,charsy,shortsy,floatsy, +1: while token.kind in [unsignedsy,signedsy,intsy,longsy,charsy,shortsy,floatsy, doublesy,compsy,extendedsy,enumsy,structsy,unionsy,typedefsy,typedef, - voidsy,constsy,volatilesy] do begin + voidsy,constsy,volatilesy,_Static_assertsy] do begin + if token.kind = _Static_assertsy then begin + DoStaticAssert; + goto 1; + end; {if} typeSpec := wordPtr; {default type specifier is an integer} TypeSpecifier(true,false); {get the type specifier} if not skipDeclarator then @@ -2689,7 +2709,9 @@ var else tp^.size := maxDisp; tp^.fieldList := ufl; - end; {if} + end {if} + else + Error(26); {error if no named declarations} storageClass := lStorageClass; {restore default storage class} isForwardDeclared := lisForwardDeclared; {restore the forward flag} doingParameters := ldoingParameters; {restore the parameters flag} @@ -3052,7 +3074,7 @@ procedure DoDeclaration {doingPrototypes, autoOrRegisterOnly: boolean}; { parameters: } { doingPrototypes - are we processing a parameter list? } -label 1,2,3; +label 1,2,3,4; var done: boolean; {for loop termination} @@ -3279,6 +3301,10 @@ var begin {DoDeclaration} +if token.kind = _Static_assertsy then begin + DoStaticAssert; + goto 4; + end; {if} lDoingParameters := doingParameters; {record the status} noFDefinitions := false; {are function definitions inhibited?} typeFound := false; {no explicit type found, yet} @@ -3718,6 +3744,7 @@ else {if not isFunction then} begin doingParameters := lDoingParameters; {restore the status} useGlobalPool := lUseGlobalPool; inhibitHeader := false; +4: end; {DoDeclaration} @@ -3745,7 +3772,7 @@ case statementList^.kind of unsignedsy,signedsy,intsy,longsy,charsy,shortsy, floatsy,doublesy,compsy,extendedsy,enumsy, structsy,unionsy,typedef,voidsy,volatilesy, - constsy]) + constsy,_Static_assertsy]) then begin hasStatementNext := false; if token.kind <> typedef then diff --git a/Scanner.pas b/Scanner.pas index 46e1856..18d6f61 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -646,6 +646,7 @@ if list or (numErr <> 0) then begin 129: msg := @'lint: division by zero'; 130: msg := @'lint: invalid shift count'; 131: msg := @'numeric constant is too long'; + 132: msg := @'static assertion failed'; otherwise: Error(57); end; {case} writeln(msg^);