From 03fc7a43b9daf2c8581f63af00435297b2cb2dd3 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 9 Jan 2023 21:58:05 -0600 Subject: [PATCH] Give an error for expressions with incomplete struct/union types. These are erroneous, in situations where the expression is used for its value. For function return types, this violates a constraint (C17 6.5.2.2 p1), so a diagnostic is required. We also now diagnose this issue for identifier expressions or unary * (indirection) expressions. These cases cause undefined behavior per C17 6.3.2.1 p2, so a diagnostic is not required, but it is nice to give one. --- Expression.pas | 23 ++++++++++++++++++++++- Scanner.pas | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Expression.pas b/Expression.pas index 9618172..0bc28ac 100644 --- a/Expression.pas +++ b/Expression.pas @@ -2887,6 +2887,23 @@ var ldoDispose: boolean; {local copy of doDispose} + procedure CheckForIncompleteStructType; + + { Check if expressionType is an incomplete struct/union type. } + + var + tp: typePtr; {the type} + + begin + tp := expressionType; + while tp^.kind = definedType do + tp := tp^.dType; + if tp^.kind in [structType,unionType] then + if tp^.size = 0 then + Error(187); + end; + + function ExpressionKind (tree: tokenPtr): typeKind; { returns the type of an expression } @@ -3516,6 +3533,7 @@ var ftype^.dispatcher); expressionType := ftype^.fType; lastWasConst := false; + CheckForIncompleteStructType; end; {else} end; {FunctionCall} @@ -3676,6 +3694,7 @@ case tree^.token.kind of LoadAddress(tree); if expressionType^.kind = pointerType then expressionType := expressionType^.ptype; + CheckForIncompleteStructType; end; enumConst: begin @@ -4645,7 +4664,9 @@ case tree^.token.kind of ((lType^.kind in [functionType,arrayType,structType,unionType]) or ((lType^.kind = definedType) and {handle const struct/union} (lType^.dType^.kind in [structType,unionType]))) then - Error(79); + Error(79) + else + CheckForIncompleteStructType; end {if} else Error(79); diff --git a/Scanner.pas b/Scanner.pas index d854710..b08cb09 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -802,6 +802,7 @@ if list or (numErr <> 0) then begin 184: msg := @'segment exceeds bank size'; 185: msg := @'lint: unused variable: '; 186: msg := @'lint: implicit conversion changes value of constant'; + 187: msg := @'expression has incomplete struct or union type'; end; {case} if extraStr <> nil then begin extraStr^ := concat(msg^,extraStr^);