Record volatile and restrict qualifiers in types.

These are needed to correctly distinguish pointer types in _Generic. They should also be used for type compatibility checks in other contexts, but currently are not.

This also fixes a couple small problems related to type qualifiers:
*restrict was not allowed to appear after * in type-names
*volatile status was not properly recorded in sym files

Here is an example of using _Generic to distinguish pointer types based on the qualifiers of the pointed-to type:

#include <stdio.h>

#define f(e) _Generic((e),\
        int * restrict *: 1,\
        int * volatile const *: 2,\
        int **: 3,\
        default: 0)

#define g(e) _Generic((e),\
        int *: 1,\
        const int *: 2,\
        volatile int *: 3,\
        default: 0)

int main(void) {
        int * restrict * p1;
        int * volatile const * p2;
        int * const * p3;

        // should print "1 2 0 1"
        printf("%i %i %i %i\n", f(p1), f(p2), f(p3), f((int * restrict *)0));

        int *q1;
        const int *q2;
        volatile int *q3;
        const volatile int *q4;

        // should print "1 2 3 0"
        printf("%i %i %i %i\n", g(q1), g(q2), g(q3), g(q4));
}

Here is an example of a problem resulting from volatile not being recorded in sym files (if a sym file was present, the read of x was lifted out of the loop):

#pragma optimize -1
static volatile int x;
#include <stdio.h>
int main(void) {
        int y;
        for (unsigned i = 0; i < 100; i++) {
                y = x*2 + 7;
        }
}
This commit is contained in:
Stephen Heumann 2021-08-29 21:10:20 -05:00
parent 586e3f9146
commit b16210a50b
7 changed files with 105 additions and 73 deletions

View File

