1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-08 15:29:37 +00:00

Merge branch 'master' into fptest

This commit is contained in:
mrdudz 2023-11-01 15:23:49 +01:00
commit a20e7b385c
3 changed files with 83 additions and 76 deletions

View File

@ -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");
}
}
}

View File

@ -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));
}
}

View File

@ -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 */