From: uz Date: Sun, 3 Aug 2008 20:55:36 +0000 (+0000) Subject: Fixed several problems with old style (K&R) declarations and a mix of old and X-Git-Tag: V2.13.0rc1~386 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a1d7fed1286d6950a39533badec3bc169b4695ce;p=cc65 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 --- diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 2157a748e..8475657a4 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -149,6 +149,21 @@ static void Parse (void) 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 */ Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); @@ -240,25 +255,12 @@ static void Parse (void) NextToken (); } else { - FuncDesc* D; - /* Function body. Check for duplicate function definitions */ if (SymIsDef (Entry)) { Error ("Body for function `%s' has already been defined", 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 */ NewFunc (Entry); } diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 9c4bb2c70..4c7e23ff0 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -179,7 +179,7 @@ Type* GetImplicitFuncType (void) Type* T = TypeAlloc (3); /* func/returns int/terminator */ /* Prepare the function descriptor */ - F->Flags = FD_IMPLICIT | FD_EMPTY | FD_VARIADIC; + F->Flags = FD_EMPTY | FD_VARIADIC; F->SymTab = &EmptySymTab; F->TagTab = &EmptySymTab; diff --git a/src/cc65/funcdesc.h b/src/cc65/funcdesc.h index 9cb450046..56da848a1 100644 --- a/src/cc65/funcdesc.h +++ b/src/cc65/funcdesc.h @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2000-2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* (C) 2000-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -44,12 +44,11 @@ -/* Masks for the Flags field in FuncDesc */ +/* Masks for the Flags field in FuncDesc */ #define FD_NONE 0x0000U /* No flags */ -#define FD_IMPLICIT 0x0001U /* Implicitly declared function */ -#define FD_EMPTY 0x0002U /* Function with empty param list */ -#define FD_VOID_PARAM 0x0004U /* Function with a void param list */ -#define FD_VARIADIC 0x0008U /* Function with variable param list */ +#define FD_EMPTY 0x0001U /* Function with empty param list */ +#define FD_VOID_PARAM 0x0002U /* Function with a void param list */ +#define FD_VARIADIC 0x0004U /* Function with variable param list */ #define FD_FASTCALL 0x0010U /* __fastcall__ function */ #define FD_FAR 0x0020U /* __far__ function */ #define FD_NEAR 0x0040U /* __near__ function */ @@ -58,7 +57,7 @@ #define FD_UNNAMED_PARAMS 0x0400U /* Function has unnamed params */ /* 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) diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 8990f48c8..d10a7ad0a 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -753,14 +753,20 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* In case of a function, use the new type descriptor, since it * 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) { /* Get the function descriptor from the new type */ FuncDesc* F = GetFuncDesc (T); - /* Use this new function descriptor */ - Entry->V.F.Func = F; - SetFuncDesc (EType, F); + /* 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; + SetFuncDesc (EType, F); + } } } diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 1ff49e159..0752d60ba 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -1,13 +1,13 @@ /*****************************************************************************/ /* */ -/* typecmp.c */ +/* typecmp.c */ /* */ -/* Type compare function for the cc65 C compiler */ +/* Type compare function for the cc65 C compiler */ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 1998-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* 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 * 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 */ - SymEntry* Sym1 = Tab1->SymHead; - SymEntry* Sym2 = Tab2->SymHead; + const SymEntry* Sym1 = Tab1->SymHead; + const SymEntry* Sym2 = Tab2->SymHead; /* Compare the fields */ 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 */ - if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) { + if (TypeCmp (Type1, Type2) < TC_EQUAL) { /* Field types not equal */ return 0; } @@ -136,7 +192,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; - int Ok; /* Initialize stuff */ @@ -175,7 +230,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* If the raw types are not identical, the types are incompatible */ if (LeftType != RightType) { SetResult (Result, TC_INCOMPATIBLE); - return; + return; } /* On indirection level zero, a qualifier or sign difference is @@ -233,22 +288,29 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); - /* If one of the functions is implicitly declared, both - * functions are considered equal. If one of the functions is - * old style, and the other is empty, the functions are - * considered equal. - */ - if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) { - Ok = 1; - } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) { - Ok = 1; - } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) { - Ok = 1; - } else { - Ok = 0; - } - - if (!Ok) { + /* If one of both functions has an empty parameter list (which + * does also mean, it is not a function definition, because the + * flag is reset in this case), it is considered equal to any + * 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_EMPTY) { + if ((F2->Flags & FD_EMPTY) == 0) { + if (ParamsHaveDefaultPromotions (F2)) { + /* Flags differ */ + SetResult (Result, TC_INCOMPATIBLE); + return; + } + } + } else if (F2->Flags & FD_EMPTY) { + if (ParamsHaveDefaultPromotions (F1)) { + /* Flags differ */ + SetResult (Result, TC_INCOMPATIBLE); + return; + } + } else { /* Check the remaining flags */ 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 */ - if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0) { + if (EqualFuncParams (F1, F2) == 0) { /* Parameter list is not identical */ SetResult (Result, TC_INCOMPATIBLE); return;