mirror of
https://github.com/cc65/cc65.git
synced 2025-01-12 17:30:50 +00:00
Fixed several problems with old style (K&R) declarations and a mix of old and
new style decls. git-svn-id: svn://svn.cc65.org/cc65/trunk@3869 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
3482a9e7ce
commit
a1d7fed128
@ -149,6 +149,21 @@ static void Parse (void)
|
|||||||
Decl.StorageClass |= SC_STORAGE | SC_DEF;
|
Decl.StorageClass |= SC_STORAGE | SC_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If this is a function declarator that is not followed by a comma
|
||||||
|
* or semicolon, it must be followed by a function body. If this is
|
||||||
|
* the case, convert an empty parameter list into one accepting no
|
||||||
|
* parameters (same as void) as required by the standard.
|
||||||
|
*/
|
||||||
|
if ((Decl.StorageClass & SC_FUNC) != 0 &&
|
||||||
|
(CurTok.Tok != TOK_COMMA) &&
|
||||||
|
(CurTok.Tok != TOK_SEMI)) {
|
||||||
|
|
||||||
|
FuncDesc* D = GetFuncDesc (Decl.Type);
|
||||||
|
if (D->Flags & FD_EMPTY) {
|
||||||
|
D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add an entry to the symbol table */
|
/* Add an entry to the symbol table */
|
||||||
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
||||||
|
|
||||||
@ -240,25 +255,12 @@ static void Parse (void)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
FuncDesc* D;
|
|
||||||
|
|
||||||
/* Function body. Check for duplicate function definitions */
|
/* Function body. Check for duplicate function definitions */
|
||||||
if (SymIsDef (Entry)) {
|
if (SymIsDef (Entry)) {
|
||||||
Error ("Body for function `%s' has already been defined",
|
Error ("Body for function `%s' has already been defined",
|
||||||
Entry->Name);
|
Entry->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An empty parameter list in a function definition means
|
|
||||||
* that the function doesn't take any parameters. The same
|
|
||||||
* in a declarator means that the function can take any
|
|
||||||
* number of parameters. This seems weird but is necessary
|
|
||||||
* to support old K&R style programs.
|
|
||||||
*/
|
|
||||||
D = Entry->V.F.Func;
|
|
||||||
if (D->Flags & FD_EMPTY) {
|
|
||||||
D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse the function body */
|
/* Parse the function body */
|
||||||
NewFunc (Entry);
|
NewFunc (Entry);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ Type* GetImplicitFuncType (void)
|
|||||||
Type* T = TypeAlloc (3); /* func/returns int/terminator */
|
Type* T = TypeAlloc (3); /* func/returns int/terminator */
|
||||||
|
|
||||||
/* Prepare the function descriptor */
|
/* Prepare the function descriptor */
|
||||||
F->Flags = FD_IMPLICIT | FD_EMPTY | FD_VARIADIC;
|
F->Flags = FD_EMPTY | FD_VARIADIC;
|
||||||
F->SymTab = &EmptySymTab;
|
F->SymTab = &EmptySymTab;
|
||||||
F->TagTab = &EmptySymTab;
|
F->TagTab = &EmptySymTab;
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2003 Ullrich von Bassewitz */
|
/* (C) 2000-2008 Ullrich von Bassewitz */
|
||||||
/* Römerstraße 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -46,10 +46,9 @@
|
|||||||
|
|
||||||
/* Masks for the Flags field in FuncDesc */
|
/* Masks for the Flags field in FuncDesc */
|
||||||
#define FD_NONE 0x0000U /* No flags */
|
#define FD_NONE 0x0000U /* No flags */
|
||||||
#define FD_IMPLICIT 0x0001U /* Implicitly declared function */
|
#define FD_EMPTY 0x0001U /* Function with empty param list */
|
||||||
#define FD_EMPTY 0x0002U /* Function with empty param list */
|
#define FD_VOID_PARAM 0x0002U /* Function with a void param list */
|
||||||
#define FD_VOID_PARAM 0x0004U /* Function with a void param list */
|
#define FD_VARIADIC 0x0004U /* Function with variable param list */
|
||||||
#define FD_VARIADIC 0x0008U /* Function with variable param list */
|
|
||||||
#define FD_FASTCALL 0x0010U /* __fastcall__ function */
|
#define FD_FASTCALL 0x0010U /* __fastcall__ function */
|
||||||
#define FD_FAR 0x0020U /* __far__ function */
|
#define FD_FAR 0x0020U /* __far__ function */
|
||||||
#define FD_NEAR 0x0040U /* __near__ function */
|
#define FD_NEAR 0x0040U /* __near__ function */
|
||||||
@ -58,7 +57,7 @@
|
|||||||
#define FD_UNNAMED_PARAMS 0x0400U /* Function has unnamed params */
|
#define FD_UNNAMED_PARAMS 0x0400U /* Function has unnamed params */
|
||||||
|
|
||||||
/* Bits that must be ignored when comparing funcs */
|
/* Bits that must be ignored when comparing funcs */
|
||||||
#define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS)
|
#define FD_IGNORE (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -753,16 +753,22 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||||||
|
|
||||||
/* In case of a function, use the new type descriptor, since it
|
/* In case of a function, use the new type descriptor, since it
|
||||||
* contains pointers to the new symbol tables that are needed if
|
* contains pointers to the new symbol tables that are needed if
|
||||||
* an actual function definition follows.
|
* an actual function definition follows. Be sure not to use the
|
||||||
|
* new descriptor if it contains a function declaration with an
|
||||||
|
* empty parameter list.
|
||||||
*/
|
*/
|
||||||
if (IsFunc) {
|
if (IsFunc) {
|
||||||
/* Get the function descriptor from the new type */
|
/* Get the function descriptor from the new type */
|
||||||
FuncDesc* F = GetFuncDesc (T);
|
FuncDesc* F = GetFuncDesc (T);
|
||||||
/* Use this new function descriptor */
|
/* Use this new function descriptor if it doesn't contain
|
||||||
|
* an empty parameter list.
|
||||||
|
*/
|
||||||
|
if ((F->Flags & FD_EMPTY) == 0) {
|
||||||
Entry->V.F.Func = F;
|
Entry->V.F.Func = F;
|
||||||
SetFuncDesc (EType, F);
|
SetFuncDesc (EType, F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the new flags */
|
/* Add the new flags */
|
||||||
Entry->Flags |= Flags;
|
Entry->Flags |= Flags;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||||
/* Römerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -58,20 +58,76 @@ static void SetResult (typecmp_t* Result, typecmp_t Val)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int EqualFuncParams (SymTable* Tab1, SymTable* Tab2)
|
static int ParamsHaveDefaultPromotions (const FuncDesc* F)
|
||||||
|
/* Check if any of the parameters of function F has a default promotion. In
|
||||||
|
* this case, the function is not compatible with an empty parameter name list
|
||||||
|
* declaration.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Get the symbol table */
|
||||||
|
const SymTable* Tab = F->SymTab;
|
||||||
|
|
||||||
|
/* Get the first parameter in the list */
|
||||||
|
const SymEntry* Sym = Tab->SymHead;
|
||||||
|
|
||||||
|
/* Walk over all parameters */
|
||||||
|
while (Sym && (Sym->Flags & SC_PARAM)) {
|
||||||
|
|
||||||
|
/* If this is an integer type, check if the promoted type is equal
|
||||||
|
* to the original type. If not, we have a default promotion.
|
||||||
|
*/
|
||||||
|
if (IsClassInt (Sym->Type)) {
|
||||||
|
if (IntPromotion (Sym->Type) != Sym->Type) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the pointer to the next param */
|
||||||
|
Sym = Sym->NextSym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No default promotions in the parameter list */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2)
|
||||||
/* Compare two function symbol tables regarding function parameters. Return 1
|
/* Compare two function symbol tables regarding function parameters. Return 1
|
||||||
* if they are equal and 0 otherwise.
|
* if they are equal and 0 otherwise.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
/* Get the symbol tables */
|
||||||
|
const SymTable* Tab1 = F1->SymTab;
|
||||||
|
const SymTable* Tab2 = F2->SymTab;
|
||||||
|
|
||||||
/* Compare the parameter lists */
|
/* Compare the parameter lists */
|
||||||
SymEntry* Sym1 = Tab1->SymHead;
|
const SymEntry* Sym1 = Tab1->SymHead;
|
||||||
SymEntry* Sym2 = Tab2->SymHead;
|
const SymEntry* Sym2 = Tab2->SymHead;
|
||||||
|
|
||||||
/* Compare the fields */
|
/* Compare the fields */
|
||||||
while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
|
while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
|
||||||
|
|
||||||
|
/* Get the symbol types */
|
||||||
|
Type* Type1 = Sym1->Type;
|
||||||
|
Type* Type2 = Sym2->Type;
|
||||||
|
|
||||||
|
/* If either of both functions is old style, apply the default
|
||||||
|
* promotions to the parameter type.
|
||||||
|
*/
|
||||||
|
if (F1->Flags & FD_OLDSTYLE) {
|
||||||
|
if (IsClassInt (Type1)) {
|
||||||
|
Type1 = IntPromotion (Type1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (F2->Flags & FD_OLDSTYLE) {
|
||||||
|
if (IsClassInt (Type2)) {
|
||||||
|
Type2 = IntPromotion (Type2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare this field */
|
/* Compare this field */
|
||||||
if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
|
if (TypeCmp (Type1, Type2) < TC_EQUAL) {
|
||||||
/* Field types not equal */
|
/* Field types not equal */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -136,7 +192,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
SymTable* Tab2;
|
SymTable* Tab2;
|
||||||
FuncDesc* F1;
|
FuncDesc* F1;
|
||||||
FuncDesc* F2;
|
FuncDesc* F2;
|
||||||
int Ok;
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize stuff */
|
/* Initialize stuff */
|
||||||
@ -233,22 +288,29 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
F1 = GetFuncDesc (lhs);
|
F1 = GetFuncDesc (lhs);
|
||||||
F2 = GetFuncDesc (rhs);
|
F2 = GetFuncDesc (rhs);
|
||||||
|
|
||||||
/* If one of the functions is implicitly declared, both
|
/* If one of both functions has an empty parameter list (which
|
||||||
* functions are considered equal. If one of the functions is
|
* does also mean, it is not a function definition, because the
|
||||||
* old style, and the other is empty, the functions are
|
* flag is reset in this case), it is considered equal to any
|
||||||
* considered equal.
|
* other definition, provided that the other has no default
|
||||||
|
* promotions in the parameter list. If none of both parameter
|
||||||
|
* lists is empty, we have to check the parameter lists and
|
||||||
|
* other attributes.
|
||||||
*/
|
*/
|
||||||
if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
|
if (F1->Flags & FD_EMPTY) {
|
||||||
Ok = 1;
|
if ((F2->Flags & FD_EMPTY) == 0) {
|
||||||
} else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
|
if (ParamsHaveDefaultPromotions (F2)) {
|
||||||
Ok = 1;
|
/* Flags differ */
|
||||||
} else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
Ok = 1;
|
return;
|
||||||
} else {
|
|
||||||
Ok = 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!Ok) {
|
} else if (F2->Flags & FD_EMPTY) {
|
||||||
|
if (ParamsHaveDefaultPromotions (F1)) {
|
||||||
|
/* Flags differ */
|
||||||
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
/* Check the remaining flags */
|
/* Check the remaining flags */
|
||||||
if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
|
if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
|
||||||
@ -258,7 +320,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Compare the parameter lists */
|
/* Compare the parameter lists */
|
||||||
if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0) {
|
if (EqualFuncParams (F1, F2) == 0) {
|
||||||
/* Parameter list is not identical */
|
/* Parameter list is not identical */
|
||||||
SetResult (Result, TC_INCOMPATIBLE);
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user