Prevent a tag declared in an inner scope from shadowing a typedef.

This could occur because when FindSymbol was called to look for symbols in all spaces, it would find a tag in an inner scope before a typedef in an outer scope. The processing order has been changed to look for regular symbols (including typedefs) in any scope, and only look for tags if no regular symbol is found.

Here is an example illustrating the problem:

typedef int T;
int main(void) {
        struct T;
        T x;
}
This commit is contained in:
Stephen Heumann 2023-03-06 21:38:05 -06:00
parent 645b210e7f
commit 3406dbd3ae
4 changed files with 13 additions and 24 deletions

View File

@ -2176,7 +2176,7 @@ begin {ExpressionTree}
opStack := nil;
stack := nil;
if token.kind = typedef then {handle typedefs that are hidden}
if FindSymbol(token,allSpaces,false,true) <> nil then
if FindSymbol(token,variableSpace,false,true) <> nil then
if token.symbolPtr^.class <> typedefsy then
token.kind := ident;
if token.kind in startExpression then begin

View File

@ -5316,12 +5316,6 @@ if tokenList <> nil then begin {get a token put back by a macro}
dispose(tPtr);
if token.kind = typedef then {allow for typedefs in a macro}
token.kind := ident;
{ dead code
if token.kind = ident then
if FindSymbol(token,allSpaces,false,false) <> nil then
if token.symbolPtr^.class = typedefsy then
token.kind := typedef;
}
4:
while (token.kind = stringconst)
and (tokenList <> nil)

View File

@ -1162,10 +1162,9 @@ function FindSymbol {var tk: tokenType; class: spaceType; oneLevel: boolean;
{ A pointer to the symbol table entry is returned. If }
{ there is no entry, nil is returned. }
label 1;
label 1,2;
var
doTagSpace: boolean; {do we still need to do the tags?}
hashDisp: longint; {disp into the hash table}
i: integer; {loop variable}
iHandle: ^identPtr; {pointer to start of hash bucket}
@ -1180,23 +1179,16 @@ begin {FindSymbol}
staticAllowed := staticAllowed and (staticNum <> '~0000');
name := tk.name; {use a local variable}
hashDisp := Hash(name); {get the disp into the symbol table}
sPtr := table; {initialize the address of the sym. tbl}
FindSymbol := nil; {assume we won't find it}
np := nil; {no string buffer, yet}
{check for the variable}
2:
sPtr := table; {initialize the address of the sym. tbl}
while sPtr <> nil do begin
iHandle := pointer(hashDisp+ord4(sPtr));
if class = tagSpace then
iHandle := pointer(ord4(iHandle) + (hashSize+1)*4);
doTagSpace := class = allSpaces;
iPtr := iHandle^;
if iPtr = nil then
if doTagSpace then begin
iHandle := pointer(ord4(iHandle) + (hashSize+1)*4);
iPtr := iHandle^;
doTagSpace := false;
end; {if}
{scan the hash bucket for a global or auto variable}
while iPtr <> nil do begin
@ -1208,12 +1200,6 @@ while sPtr <> nil do begin
goto 1;
end; {if}
iPtr := iPtr^.next;
if iPtr = nil then
if doTagSpace then begin
iHandle := pointer(ord4(iHandle) + (hashSize+1)*4);
iPtr := iHandle^;
doTagSpace := false;
end; {if}
end; {while}
{rescan for a static variable}
@ -1256,6 +1242,13 @@ while sPtr <> nil do begin
sPtr := sPtr^.next;
end; {while}
{we only get here if a symbol was not found}
if class = allSpaces then begin
class := tagSpace;
goto 2;
end; {if}
FindSymbol := nil;
1:
if np <> nil then
dispose(np);

View File

@ -2146,6 +2146,8 @@ int foo(int[42]);
237. If the same identifier was used for both a variable or function name and a struct/union/enum tag, it might not be possible to take the address of the variable or function within the initializer for a static variable.
238. If a typedef name declared in an outer scope was used within an inner scope where the same name was declared as a struct/union/enum tag, it would not be properly recognized as a typedef name, leading to spurious errors.
-- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file.