mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 02:29:52 +00:00
Fixed checks and diagnostics on type-casting.
This commit is contained in:
parent
23621f3299
commit
911a79796d
@ -207,27 +207,30 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||||||
printf ("\n");
|
printf ("\n");
|
||||||
PrintRawType (stdout, NewType);
|
PrintRawType (stdout, NewType);
|
||||||
#endif
|
#endif
|
||||||
|
/* First, do some type checking */
|
||||||
int HasWarning = 0;
|
int HasWarning = 0;
|
||||||
int HasError = 0;
|
int HasError = 0;
|
||||||
const char* Msg = 0;
|
const char* Msg = 0;
|
||||||
const Type* OldType = Expr->Type;
|
const Type* OldType = Expr->Type;
|
||||||
|
|
||||||
|
|
||||||
/* First, do some type checking */
|
/* If one of the sides is of type void, it is an error */
|
||||||
if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
|
if (IsTypeVoid (NewType) || IsTypeVoid (OldType)) {
|
||||||
/* If one of the sides are of type void, output a more apropriate
|
HasError = 1;
|
||||||
** error message.
|
|
||||||
*/
|
|
||||||
Error ("Illegal type");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If Expr is a function, convert it to pointer to function */
|
/* If both types are strictly compatible, no conversion is needed */
|
||||||
if (IsTypeFunc (Expr->Type)) {
|
if (TypeCmp (NewType, OldType) >= TC_STRICT_COMPATIBLE) {
|
||||||
Expr->Type = PointerTo (Expr->Type);
|
/* We're already done */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If both types are equal, no conversion is needed */
|
/* If Expr is an array or a function, convert it to a pointer */
|
||||||
if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) {
|
Expr->Type = PtrConversion (Expr->Type);
|
||||||
|
|
||||||
|
/* If we have changed the type, check again for strictly compatibility */
|
||||||
|
if (Expr->Type != OldType &&
|
||||||
|
TypeCmp (NewType, Expr->Type) >= TC_STRICT_COMPATIBLE) {
|
||||||
/* We're already done */
|
/* We're already done */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -237,10 +240,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||||||
|
|
||||||
/* Handle conversions to int type */
|
/* Handle conversions to int type */
|
||||||
if (IsClassPtr (Expr->Type)) {
|
if (IsClassPtr (Expr->Type)) {
|
||||||
/* Pointer -> int conversion. Convert array to pointer */
|
|
||||||
if (IsTypeArray (Expr->Type)) {
|
|
||||||
Expr->Type = ArrayToPtr (Expr->Type);
|
|
||||||
}
|
|
||||||
Warning ("Converting pointer to integer without a cast");
|
Warning ("Converting pointer to integer without a cast");
|
||||||
} else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
|
} else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
|
||||||
HasError = 1;
|
HasError = 1;
|
||||||
@ -254,11 +253,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||||||
/* Handle conversions to pointer type */
|
/* Handle conversions to pointer type */
|
||||||
if (IsClassPtr (Expr->Type)) {
|
if (IsClassPtr (Expr->Type)) {
|
||||||
|
|
||||||
/* Convert array to pointer */
|
|
||||||
if (IsTypeArray (Expr->Type)) {
|
|
||||||
Expr->Type = ArrayToPtr (Expr->Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pointer to pointer assignment is valid, if:
|
/* Pointer to pointer assignment is valid, if:
|
||||||
** - both point to the same types, or
|
** - both point to the same types, or
|
||||||
** - the rhs pointer is a void pointer, or
|
** - the rhs pointer is a void pointer, or
|
||||||
@ -271,11 +265,15 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||||||
case TC_INCOMPATIBLE:
|
case TC_INCOMPATIBLE:
|
||||||
HasWarning = 1;
|
HasWarning = 1;
|
||||||
Msg = "Incompatible pointer assignment to '%s' from '%s'";
|
Msg = "Incompatible pointer assignment to '%s' from '%s'";
|
||||||
|
/* Use the pointer type in the diagnostic */
|
||||||
|
OldType = Expr->Type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TC_QUAL_DIFF:
|
case TC_QUAL_DIFF:
|
||||||
HasWarning = 1;
|
HasWarning = 1;
|
||||||
Msg = "Pointer assignment to '%s' from '%s' discards qualifiers";
|
Msg = "Pointer assignment to '%s' from '%s' discards qualifiers";
|
||||||
|
/* Use the pointer type in the diagnostic */
|
||||||
|
OldType = Expr->Type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -309,8 +307,21 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||||||
TypeCompatibilityDiagnostic (NewType, OldType, 0, Msg);
|
TypeCompatibilityDiagnostic (NewType, OldType, 0, Msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Both types must be complete */
|
||||||
|
if (!IsIncompleteESUType (NewType) && !IsIncompleteESUType (Expr->Type)) {
|
||||||
/* Do the actual conversion */
|
/* Do the actual conversion */
|
||||||
DoConversion (Expr, NewType);
|
DoConversion (Expr, NewType);
|
||||||
|
} else {
|
||||||
|
/* We should have already generated error elsewhere so that we
|
||||||
|
** could just silently fail here to avoid excess errors, but to
|
||||||
|
** be safe, we must ensure that we do have errors.
|
||||||
|
*/
|
||||||
|
if (IsIncompleteESUType (NewType)) {
|
||||||
|
Error ("Conversion to incomplete type '%s'", GetFullTypeName (NewType));
|
||||||
|
} else {
|
||||||
|
Error ("Conversion from incomplete type '%s'", GetFullTypeName (Expr->Type));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,19 +344,30 @@ void TypeCast (ExprDesc* Expr)
|
|||||||
/* Read the expression we have to cast */
|
/* Read the expression we have to cast */
|
||||||
hie10 (Expr);
|
hie10 (Expr);
|
||||||
|
|
||||||
/* Only allow casts to arithmetic or pointer types, or just changing the
|
/* Only allow casts to arithmetic, pointer or void types */
|
||||||
** qualifiers.
|
if (IsCastType (NewType)) {
|
||||||
*/
|
if (!IsIncompleteESUType (NewType)) {
|
||||||
if (TypeCmp (NewType, Expr->Type) >= TC_QUAL_DIFF) {
|
|
||||||
/* The expression has always the new type */
|
|
||||||
ReplaceType (Expr, NewType);
|
|
||||||
} else if (IsCastType (NewType)) {
|
|
||||||
/* Convert functions and arrays to "pointer to" object */
|
/* Convert functions and arrays to "pointer to" object */
|
||||||
Expr->Type = PtrConversion (Expr->Type);
|
Expr->Type = PtrConversion (Expr->Type);
|
||||||
/* Convert the value */
|
|
||||||
|
if (TypeCmp (NewType, Expr->Type) >= TC_QUAL_DIFF) {
|
||||||
|
/* If the new type only differs in qualifiers, just use it to
|
||||||
|
** replace the old one.
|
||||||
|
*/
|
||||||
|
ReplaceType (Expr, NewType);
|
||||||
|
} else if (IsCastType (Expr->Type)) {
|
||||||
|
/* Convert the value. The rsult has always the new type */
|
||||||
DoConversion (Expr, NewType);
|
DoConversion (Expr, NewType);
|
||||||
} else {
|
} else {
|
||||||
Error ("Arithmetic or pointer type expected but '%s' is used",
|
TypeCompatibilityDiagnostic (NewType, Expr->Type, 1,
|
||||||
|
"Cast to incompatible type '%s' from '%s'");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Error ("Cast to incomplete type '%s'",
|
||||||
GetFullTypeName (NewType));
|
GetFullTypeName (NewType));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Error ("Arithmetic or pointer type expected but %s is used",
|
||||||
|
GetBasicTypeName (NewType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user