diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 8fc314342..4bfd52c5e 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -493,8 +493,44 @@ static void FixQualifiers (Type* DataType) +static void FixFunctionReturnType (Type* T) +/* Check if the data type consists of any functions returning forbidden return +** types and remove qualifiers from the return types if they are not void. +*/ +{ + while (T->C != T_END) { + if (IsTypeFunc (T)) { + ++T; + + /* Functions may not return functions or arrays */ + if (IsTypeFunc (T)) { + Error ("Functions are not allowed to return functions"); + } else if (IsTypeArray (T)) { + Error ("Functions are not allowed to return arrays"); + } + + /* The return type must not be qualified */ + if ((GetQualifier (T) & T_QUAL_CVR) != T_QUAL_NONE) { + /* We are stricter than the standard here */ + if (GetRawTypeRank (T) == T_RANK_VOID) { + /* A qualified void type is always an error */ + Error ("Function definition has qualified void return type"); + } else { + /* For others, qualifiers are ignored */ + Warning ("Type qualifiers ignored on function return type"); + T[0].C &= ~T_QUAL_CVR; + } + } + } else { + ++T; + } + } +} + + + static void CheckArrayElementType (const Type* T) -/* Check if data type consists of arrays of incomplete element types */ +/* Check recursively if type consists of arrays of forbidden element types */ { while (T->C != T_END) { if (IsTypeArray (T)) { @@ -2061,46 +2097,39 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) /* Do several fixes on qualifiers */ FixQualifiers (D->Type); - /* Check if the data type consists of any arrays of forbidden types */ - CheckArrayElementType (D->Type); + /* Check if the data type consists of any functions returning forbidden return + ** types and remove qualifiers from the return types if they are not void. + */ + FixFunctionReturnType (D->Type); - /* If we have a function, add a special storage class */ - if (IsTypeFunc (D->Type)) { - D->StorageClass |= SC_FUNC; - } + /* Check recursively if the data type consists of arrays of forbidden types */ + CheckArrayElementType (D->Type); /* Parse attributes for this declarator */ ParseAttribute (D); - /* Check several things for function or function pointer types */ - if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) { + /* If we have a function, add a special storage class */ + if (IsTypeFunc (D->Type)) { - /* A function. Check the return type */ - Type* RetType = GetFuncReturnTypeModifiable (D->Type); + D->StorageClass |= SC_FUNC; - /* Functions may not return functions or arrays */ - if (IsTypeFunc (RetType)) { - Error ("Functions are not allowed to return functions"); - } else if (IsTypeArray (RetType)) { - Error ("Functions are not allowed to return arrays"); - } + } else if (!IsTypeVoid (D->Type)) { + /* Check the size of the generated type */ + unsigned Size = SizeOf (D->Type); - /* The return type must not be qualified */ - if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) { - - if (GetRawTypeRank (RetType) == T_RANK_VOID) { - /* A qualified void type is always an error */ - Error ("function definition has qualified void return type"); + if (Size >= 0x10000) { + if (D->Ident[0] != '\0') { + Error ("Size of '%s' is invalid (0x%06X)", D->Ident, Size); } else { - /* For others, qualifiers are ignored */ - Warning ("type qualifiers ignored on function return type"); - RetType[0].C = GetUnqualRawTypeCode (RetType); + Error ("Invalid size in declaration (0x%06X)", Size); } } + } - /* Warn about an implicit int return in the function */ - if ((Spec->Flags & DS_DEF_TYPE) != 0 && - RetType[0].C == T_INT && RetType[1].C == T_END) { + /* Check a few pre-C99 things */ + if ((Spec->Flags & DS_DEF_TYPE) != 0) { + /* Check and warn about an implicit int return in the function */ + if (IsTypeFunc (D->Type) && IsRankInt (GetFuncReturnType (D->Type))) { /* Function has an implicit int return. Output a warning if we don't ** have the C89 standard enabled explicitly. */ @@ -2110,29 +2139,16 @@ void ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode) GetFuncDesc (D->Type)->Flags |= FD_OLDSTYLE_INTRET; } - } - - /* For anthing that is not a function or typedef, check for an implicit - ** int declaration. - */ - if ((D->StorageClass & SC_FUNC) != SC_FUNC && - (D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { - /* If the standard was not set explicitly to C89, print a warning - ** for variables with implicit int type. + /* For anthing that is not a function or typedef, check for an implicit + ** int declaration. */ - if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) { - Warning ("Implicit 'int' is an obsolete feature"); - } - } - - if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type)) { - /* Check the size of the generated type */ - unsigned Size = SizeOf (D->Type); - if (Size >= 0x10000) { - if (D->Ident[0] != '\0') { - Error ("Size of '%s' is invalid (0x%06X)", D->Ident, Size); - } else { - Error ("Invalid size in declaration (0x%06X)", Size); + if ((D->StorageClass & SC_FUNC) != SC_FUNC && + (D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { + /* If the standard was not set explicitly to C89, print a warning + ** for variables with implicit int type. + */ + if (IS_Get (&Standard) >= STD_C99) { + Warning ("Implicit 'int' is an obsolete feature"); } } } diff --git a/src/cc65/function.c b/src/cc65/function.c index 1ad89b111..06800b133 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -466,11 +466,15 @@ void NewFunc (SymEntry* Func, FuncDesc* D) /* Check return type */ ReturnType = F_GetReturnType (CurrentFunc); - if (IsIncompleteESUType (ReturnType)) { + if (!IsTypeArray (ReturnType) && !IsTypeFunc (ReturnType)) { /* There are already diagnostics on returning arrays or functions */ - if (!IsTypeArray (ReturnType) && !IsTypeFunc (ReturnType)) { + if (IsIncompleteESUType (ReturnType)) { Error ("Function has incomplete return type '%s'", GetFullTypeName (ReturnType)); + } else if (IsPassByRefType (ReturnType)) { + /* Handle struct/union specially */ + Error ("Function return type '%s' of size %u is unsupported", + GetFullTypeName (ReturnType), SizeOf (ReturnType)); } } diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index e1add990e..c86f25f8a 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -311,7 +311,6 @@ static void ReturnStatement (void) /* Handle the 'return' statement */ { ExprDesc Expr; - const Type* ReturnType; ED_Init (&Expr); NextToken (); @@ -327,31 +326,19 @@ static void ReturnStatement (void) if (F_HasVoidReturn (CurrentFunc)) { Error ("Returning a value in function with return type 'void'"); } else { - /* Check the return type first */ - ReturnType = F_GetReturnType (CurrentFunc); - if (IsIncompleteESUType (ReturnType)) { - /* Avoid excess errors */ - if (ErrorCount == 0) { - Error ("Returning a value in function with incomplete return type"); - } + const Type* ReturnType = F_GetReturnType (CurrentFunc); + + /* Convert the return value to the type of the function result */ + TypeConversion (&Expr, ReturnType); + + /* Load the value into the primary */ + if (IsClassStruct (Expr.Type)) { + /* Handle struct/union specially */ + LoadExpr (CG_TypeOf (GetStructReplacementType (ReturnType)), &Expr); } else { - /* Convert the return value to the type of the function result */ - TypeConversion (&Expr, ReturnType); - /* Load the value into the primary */ - if (IsClassStruct (Expr.Type)) { - /* Handle struct/union specially */ - ReturnType = GetStructReplacementType (Expr.Type); - if (ReturnType == Expr.Type) { - Error ("Returning '%s' of this size by value is not supported", GetFullTypeName (Expr.Type)); - } - LoadExpr (CG_TypeOf (ReturnType), &Expr); - - } else { - /* Load the value into the primary */ - LoadExpr (CF_NONE, &Expr); - } + LoadExpr (CF_NONE, &Expr); } /* Append deferred inc/dec at sequence point */