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);
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);
}
/* */
/* */
/* */
-/* (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 */
/* */
-/* 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 */
#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)
/*****************************************************************************/
/* */
-/* 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 */
/* */
-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;
}
SymTable* Tab2;
FuncDesc* F1;
FuncDesc* F2;
- int Ok;
/* Initialize stuff */
/* 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
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)) {
}
/* 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;