Disallowed arrays of incomplete types.
Fixed diagnostics on incomplete local arrays.
This commit is contained in:
@@ -140,19 +140,10 @@ static void Parse (void)
|
|||||||
comma = 0;
|
comma = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
Declaration Decl;
|
Declaration Decl;
|
||||||
|
|
||||||
/* Read the next declaration */
|
/* Read the next declaration */
|
||||||
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
||||||
if (Decl.Ident[0] == '\0') {
|
|
||||||
NextToken ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Decl.StorageClass & SC_FICTITIOUS) == SC_FICTITIOUS) {
|
|
||||||
/* Failed parsing */
|
|
||||||
goto SkipOneDecl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we must reserve storage for the variable. We do this,
|
/* Check if we must reserve storage for the variable. We do this,
|
||||||
**
|
**
|
||||||
@@ -163,8 +154,9 @@ static void Parse (void)
|
|||||||
**
|
**
|
||||||
** This means that "extern int i;" will not get storage allocated.
|
** This means that "extern int i;" will not get storage allocated.
|
||||||
*/
|
*/
|
||||||
if ((Decl.StorageClass & SC_FUNC) != SC_FUNC &&
|
if ((Decl.StorageClass & SC_FUNC) != SC_FUNC &&
|
||||||
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF &&
|
||||||
|
(Decl.StorageClass & SC_FICTITIOUS) != SC_FICTITIOUS) {
|
||||||
if ((Spec.Flags & DS_DEF_STORAGE) != 0 ||
|
if ((Spec.Flags & DS_DEF_STORAGE) != 0 ||
|
||||||
(Decl.StorageClass & (SC_EXTERN|SC_STATIC)) == SC_STATIC ||
|
(Decl.StorageClass & (SC_EXTERN|SC_STATIC)) == SC_STATIC ||
|
||||||
((Decl.StorageClass & SC_EXTERN) != 0 &&
|
((Decl.StorageClass & SC_EXTERN) != 0 &&
|
||||||
@@ -296,7 +288,6 @@ static void Parse (void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipOneDecl:
|
|
||||||
/* Check for end of declaration list */
|
/* Check for end of declaration list */
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -452,10 +443,6 @@ void Compile (const char* FileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sym = GetSymType (GetElementType (Entry->Type));
|
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 */
|
/* For non-ESU types, Size != 0 */
|
||||||
|
|||||||
@@ -457,6 +457,37 @@ static unsigned ParseOneStorageClass (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void CheckArrayElementType (Type* DataType)
|
||||||
|
/* Check if data type consists of arrays of incomplete element types */
|
||||||
|
{
|
||||||
|
Type* T = DataType;
|
||||||
|
|
||||||
|
while (T->C != T_END) {
|
||||||
|
if (IsTypeArray (T)) {
|
||||||
|
++T;
|
||||||
|
if (IsIncompleteESUType (T)) {
|
||||||
|
/* We cannot have an array of incomplete elements */
|
||||||
|
Error ("Array of incomplete element type '%s'", GetFullTypeName (T));
|
||||||
|
} else if (SizeOf (T) == 0) {
|
||||||
|
/* If the array is multi-dimensional, try to get the true
|
||||||
|
** element type.
|
||||||
|
*/
|
||||||
|
if (IsTypeArray (T)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* We could support certain 0-size element types as an extension */
|
||||||
|
if (!IsTypeVoid (T) || IS_Get (&Standard) != STD_CC65) {
|
||||||
|
Error ("Array of 0-size element type '%s'", GetFullTypeName (T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
|
static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
|
||||||
/* Parse a storage class */
|
/* Parse a storage class */
|
||||||
{
|
{
|
||||||
@@ -956,16 +987,16 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
|
|||||||
FieldTab = GetSymTab ();
|
FieldTab = GetSymTab ();
|
||||||
LeaveStructLevel ();
|
LeaveStructLevel ();
|
||||||
|
|
||||||
/* Empty union is not supported now */
|
|
||||||
if (UnionSize == 0) {
|
|
||||||
Error ("Empty union type '%s' is not supported", Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a fictitious symbol if errors occurred during parsing */
|
/* Return a fictitious symbol if errors occurred during parsing */
|
||||||
if (PrevErrorCount != ErrorCount) {
|
if (PrevErrorCount != ErrorCount) {
|
||||||
Flags |= SC_FICTITIOUS;
|
Flags |= SC_FICTITIOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Empty union is not supported now */
|
||||||
|
if (UnionSize == 0) {
|
||||||
|
Error ("Empty union type '%s' is not supported", Name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make a real entry from the forward decl and return it */
|
/* Make a real entry from the forward decl and return it */
|
||||||
return AddStructSym (Name, SC_UNION | SC_DEF | Flags, UnionSize, FieldTab);
|
return AddStructSym (Name, SC_UNION | SC_DEF | Flags, UnionSize, FieldTab);
|
||||||
}
|
}
|
||||||
@@ -1160,16 +1191,16 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
|
|||||||
FieldTab = GetSymTab ();
|
FieldTab = GetSymTab ();
|
||||||
LeaveStructLevel ();
|
LeaveStructLevel ();
|
||||||
|
|
||||||
/* Empty struct is not supported now */
|
|
||||||
if (StructSize == 0) {
|
|
||||||
Error ("Empty struct type '%s' is not supported", Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a fictitious symbol if errors occurred during parsing */
|
/* Return a fictitious symbol if errors occurred during parsing */
|
||||||
if (PrevErrorCount != ErrorCount) {
|
if (PrevErrorCount != ErrorCount) {
|
||||||
Flags |= SC_FICTITIOUS;
|
Flags |= SC_FICTITIOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Empty struct is not supported now */
|
||||||
|
if (StructSize == 0) {
|
||||||
|
Error ("Empty struct type '%s' is not supported", Name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make a real entry from the forward decl and return it */
|
/* Make a real entry from the forward decl and return it */
|
||||||
return AddStructSym (Name, SC_STRUCT | SC_DEF | Flags, StructSize, FieldTab);
|
return AddStructSym (Name, SC_STRUCT | SC_DEF | Flags, StructSize, FieldTab);
|
||||||
}
|
}
|
||||||
@@ -1922,6 +1953,9 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
|||||||
/* Do several fixes on qualifiers */
|
/* Do several fixes on qualifiers */
|
||||||
FixQualifiers (D->Type);
|
FixQualifiers (D->Type);
|
||||||
|
|
||||||
|
/* Check if the data type consists of any arrays of forbidden types */
|
||||||
|
CheckArrayElementType (D->Type);
|
||||||
|
|
||||||
/* If we have a function, add a special storage class */
|
/* If we have a function, add a special storage class */
|
||||||
if (IsTypeFunc (D->Type)) {
|
if (IsTypeFunc (D->Type)) {
|
||||||
D->StorageClass |= SC_FUNC;
|
D->StorageClass |= SC_FUNC;
|
||||||
@@ -1993,10 +2027,15 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
|||||||
Error ("Invalid size in declaration (0x%06X)", Size);
|
Error ("Invalid size in declaration (0x%06X)", Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PrevErrorCount != ErrorCount) {
|
if (PrevErrorCount != ErrorCount) {
|
||||||
/* Don't give storage if the declaration is not parsed correctly */
|
/* Make the declaration fictitious if is is not parsed correctly */
|
||||||
D->StorageClass |= SC_DECL | SC_FICTITIOUS;
|
D->StorageClass |= SC_DECL | SC_FICTITIOUS;
|
||||||
|
|
||||||
|
if (Mode == DM_NEED_IDENT && D->Ident[0] == '\0') {
|
||||||
|
/* Use a fictitious name for the identifier if it is missing */
|
||||||
|
AnonName (D->Ident, "global");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2242,7 +2281,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
|
|
||||||
/* Get the array data */
|
/* Get the array data */
|
||||||
Type* ElementType = GetElementType (T);
|
Type* ElementType = GetElementType (T);
|
||||||
unsigned ElementSize = CheckedSizeOf (ElementType);
|
unsigned ElementSize = SizeOf (ElementType);
|
||||||
long ElementCount = GetElementCount (T);
|
long ElementCount = GetElementCount (T);
|
||||||
|
|
||||||
/* Special handling for a character array initialized by a literal */
|
/* Special handling for a character array initialized by a literal */
|
||||||
|
|||||||
@@ -172,7 +172,11 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg)
|
|||||||
|
|
||||||
/* Cannot allocate a variable of zero size */
|
/* Cannot allocate a variable of zero size */
|
||||||
if (Size == 0) {
|
if (Size == 0) {
|
||||||
Error ("Variable '%s' has unknown size", Decl->Ident);
|
if (IsTypeArray (Decl->Type)) {
|
||||||
|
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||||
|
} else {
|
||||||
|
Error ("Variable '%s' has unknown size", Decl->Ident);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +361,11 @@ static void ParseAutoDecl (Declaration* Decl)
|
|||||||
|
|
||||||
/* Cannot allocate a variable of zero size */
|
/* Cannot allocate a variable of zero size */
|
||||||
if (Size == 0) {
|
if (Size == 0) {
|
||||||
Error ("Variable '%s' has unknown size", Decl->Ident);
|
if (IsTypeArray (Decl->Type)) {
|
||||||
|
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||||
|
} else {
|
||||||
|
Error ("Variable '%s' has unknown size", Decl->Ident);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +419,11 @@ static void ParseStaticDecl (Declaration* Decl)
|
|||||||
|
|
||||||
/* Cannot allocate a variable of zero size */
|
/* Cannot allocate a variable of zero size */
|
||||||
if (Size == 0) {
|
if (Size == 0) {
|
||||||
Error ("Variable '%s' has unknown size", Decl->Ident);
|
if (IsTypeArray (Decl->Type)) {
|
||||||
|
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||||
|
} else {
|
||||||
|
Error ("Variable '%s' has unknown size", Decl->Ident);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user