Handle storage class specifiers in DeclarationSpecifiers.

_Thread_local is recognized but gives a "not supported" error. It could arguably be 'supported' trivially by saying the execution of an ORCA/C program is just one thread and so no special handling is needed, but that likely isn't what someone using it would expect.

There would be a possible issue if a "static" or "typedef" storage class specifier occurred after a type specifier that required memory to be allocated for it, because that memory conceptually might be in the local pool, but static objects are processed at the end of the translation unit, so their types need to stick around. In practice, this should not occur, because the local pool isn't currently used for much (in particular, not for statements or declarations in the body of a function). We give an error in case this somehow might occur.

In combination with preceding commits, this fixes #14. Declaration specifiers can now appear in any order, as required by the C standards.
This commit is contained in:
Stephen Heumann 2020-01-17 20:29:57 -06:00
parent fbe44e1852
commit df029ce06f
2 changed files with 44 additions and 24 deletions

View File

@ -164,6 +164,7 @@ var
skipDeclarator: boolean; {for enum,struct,union with no declarator}
statementList: statementPtr; {list of open statements}
savedVolatile: boolean; {saved copy of volatile}
doingForLoopClause1: boolean; {doing the first clause of a for loop?}
{parameter processing variables}
{------------------------------}
@ -615,7 +616,9 @@ var
charsy,shortsy,floatsy,doublesy,compsy,extendedsy,enumsy,
structsy,unionsy,typedef,voidsy,volatilesy,constsy,
externsy,staticsy,typedefsy,_Static_assertsy]) then begin
DoDeclaration(false, true)
doingForLoopClause1 := true;
DoDeclaration(false, true);
doingForLoopClause1 := false;
end {if}
else if token.kind <> semicolonch then begin
Expression(normalExpression, [semicolonch]);
@ -2801,6 +2804,41 @@ typeSpecifiers := [];
typeDone := false;
while token.kind in allowedTokens do begin
case token.kind of
{storage class specifiers}
autosy,externsy,registersy,staticsy,typedefsy: begin
if storageClass <> ident then begin
if typeDone or (typeSpecifiers <> []) then
Error(9)
else
Error(26);
end; {if}
storageClass := token.kind;
if not doingFunction then
if token.kind = autosy then
Error(62);
if doingParameters then begin
if token.kind <> registersy then
Error(87);
end {if}
else if storageClass in [staticsy,typedefsy] then begin
{Error if we may have allocated type info in local pool.}
{This should not come up with current use of MM pools. }
if not useGlobalPool then
if typeDone then
Error(57);
useGlobalPool := true;
end; {else if}
if doingForLoopClause1 then
if not (storageClass in [autosy,registersy]) then
Error(127);
NextToken;
end;
_Thread_localsy: begin
Error(139);
NextToken;
end;
{function specifiers}
inlinesy,_Noreturnsy,asmsy,pascalsy: begin
myFunctionSpecifiers := myFunctionSpecifiers + [token.kind];
@ -3337,33 +3375,13 @@ if token.kind in [constsy,volatilesy] {handle leading constsy, volatile}
NextToken;
end; {while}
end; {if}
storageClass := ident; {handle a StorageClassSpecifier}
lUseGlobalPool := useGlobalPool;
if token.kind in [autosy,externsy,registersy,staticsy,typedefsy] then begin
typeFound := true;
storageClass := token.kind;
if not doingFunction then
if token.kind = autosy then
Error(62);
if doingParameters then begin
if token.kind <> registersy then
Error(87);
end {if}
else if storageClass in [staticsy,typedefsy] then
useGlobalPool := true;
if autoOrRegisterOnly then
if not (storageClass in [autosy,registersy]) then
Error(127);
NextToken;
end; {if}
storageClass := ident;
typeSpec := wordPtr; {default type specifier is an integer}
{handle a TypeSpecifier/declarator}
if token.kind in
specifierQualifierListElement+[inlinesy,_Noreturnsy,pascalsy,asmsy] then
begin
if token.kind in declarationSpecifiersElement then begin
typeFound := true;
DeclarationSpecifiers(foundConstsy,
specifierQualifierListElement+[inlinesy,_Noreturnsy,pascalsy,asmsy]);
DeclarationSpecifiers(foundConstsy, declarationSpecifiersElement);
isPascal := pascalsy in functionSpecifiers;
isAsm := asmsy in functionSpecifiers;
isInline := inlinesy in functionSpecifiers;
@ -4302,6 +4320,7 @@ lastLine := 0; {no pc_lnm generated yet}
nameFound := false; {no pc_nam generated yet}
statementList := nil; {no open statements}
codegenStarted := false; {code generator is not started}
doingForLoopClause1 := false; {not doing a for loop}
{init syntactic classes of tokens}
{See C17 section 6.7 ff.}

View File

@ -653,6 +653,7 @@ if list or (numErr <> 0) then begin
136: msg := @'complex or imaginary types are not supported by ORCA/C';
137: msg := @'atomic types are not supported by ORCA/C';
138: msg := @'unsupported alignment';
139: msg := @'thread-local storage is not supported by ORCA/C';
otherwise: Error(57);
end; {case}
writeln(msg^);