@ -274,11 +274,14 @@ type
parameterType: typePtr; parameterType: typePtr;
end; end;
typeQualifierEnum = (tqConst, tqVolatile, tqRestrict);
typeQualifierSet = set of typeQualifierEnum;
typeKind = (scalarType,arrayType,pointerType,functionType,enumType, typeKind = (scalarType,arrayType,pointerType,functionType,enumType,
enumConst,structType,unionType,definedType); enumConst,structType,unionType,definedType);
typeRecord = record {type} typeRecord = record {type}
size: longint; {size of the type in bytes} size: longint; {size of the type in bytes}
isConstant: boolean; {is the type a constant?} qualifiers: typeQualifierSet; {type qualifiers}
saveDisp: longint; {disp in symbol file} saveDisp: longint; {disp in symbol file}
case kind: typeKind of {NOTE: aType,pType and fType must overlap} case kind: typeKind of {NOTE: aType,pType and fType must overlap}
scalarType : (baseType: baseTypeEnum; {our internal type representation} scalarType : (baseType: baseTypeEnum; {our internal type representation}

View File

@ -575,7 +575,7 @@ var
begin {AssignmentConversion} begin {AssignmentConversion}
kind1 := t1^.kind; kind1 := t1^.kind;
kind2 := t2^.kind; kind2 := t2^.kind;
if t1^.isConstant then if tqConst in t1^.qualifiers then
if genCode then if genCode then
if checkConst then if checkConst then
Error(93); Error(93);
@ -947,7 +947,7 @@ var
fnPtr := pointer(GCalloc(sizeof(typeRecord))); fnPtr := pointer(GCalloc(sizeof(typeRecord)));
{fnPtr^.size := 0;} {fnPtr^.size := 0;}
{fnPtr^.saveDisp := 0;} {fnPtr^.saveDisp := 0;}
{fnPtr^.isConstant := false;} {fnPtr^.qualifiers := [];}
fnPtr^.kind := functionType; fnPtr^.kind := functionType;
fnPtr^.fType := intPtr; fnPtr^.fType := intPtr;
{fnPtr^.varargs := false;} {fnPtr^.varargs := false;}
@ -1888,14 +1888,14 @@ var
if expressionType^.kind = functionType then begin if expressionType^.kind = functionType then begin
controllingType.size := cgLongSize; controllingType.size := cgLongSize;
controllingType.saveDisp := 0; controllingType.saveDisp := 0;
controllingType.isConstant := false; controllingType.qualifiers := [];
controllingType.kind := pointerType; controllingType.kind := pointerType;
controllingType.pType := expressionType; controllingType.pType := expressionType;
end {if} end {if}
else if expressionType^.kind in [structType,unionType] then begin else if expressionType^.kind in [structType,unionType] then begin
controllingType.size := expressionType^.size; controllingType.size := expressionType^.size;
controllingType.saveDisp := 0; controllingType.saveDisp := 0;
controllingType.isConstant := false; controllingType.qualifiers := [];
controllingType.kind := definedType; controllingType.kind := definedType;
controllingType.dType := expressionType; controllingType.dType := expressionType;
end {else if} end {else if}
@ -1903,7 +1903,7 @@ var
controllingType := expressionType^; controllingType := expressionType^;
if controllingType.kind = arrayType then if controllingType.kind = arrayType then
controllingType.kind := pointerType; controllingType.kind := pointerType;
controllingType.isConstant := false; controllingType.qualifiers := [];
typesSeen := nil; typesSeen := nil;
resultExpr := nil; resultExpr := nil;
@ -2778,7 +2778,7 @@ var
eType := pointer(Malloc(sizeof(typeRecord))); eType := pointer(Malloc(sizeof(typeRecord)));
eType^.size := cgLongSize; eType^.size := cgLongSize;
eType^.saveDisp := 0; eType^.saveDisp := 0;
eType^.isConstant := false; eType^.qualifiers := [];
eType^.kind := pointerType; eType^.kind := pointerType;
eType^.pType := iType; eType^.pType := iType;
expressionType := eType; expressionType := eType;
@ -2813,7 +2813,7 @@ var
eType := pointer(Malloc(sizeof(typeRecord))); eType := pointer(Malloc(sizeof(typeRecord)));
eType^.size := cgLongSize; eType^.size := cgLongSize;
eType^.saveDisp := 0; eType^.saveDisp := 0;
eType^.isConstant := false; eType^.qualifiers := [];
eType^.kind := pointerType; eType^.kind := pointerType;
eType^.pType := expressionType; eType^.pType := expressionType;
expressionType := eType; expressionType := eType;
@ -2830,7 +2830,7 @@ var
eType := pointer(Malloc(sizeof(typeRecord))); eType := pointer(Malloc(sizeof(typeRecord)));
eType^.size := cgLongSize; eType^.size := cgLongSize;
eType^.saveDisp := 0; eType^.saveDisp := 0;
eType^.isConstant := false; eType^.qualifiers := [];
eType^.kind := pointerType; eType^.kind := pointerType;
eType^.pType := expressionType; eType^.pType := expressionType;
expressionType := eType; expressionType := eType;
@ -2943,7 +2943,7 @@ var
with tree^.id^ do begin with tree^.id^ do begin
{check for ++ or -- of a constant} {check for ++ or -- of a constant}
if iType^.isConstant then if tqConst in iType^.qualifiers then
Error(93); Error(93);
{do an efficient ++ or -- on a named location} {do an efficient ++ or -- on a named location}
@ -3560,6 +3560,8 @@ case tree^.token.kind of
GenerateCode(tree^.right); GenerateCode(tree^.right);
AssignmentConversion(lType, expressionType, lastWasConst, AssignmentConversion(lType, expressionType, lastWasConst,
lastConst, true, true); lastConst, true, true);
while lType^.kind = definedType do
lType := lType^.dType;
case lType^.kind of case lType^.kind of
scalarType: scalarType:
if lisBitField then if lisBitField then
@ -3623,7 +3625,7 @@ case tree^.token.kind of
else else
Gen1t(pc_ind, 0, lType^.baseType); Gen1t(pc_ind, 0, lType^.baseType);
end; {else} end; {else}
if lType^.isConstant then if tqConst in lType^.qualifiers then
Error(93); Error(93);
if doingScalar if doingScalar
and (ltype^.kind = arrayType) and (id^.storage = parameter) then and (ltype^.kind = arrayType) and (id^.storage = parameter) then
@ -4082,7 +4084,7 @@ case tree^.token.kind of
tType := pointer(Malloc(sizeof(typeRecord))); tType := pointer(Malloc(sizeof(typeRecord)));
tType^.size := cgLongSize; tType^.size := cgLongSize;
tType^.saveDisp := 0; tType^.saveDisp := 0;
tType^.isConstant := false; tType^.qualifiers := [];
tType^.kind := pointerType; tType^.kind := pointerType;
tType^.pType := expressionType^.aType; tType^.pType := expressionType^.aType;
expressionType := tType; expressionType := tType;
@ -4138,7 +4140,7 @@ case tree^.token.kind of
tType := pointer(Malloc(sizeof(typeRecord))); tType := pointer(Malloc(sizeof(typeRecord)));
tType^.size := cgLongSize; tType^.size := cgLongSize;
tType^.saveDisp := 0; tType^.saveDisp := 0;
tType^.isConstant := false; tType^.qualifiers := [];
tType^.kind := pointerType; tType^.kind := pointerType;
tType^.pType := expressionType^.aType; tType^.pType := expressionType^.aType;
expressionType := tType; expressionType := tType;

View File

@ -18,7 +18,7 @@ uses CCommon, MM, Scanner, Symbol, CGI;
{$segment 'SCANNER'} {$segment 'SCANNER'}
const const
symFileVersion = 14; {version number of .sym file format} symFileVersion = 15; {version number of .sym file format}
var var
inhibitHeader: boolean; {should .sym includes be blocked?} inhibitHeader: boolean; {should .sym includes be blocked?}
@ -1016,7 +1016,9 @@ procedure EndInclude {chPtr: ptr};
WriteByte(0); WriteByte(0);
tp^.saveDisp := GetMark; tp^.saveDisp := GetMark;
WriteLong(tp^.size); WriteLong(tp^.size);
WriteByte(ord(tp^.isConstant)); WriteByte(ord(tqConst in tp^.qualifiers)
| (ord(tqVolatile in tp^.qualifiers) << 1)
| (ord(tqRestrict in tp^.qualifiers) << 2));
WriteByte(ord(tp^.kind)); WriteByte(ord(tp^.kind));
case tp^.kind of case tp^.kind of
scalarType: begin scalarType: begin
@ -1636,7 +1638,17 @@ var
tdisp^.tPtr := tp; tdisp^.tPtr := tp;
tp^.size := ReadLong; tp^.size := ReadLong;
tp^.saveDisp := 0; tp^.saveDisp := 0;
tp^.isConstant := boolean(ReadByte); val := ReadByte;
if odd(val) then
tp^.qualifiers := [tqConst]
else
tp^.qualifiers := [];
if odd(val >> 1) then begin
tp^.qualifiers := tp^.qualifiers + [tqVolatile];
volatile := true;
end; {if}
if odd(val >> 2) then
tp^.qualifiers := tp^.qualifiers + [tqRestrict];
tp^.kind := typeKind(ReadByte); tp^.kind := typeKind(ReadByte);
case tp^.kind of case tp^.kind of
scalarType: begin scalarType: begin

View File

@ -1237,7 +1237,7 @@ type
pointerListPtr = ^pointerList; {for stacking pointer types} pointerListPtr = ^pointerList; {for stacking pointer types}
pointerList = record pointerList = record
next: pointerListPtr; next: pointerListPtr;
isConstant: boolean; qualifiers: typeQualifierSet;
end; end;
var var
@ -1315,7 +1315,7 @@ var
{tPtr2^.size := 0;} {tPtr2^.size := 0;}
{tPtr2^.saveDisp := 0;} {tPtr2^.saveDisp := 0;}
tPtr2^.kind := definedType; tPtr2^.kind := definedType;
{tPtr^.isConstant := false;} {tPtr^.qualifiers := [];}
tPtr2^.dType := tPtr; tPtr2^.dType := tPtr;
end {if} end {if}
else else
@ -1342,14 +1342,16 @@ var
new(cp); new(cp);
cp^.next := cpList; cp^.next := cpList;
cpList := cp; cpList := cp;
cp^.isConstant := false; cp^.qualifiers := [];
while token.kind in [_Alignassy..whilesy] do begin while token.kind in [_Alignassy..whilesy] do begin
if token.kind = constsy then if token.kind = constsy then
cpList^.isConstant := true cpList^.qualifiers := cpList^.qualifiers + [tqConst]
else if token.kind = volatilesy then else if token.kind = volatilesy then begin
cpList^.qualifiers := cpList^.qualifiers + [tqVolatile];
volatile := true volatile := true
else if token.kind = restrictsy then end {else if}
{always allowed for now (not recorded as part of the type)} else if token.kind = restrictsy then {always allowed for now}
cpList^.qualifiers := cpList^.qualifiers + [tqRestrict]
else else
Error(9); Error(9);
NextToken; NextToken;
@ -1403,7 +1405,7 @@ var
{tPtr2^.size := 0;} {tPtr2^.size := 0;}
{tPtr2^.saveDisp := 0;} {tPtr2^.saveDisp := 0;}
tPtr2^.kind := functionType; tPtr2^.kind := functionType;
{tPtr2^.isConstant := false;} {tPtr2^.qualifiers := [];}
{tPtr2^.varargs := false;} {tPtr2^.varargs := false;}
{tPtr2^.prototyped := false;} {tPtr2^.prototyped := false;}
{tPtr2^.overrideKR := false;} {tPtr2^.overrideKR := false;}
@ -1548,7 +1550,7 @@ var
tPtr2 := pointer(Calloc(sizeof(typeRecord))); tPtr2 := pointer(Calloc(sizeof(typeRecord)));
{tPtr2^.size := 0;} {tPtr2^.size := 0;}
{tPtr2^.saveDisp := 0;} {tPtr2^.saveDisp := 0;}
{tPtr2^.isConstant := false;} {tPtr2^.qualifiers := [];}
tPtr2^.kind := arrayType; tPtr2^.kind := arrayType;
{tPtr2^.elements := 0;} {tPtr2^.elements := 0;}
new(ttPtr); new(ttPtr);
@ -1573,7 +1575,7 @@ var
tPtr2 := pointer(Malloc(sizeof(typeRecord))); tPtr2 := pointer(Malloc(sizeof(typeRecord)));
tPtr2^.size := cgPointerSize; tPtr2^.size := cgPointerSize;
tPtr2^.saveDisp := 0; tPtr2^.saveDisp := 0;
tPtr2^.isConstant := cpList^.isConstant; tPtr2^.qualifiers := cpList^.qualifiers;
tPtr2^.kind := pointerType; tPtr2^.kind := pointerType;
new(ttPtr); new(ttPtr);
ttPtr^.next := typeStack; ttPtr^.next := typeStack;
@ -2689,7 +2691,7 @@ var
typeSpecifiers: tokenSet; {set of tokens specifying the type} typeSpecifiers: tokenSet; {set of tokens specifying the type}
typeDone: boolean; {no more type specifiers can be accepted} typeDone: boolean; {no more type specifiers can be accepted}
isConstant: boolean; {did we find a constsy?} typeQualifiers: typeQualifierSet; {set of type qualifiers found}
myIsForwardDeclared: boolean; {value of isForwardDeclared to generate} myIsForwardDeclared: boolean; {value of isForwardDeclared to generate}
mySkipDeclarator: boolean; {value of skipDeclarator to generate} mySkipDeclarator: boolean; {value of skipDeclarator to generate}
@ -2929,9 +2931,9 @@ myTypeSpec := nil;
myIsForwardDeclared := false; {not doing a forward reference (yet)} myIsForwardDeclared := false; {not doing a forward reference (yet)}
mySkipDeclarator := false; {declarations are required (so far)} mySkipDeclarator := false; {declarations are required (so far)}
myDeclarationModifiers := []; myDeclarationModifiers := [];
typeQualifiers := [];
typeSpecifiers := []; typeSpecifiers := [];
typeDone := false; typeDone := false;
isConstant := false;
isLongLong := false; isLongLong := false;
while token.kind in allowedTokens do begin while token.kind in allowedTokens do begin
case token.kind of case token.kind of
@ -2981,18 +2983,20 @@ while token.kind in allowedTokens do begin
{type qualifiers} {type qualifiers}
constsy: begin constsy: begin
myDeclarationModifiers := myDeclarationModifiers + [token.kind]; myDeclarationModifiers := myDeclarationModifiers + [token.kind];
isConstant := true; typeQualifiers := typeQualifiers + [tqConst];
NextToken; NextToken;
end; end;
volatilesy: begin volatilesy: begin
myDeclarationModifiers := myDeclarationModifiers + [token.kind]; myDeclarationModifiers := myDeclarationModifiers + [token.kind];
typeQualifiers := typeQualifiers + [tqVolatile];
volatile := true; volatile := true;
NextToken; NextToken;
end; end;
restrictsy: begin restrictsy: begin
myDeclarationModifiers := myDeclarationModifiers + [token.kind]; myDeclarationModifiers := myDeclarationModifiers + [token.kind];
typeQualifiers := typeQualifiers + [tqRestrict];
if typeDone or (typeSpecifiers <> []) then if typeDone or (typeSpecifiers <> []) then
if (myTypeSpec^.kind <> pointerType) if (myTypeSpec^.kind <> pointerType)
or (myTypeSpec^.pType^.kind = functionType) then or (myTypeSpec^.pType^.kind = functionType) then
@ -3063,7 +3067,7 @@ while token.kind in allowedTokens do begin
tPtr := pointer(Malloc(sizeof(typeRecord))); tPtr := pointer(Malloc(sizeof(typeRecord)));
tPtr^.size := cgWordSize; tPtr^.size := cgWordSize;
tPtr^.saveDisp := 0; tPtr^.saveDisp := 0;
tPtr^.isConstant := false; tPtr^.qualifiers := [];
tPtr^.kind := enumType; tPtr^.kind := enumType;
variable := variable :=
NewSymbol(ttoken.name, tPtr, storageClass, tagSpace, defined); NewSymbol(ttoken.name, tPtr, storageClass, tagSpace, defined);
@ -3077,7 +3081,7 @@ while token.kind in allowedTokens do begin
tPtr := pointer(Malloc(sizeof(typeRecord))); tPtr := pointer(Malloc(sizeof(typeRecord)));
tPtr^.size := cgWordSize; tPtr^.size := cgWordSize;
tPtr^.saveDisp := 0; tPtr^.saveDisp := 0;
tPtr^.isConstant := false; tPtr^.qualifiers := [];
tPtr^.kind := enumConst; tPtr^.kind := enumConst;
if token.kind = ident then begin if token.kind = ident then begin
variable := variable :=
@ -3157,7 +3161,7 @@ while token.kind in allowedTokens do begin
structTypePtr := pointer(Calloc(sizeof(typeRecord))); structTypePtr := pointer(Calloc(sizeof(typeRecord)));
{structTypePtr^.size := 0;} {structTypePtr^.size := 0;}
{structTypePtr^.saveDisp := 0;} {structTypePtr^.saveDisp := 0;}
{structTypePtr^.isConstant := false;} {structTypePtr^.qualifiers := [];}
structTypePtr^.kind := tkind; structTypePtr^.kind := tkind;
{structTypePtr^.fieldList := nil;} {structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;} {structTypePtr^.sName := nil;}
@ -3189,7 +3193,7 @@ while token.kind in allowedTokens do begin
structTypePtr := pointer(Calloc(sizeof(typeRecord))); structTypePtr := pointer(Calloc(sizeof(typeRecord)));
{structTypePtr^.size := 0;} {structTypePtr^.size := 0;}
{structTypePtr^.saveDisp := 0;} {structTypePtr^.saveDisp := 0;}
{structTypePtr^.isConstant := false;} {structTypePtr^.qualifiers := [];}
structTypePtr^.kind := tkind; structTypePtr^.kind := tkind;
{structTypePtr^.fieldList := nil;} {structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;} {structTypePtr^.sName := nil;}
@ -3260,7 +3264,7 @@ if typeSpec = nil then begin
if (lint & lintC99Syntax) <> 0 then if (lint & lintC99Syntax) <> 0 then
Error(151); Error(151);
end; {if} end; {if}
if isconstant then begin {handle a constant type} if typeQualifiers <> [] then begin {handle a qualified type}
new(tPtr); new(tPtr);
if typeSpec^.kind in [structType,unionType] then begin if typeSpec^.kind in [structType,unionType] then begin
with tPtr^ do begin with tPtr^ do begin
@ -3268,11 +3272,13 @@ if isconstant then begin {handle a constant type}
kind := definedType; kind := definedType;
dType := typeSpec; dType := typeSpec;
saveDisp := 0; saveDisp := 0;
qualifiers := typeQualifiers;
end; {with} end; {with}
end {if} end {if}
else else begin
tPtr^ := typeSpec^; tPtr^ := typeSpec^;
tPtr^.isConstant := true; tPtr^.qualifiers := tPtr^.qualifiers + typeQualifiers;
end; {else}
typeSpec := tPtr; typeSpec := tPtr;
end; {if} end; {if}
end; {DeclarationSpecifiers} end; {DeclarationSpecifiers}
@ -3969,7 +3975,7 @@ var
tp := pointer(Calloc(sizeof(typeRecord))); tp := pointer(Calloc(sizeof(typeRecord)));
{tp^.size := 0;} {tp^.size := 0;}
{tp^.saveDisp := 0;} {tp^.saveDisp := 0;}
{tp^.isConstant := false;} {tp^.qualifiers := [];}
tp^.kind := functionType; tp^.kind := functionType;
{tp^.varargs := false;} {tp^.varargs := false;}
{tp^.prototyped := false;} {tp^.prototyped := false;}
@ -4004,13 +4010,17 @@ var
tp := pointer(Malloc(sizeof(typeRecord))); tp := pointer(Malloc(sizeof(typeRecord)));
tp^.size := cgLongSize; tp^.size := cgLongSize;
tp^.saveDisp := 0; tp^.saveDisp := 0;
tp^.isConstant := false; tp^.qualifiers := [];
tp^.kind := pointerType; tp^.kind := pointerType;
while token.kind in [constsy,volatilesy] do begin while token.kind in [constsy,volatilesy,restrictsy] do begin
if token.kind = constsy then if token.kind = constsy then
tp^.isConstant := true tp^.qualifiers := tp^.qualifiers + [tqConst]
else {if token.kind = volatilesy then} else if token.kind = volatilesy then begin
tp^.qualifiers := tp^.qualifiers + [tqVolatile];
volatile := true; volatile := true;
end {else}
else {if token.kind = restrictsy then}
tp^.qualifiers := tp^.qualifiers + [tqRestrict];
NextToken; NextToken;
end; {while} end; {while}
AbstractDeclarator; AbstractDeclarator;
@ -4053,7 +4063,7 @@ var
tp := pointer(Calloc(sizeof(typeRecord))); tp := pointer(Calloc(sizeof(typeRecord)));
{tp^.size := 0;} {tp^.size := 0;}
{tp.saveDisp := 0;} {tp.saveDisp := 0;}
{tp^.isConstant := false;} {tp^.qualifiers := [];}
tp^.kind := functionType; tp^.kind := functionType;
{tp^.varargs := false;} {tp^.varargs := false;}
{tp^.prototyped := false;} {tp^.prototyped := false;}
@ -4493,7 +4503,7 @@ len := ord(functionName^[0]) + 1;
tp := pointer(GCalloc(sizeof(typeRecord))); tp := pointer(GCalloc(sizeof(typeRecord)));
tp^.size := len; tp^.size := len;
tp^.saveDisp := 0; tp^.saveDisp := 0;
tp^.isConstant := false; tp^.qualifiers := [];
tp^.kind := arrayType; tp^.kind := arrayType;
tp^.aType := constCharPtr; tp^.aType := constCharPtr;
tp^.elements := len; tp^.elements := len;

View File

@ -33,8 +33,12 @@ procedure PrintOneSymbol {ip: identPtr};
begin {PrintType} begin {PrintType}
with tp^ do begin with tp^ do begin
write(' ', size:1, ' byte '); write(' ', size:1, ' byte ');
if isConstant then if tqConst in qualifiers then
write('constant '); write('constant ');
if tqVolatile in qualifiers then
write('volatile ');
if tqRestrict in qualifiers then
write('restricted ');
case kind of case kind of
scalarType : writeln('scalar'); scalarType : writeln('scalar');
arrayType : begin arrayType : begin

View File

@ -474,9 +474,8 @@ if t1 = t2 then begin {shortcut}
goto 1; goto 1;
end; {if} end; {if}
StrictCompTypes := false; {assume the types are not compatible} StrictCompTypes := false; {assume the types are not compatible}
if t1^.isConstant <> t2^.isConstant then {qualifiers must be the same} if t1^.qualifiers <> t2^.qualifiers then {qualifiers must be the same}
goto 1; goto 1;
{TODO: Check other qualifiers (currently not recorded)}
while t1^.kind = definedType do {scan past type definitions} while t1^.kind = definedType do {scan past type definitions}
t1 := t1^.dType; t1 := t1^.dType;
while t2^.kind = definedType do while t2^.kind = definedType do
@ -521,13 +520,13 @@ case kind1 of
if p1^.parameterType = p2^.parameterType then if p1^.parameterType = p2^.parameterType then
{these parameters are compatible} {these parameters are compatible}
else begin else begin
tp1.isConstant := false; tp1.qualifiers := [];
tp2.isConstant := false; tp2.qualifiers := [];
if tp1.kind = arrayType then if tp1.kind = arrayType then
tp1.kind := pointerType tp1.kind := pointerType
else if tp1.kind = functionType then begin else if tp1.kind = functionType then begin
tp1.size := cgLongSize; tp1.size := cgLongSize;
tp1.isConstant := false; tp1.qualifiers := [];
tp1.saveDisp := 0; tp1.saveDisp := 0;
tp1.kind := pointerType; tp1.kind := pointerType;
tp1.pType := p1^.parameterType; tp1.pType := p1^.parameterType;
@ -536,7 +535,7 @@ case kind1 of
tp2.kind := pointerType tp2.kind := pointerType
else if tp2.kind = functionType then begin else if tp2.kind = functionType then begin
tp2.size := cgLongSize; tp2.size := cgLongSize;
tp2.isConstant := false; tp2.qualifiers := [];
tp2.saveDisp := 0; tp2.saveDisp := 0;
tp2.kind := pointerType; tp2.kind := pointerType;
tp2.pType := p2^.parameterType; tp2.pType := p2^.parameterType;
@ -1368,7 +1367,7 @@ new(sCharPtr); {signed char}
with sCharPtr^ do begin with sCharPtr^ do begin
size := cgByteSize; size := cgByteSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgByte; baseType := cgByte;
cType := ctSChar; cType := ctSChar;
@ -1377,7 +1376,7 @@ new(charPtr); {char}
with charPtr^ do begin with charPtr^ do begin
size := cgByteSize; size := cgByteSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgUByte; baseType := cgUByte;
cType := ctChar; cType := ctChar;
@ -1386,7 +1385,7 @@ new(uCharPtr); {unsigned char}
with uCharPtr^ do begin with uCharPtr^ do begin
size := cgByteSize; size := cgByteSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgUByte; baseType := cgUByte;
cType := ctUChar; cType := ctUChar;
@ -1395,7 +1394,7 @@ new(shortPtr); {short}
with shortPtr^ do begin with shortPtr^ do begin
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgWord; baseType := cgWord;
cType := ctShort; cType := ctShort;
@ -1404,7 +1403,7 @@ new(uShortPtr); {unsigned short}
with uShortPtr^ do begin with uShortPtr^ do begin
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgUWord; baseType := cgUWord;
cType := ctUShort; cType := ctUShort;
@ -1413,7 +1412,7 @@ new(intPtr); {int}
with intPtr^ do begin with intPtr^ do begin
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgWord; baseType := cgWord;
cType := ctInt; cType := ctInt;
@ -1422,7 +1421,7 @@ new(uIntPtr); {unsigned int}
with uIntPtr^ do begin with uIntPtr^ do begin
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgUWord; baseType := cgUWord;
cType := ctUInt; cType := ctUInt;
@ -1431,7 +1430,7 @@ new(int32Ptr); {int (32-bit)}
with int32Ptr^ do begin with int32Ptr^ do begin
size := cgLongSize; size := cgLongSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgLong; baseType := cgLong;
cType := ctInt32; cType := ctInt32;
@ -1440,7 +1439,7 @@ new(uInt32Ptr); {unsigned int (32-bit)}
with uInt32Ptr^ do begin with uInt32Ptr^ do begin
size := cgLongSize; size := cgLongSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgULong; baseType := cgULong;
cType := ctUInt32; cType := ctUInt32;
@ -1449,7 +1448,7 @@ new(longPtr); {long}
with longPtr^ do begin with longPtr^ do begin
size := cgLongSize; size := cgLongSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgLong; baseType := cgLong;
cType := ctLong; cType := ctLong;
@ -1458,7 +1457,7 @@ new(uLongPtr); {unsigned long}
with uLongPtr^ do begin with uLongPtr^ do begin
size := cgLongSize; size := cgLongSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgULong; baseType := cgULong;
cType := ctULong; cType := ctULong;
@ -1467,7 +1466,7 @@ new(longLongPtr); {long long}
with longLongPtr^ do begin with longLongPtr^ do begin
size := cgQuadSize; size := cgQuadSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgQuad; baseType := cgQuad;
cType := ctLongLong; cType := ctLongLong;
@ -1476,7 +1475,7 @@ new(uLongLongPtr); {unsigned long long}
with uLongLongPtr^ do begin with uLongLongPtr^ do begin
size := cgQuadSize; size := cgQuadSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgUQuad; baseType := cgUQuad;
cType := ctULongLong; cType := ctULongLong;
@ -1485,7 +1484,7 @@ new(floatPtr); {real}
with floatPtr^ do begin with floatPtr^ do begin
size := cgRealSize; size := cgRealSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgReal; baseType := cgReal;
cType := ctFloat; cType := ctFloat;
@ -1494,7 +1493,7 @@ new(doublePtr); {double}
with doublePtr^ do begin with doublePtr^ do begin
size := cgDoubleSize; size := cgDoubleSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgDouble; baseType := cgDouble;
cType := ctDouble; cType := ctDouble;
@ -1503,7 +1502,7 @@ new(compPtr); {comp}
with compPtr^ do begin with compPtr^ do begin
size := cgCompSize; size := cgCompSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgComp; baseType := cgComp;
cType := ctComp; cType := ctComp;
@ -1512,7 +1511,7 @@ new(extendedPtr); {extended, aka long double}
with extendedPtr^ do begin with extendedPtr^ do begin
size := cgExtendedSize; size := cgExtendedSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgExtended; baseType := cgExtended;
cType := ctLongDouble; cType := ctLongDouble;
@ -1521,7 +1520,7 @@ new(boolPtr); {_Bool}
with boolPtr^ do begin with boolPtr^ do begin
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgWord; baseType := cgWord;
cType := ctBool; cType := ctBool;
@ -1530,7 +1529,7 @@ new(stringTypePtr); {string constant type}
with stringTypePtr^ do begin with stringTypePtr^ do begin
size := 0; size := 0;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := arrayType; kind := arrayType;
aType := charPtr; aType := charPtr;
elements := 1; elements := 1;
@ -1539,7 +1538,7 @@ new(voidPtr); {void}
with voidPtr^ do begin with voidPtr^ do begin
size := 0; size := 0;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := scalarType; kind := scalarType;
baseType := cgVoid; baseType := cgVoid;
cType := ctVoid; cType := ctVoid;
@ -1548,7 +1547,7 @@ new(voidPtrPtr); {typeless pointer}
with voidPtrPtr^ do begin with voidPtrPtr^ do begin
size := 4; size := 4;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := pointerType; kind := pointerType;
pType := voidPtr; pType := voidPtr;
end; {with} end; {with}
@ -1556,7 +1555,7 @@ new(defaultStruct); {default structure}
with defaultStruct^ do begin {(for structures with errors)} with defaultStruct^ do begin {(for structures with errors)}
size := cgWordSize; size := cgWordSize;
saveDisp := 0; saveDisp := 0;
isConstant := false; qualifiers := [];
kind := structType; kind := structType;
sName := nil; sName := nil;
new(fieldList); new(fieldList);
@ -1572,7 +1571,7 @@ with defaultStruct^ do begin {(for structures with errors)}
end; {with} end; {with}
new(constCharPtr); {const char} new(constCharPtr); {const char}
constCharPtr^ := charPtr^; constCharPtr^ := charPtr^;
constCharPtr^.isConstant := true; constCharPtr^.qualifiers := [tqConst];
end; {InitSymbol} end; {InitSymbol}

View File

@ -1204,6 +1204,8 @@ int foo(int[42]);
159. The CLOCKS_PER_SEC and CLK_TCK macros were hard-coded as 60, but they should actually be 50 if the system is in 50Hz video mode. This could throw off timing code that used these macros in conjunction with clock(). The macros now expand to code that will detect the video mode and give the appropriate value. 159. The CLOCKS_PER_SEC and CLK_TCK macros were hard-coded as 60, but they should actually be 50 if the system is in 50Hz video mode. This could throw off timing code that used these macros in conjunction with clock(). The macros now expand to code that will detect the video mode and give the appropriate value.
160. The volatile type qualifier was omitted from declarations recorded in a .sym file. This could lead to volatile accesses being optimized away.
-- Bugs from C 2.1.0 that have been fixed ----------------------------------- -- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file. 1. In some situations, fread() reread the first 1K or so of the file.