From 3406dbd3ae8badb0d64d81204f2862a507c2c96c Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 6 Mar 2023 21:38:05 -0600 Subject: [PATCH] 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; } --- Expression.pas | 2 +- Scanner.pas | 6 ------ Symbol.pas | 27 ++++++++++----------------- cc.notes | 2 ++ 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/Expression.pas b/Expression.pas index 058ca51..8240db4 100644 --- a/Expression.pas +++ b/Expression.pas @@ -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 diff --git a/Scanner.pas b/Scanner.pas index b1b1141..754310e 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -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) diff --git a/Symbol.pas b/Symbol.pas index 8a506f1..4563392 100644 --- a/Symbol.pas +++ b/Symbol.pas @@ -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); diff --git a/cc.notes b/cc.notes index 723e840..d3bb7d7 100644 --- a/cc.notes +++ b/cc.notes @@ -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.