mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 19:29:37 +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:
parent
fdd120db49
commit
fdef067629
@ -248,16 +248,11 @@ static void Parse (void)
|
|||||||
/* We cannot declare variables of type void */
|
/* We cannot declare variables of type void */
|
||||||
Error ("Illegal type for variable '%s'", Decl.Ident);
|
Error ("Illegal type for variable '%s'", Decl.Ident);
|
||||||
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
||||||
} else if (Size == 0) {
|
} else if (Size == 0 && SymIsDef (Entry)) {
|
||||||
/* Size is unknown. Is it an array? */
|
/* Size is unknown. Is it an array? */
|
||||||
if (!IsTypeArray (Decl.Type)) {
|
if (!IsTypeArray (Decl.Type)) {
|
||||||
Error ("Variable '%s' has unknown size", Decl.Ident);
|
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 {
|
} else {
|
||||||
/* A global (including static) uninitialized variable is
|
/* A global (including static) uninitialized variable is
|
||||||
** only a tentative definition. For example, this is valid:
|
** 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) {
|
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
|
||||||
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
||||||
/* Assembly definition of uninitialized global variable */
|
/* 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 */
|
Sym = GetSymType (GetElementType (Entry->Type));
|
||||||
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
|
if (Size == 0 && Sym != 0 && SymIsDef (Sym)) {
|
||||||
SetSegName (SEG_BSS, Entry->V.BssName);
|
/* Array of 0-size elements */
|
||||||
g_segname (SEG_BSS);
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
void PushAddr (const ExprDesc* Expr)
|
||||||
/* If the expression contains an address that was somehow evaluated,
|
/* If the expression contains an address that was somehow evaluated,
|
||||||
** push this address on the stack. This is a helper function for all
|
** push this address on the stack. This is a helper function for all
|
||||||
@ -1890,7 +1907,7 @@ void hie10 (ExprDesc* Expr)
|
|||||||
if (TypeSpecAhead ()) {
|
if (TypeSpecAhead ()) {
|
||||||
Type T[MAXTYPELEN];
|
Type T[MAXTYPELEN];
|
||||||
NextToken ();
|
NextToken ();
|
||||||
Size = CheckedSizeOf (ParseType (T));
|
Size = ExprCheckedSizeOf (ParseType (T));
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
} else {
|
} else {
|
||||||
/* Remember the output queue pointer */
|
/* Remember the output queue pointer */
|
||||||
@ -1908,7 +1925,7 @@ void hie10 (ExprDesc* Expr)
|
|||||||
ReleaseLiteral (Expr->LVal);
|
ReleaseLiteral (Expr->LVal);
|
||||||
}
|
}
|
||||||
/* Calculate the size */
|
/* Calculate the size */
|
||||||
Size = CheckedSizeOf (Expr->Type);
|
Size = ExprCheckedSizeOf (Expr->Type);
|
||||||
}
|
}
|
||||||
/* Remove any generated code */
|
/* Remove any generated code */
|
||||||
RemoveCode (&Mark);
|
RemoveCode (&Mark);
|
||||||
|
Loading…
Reference in New Issue
Block a user