1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00

Fixed tentative definition of variables of incomplete types that may be completed later.

Tenative arrays that never get completed are now assumed each to have one element.
This commit is contained in:
acqn 2020-08-03 01:36:19 +08:00 committed by Oliver Schmidt
parent fdd120db49
commit fdef067629
2 changed files with 54 additions and 17 deletions

View File

@ -248,16 +248,11 @@ static void Parse (void)
/* We cannot declare variables of type void */
Error ("Illegal type for variable '%s'", Decl.Ident);
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
} else if (Size == 0) {
} else if (Size == 0 && SymIsDef (Entry)) {
/* Size is unknown. Is it an array? */
if (!IsTypeArray (Decl.Type)) {
Error ("Variable '%s' has unknown size", Decl.Ident);
}
/* Do this only if the same array has not been defined */
if (!SymIsDef (Entry)) {
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
Entry->Flags |= SC_DECL;
}
} else {
/* A global (including static) uninitialized variable is
** only a tentative definition. For example, this is valid:
@ -432,17 +427,42 @@ void Compile (const char* FileName)
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
/* Assembly definition of uninitialized global variable */
SymEntry* Sym = GetSymType (Entry->Type);
unsigned Size = SizeOf (Entry->Type);
if (Size == 0 && IsTypeArray (Entry->Type)) {
if (GetElementCount (Entry->Type) == UNSPECIFIED) {
/* Assume array size of 1 */
SetElementCount (Entry->Type, 1);
Size = SizeOf (Entry->Type);
Warning ("Tentative array '%s[]' assumed to have one element", Entry->Name);
}
/* Set the segment name only when it changes */
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
SetSegName (SEG_BSS, Entry->V.BssName);
g_segname (SEG_BSS);
Sym = GetSymType (GetElementType (Entry->Type));
if (Size == 0 && Sym != 0 && SymIsDef (Sym)) {
/* Array of 0-size elements */
Warning ("Array '%s[]' has 0-sized elements", Entry->Name);
}
}
/* For non-ESU types, Size != 0 */
if (Size != 0 || (Sym != 0 && SymIsDef (Sym))) {
/* Set the segment name only when it changes */
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
SetSegName (SEG_BSS, Entry->V.BssName);
g_segname (SEG_BSS);
}
g_usebss ();
g_defgloblabel (Entry->Name);
g_res (Size);
/* Mark as defined; so that it will be exported, not imported */
Entry->Flags |= SC_DEF;
} else {
/* Tentative declared variable is still of incomplete type */
Error ("Tentative definition of '%s' of type '%s' is incomplete",
Entry->Name,
GetFullTypeName (Entry->Type));
}
g_usebss ();
g_defgloblabel (Entry->Name);
g_res (SizeOf (Entry->Type));
/* Mark as defined; so that it will be exported, not imported */
Entry->Flags |= SC_DEF;
}
}
}

View File

@ -244,6 +244,23 @@ static int TypeSpecAhead (void)
static unsigned ExprCheckedSizeOf (const Type* T)
/* Specially checked SizeOf() used in 'sizeof' expressions */
{
unsigned Size = SizeOf (T);
SymEntry* Sym;
if (Size == 0) {
Sym = GetSymType (T);
if (Sym == 0 || !SymIsDef (Sym)) {
Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T));
}
}
return Size;
}
void PushAddr (const ExprDesc* Expr)
/* If the expression contains an address that was somehow evaluated,
** push this address on the stack. This is a helper function for all
@ -1890,7 +1907,7 @@ void hie10 (ExprDesc* Expr)
if (TypeSpecAhead ()) {
Type T[MAXTYPELEN];
NextToken ();
Size = CheckedSizeOf (ParseType (T));
Size = ExprCheckedSizeOf (ParseType (T));
ConsumeRParen ();
} else {
/* Remember the output queue pointer */
@ -1908,7 +1925,7 @@ void hie10 (ExprDesc* Expr)
ReleaseLiteral (Expr->LVal);
}
/* Calculate the size */
Size = CheckedSizeOf (Expr->Type);
Size = ExprCheckedSizeOf (Expr->Type);
}
/* Remove any generated code */
RemoveCode (&Mark);