Warnings on discarding pointer qualifiers always.

Added new -W options to turn on/off warnings on certain pointer conversion cases:
- pointer-sign: to a pointer type differing in pointee signedness. Default on.
- pointer-types: to a pointer type incompatible. Default on.
This commit is contained in:
acqn 2021-03-25 13:32:46 +08:00 committed by Oliver Schmidt
parent b802efde54
commit 4a38965384
5 changed files with 36 additions and 17 deletions

View file

@ -68,6 +68,8 @@ IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */
/* Warn about: */
IntStack WarnConstComparison= INTSTACK(1); /* - constant comparison results */
IntStack WarnNoEffect = INTSTACK(1); /* - statements without an effect */
IntStack WarnPointerSign = INTSTACK(1); /* - pointer conversion to pointer differing in signedness */
IntStack WarnPointerTypes = INTSTACK(1); /* - pointer conversion to incompatible pointer type */
IntStack WarnRemapZero = INTSTACK(1); /* - remapping character code zero */
IntStack WarnStructParam = INTSTACK(0); /* - structs passed by val */
IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
@ -87,6 +89,8 @@ static WarnMapEntry WarnMap[] = {
{ &WarnConstComparison, "const-comparison" },
{ &WarningsAreErrors, "error" },
{ &WarnNoEffect, "no-effect" },
{ &WarnPointerSign, "pointer-sign" },
{ &WarnPointerTypes, "pointer-types" },
{ &WarnRemapZero, "remap-zero" },
{ &WarnStructParam, "struct-param" },
{ &WarnUnknownPragma, "unknown-pragma" },

View file

@ -64,6 +64,8 @@ extern IntStack WarnEnable; /* Enable warnings */
extern IntStack WarningsAreErrors; /* Treat warnings as errors */
/* Warn about: */
extern IntStack WarnConstComparison; /* - constant comparison results */
extern IntStack WarnPointerSign; /* - pointer conversion to pointer differing in signedness */
extern IntStack WarnPointerTypes; /* - pointer conversion to incompatible pointer type */
extern IntStack WarnNoEffect; /* - statements without an effect */
extern IntStack WarnRemapZero; /* - remapping character code zero */
extern IntStack WarnStructParam; /* - structs passed by val */

View file

@ -143,6 +143,7 @@ static void SetResult (typecmp_t* Result, typecmpcode_t Val)
if (Val < Result->C) {
if (Result->Indirections > 0) {
if (Val >= TC_STRICT_COMPATIBLE) {
/* Arrays etc. */
Result->C = Val;
} else if (Result->Indirections == 1) {
/* C Standard allows implicit conversion as long as one side is
@ -150,10 +151,17 @@ static void SetResult (typecmp_t* Result, typecmpcode_t Val)
*/
if ((Result->F & TCF_MASK_VOID_PTR) != 0) {
Result->C = TC_VOID_PTR;
} else if (Val == TC_SIGN_DIFF) {
/* Special treatment with pointee signedness difference */
Result->C = TC_PTR_SIGN_DIFF;
} else {
/* Incompatible */
Result->C = TC_PTR_INCOMPATIBLE;
}
} else {
/* Pointer-to-pointer types must have compatible pointte types,
** or they are just incompatible.
*/
Result->C = TC_PTR_INCOMPATIBLE;
}
} else {

View file

@ -52,6 +52,7 @@
typedef enum {
TC_INCOMPATIBLE, /* Distinct types */
TC_SIGN_DIFF, /* Signedness differs */
TC_PTR_SIGN_DIFF, /* Pointee signedness differs */
TC_PTR_INCOMPATIBLE, /* Distinct pointer types */
TC_VOID_PTR, /* Non-void and void pointers */
TC_STRICT_COMPATIBLE, /* Strict compatibility according to the C Standard */

View file

@ -190,7 +190,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
#endif
/* First, do some type checking */
typecmp_t Result = TYPECMP_INITIALIZER;
int HasWarning = 0;
int HasError = 0;
const char* Msg = 0;
const Type* OldType = Expr->Type;
@ -232,19 +231,28 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
** - both point to the same types, or
** - the rhs pointer is a void pointer, or
** - the lhs pointer is a void pointer.
** Note: We additionally allow converting function pointers to and from
** void pointers, just with warnings.
*/
if (Result.C <= TC_PTR_INCOMPATIBLE ||
(Result.F & TCF_INCOMPATIBLE_QUAL) != 0)
{
HasWarning = 1;
Msg = "Incompatible pointer conversion to '%s' from '%s'";
/* Use the pointer type in the diagnostic */
OldType = Expr->Type;
} else if ((Result.F & TCF_PTR_QUAL_DIFF) != 0) {
HasWarning = 1;
Msg = "Pointer conversion to '%s' from '%s' discards qualifiers";
/* Use the pointer type in the diagnostic */
OldType = Expr->Type;
if (Result.C == TC_PTR_SIGN_DIFF) {
/* Specific warning for pointee signedness difference */
if (IS_Get (&WarnPointerSign)) {
TypeCompatibilityDiagnostic (NewType, Expr->Type,
0, "Pointer conversion to '%s' from '%s' changes pointee signedness");
}
} else if ((Result.C <= TC_PTR_INCOMPATIBLE ||
(Result.F & TCF_INCOMPATIBLE_QUAL) != 0)) {
/* Incompatible pointee types or qualifiers */
if (IS_Get (&WarnPointerTypes)) {
TypeCompatibilityDiagnostic (NewType, Expr->Type,
0, "Incompatible pointer conversion to '%s' from '%s'");
}
}
if ((Result.F & TCF_PTR_QUAL_DIFF) != 0) {
/* Discarding qualifiers is a bad thing and we always warn */
TypeCompatibilityDiagnostic (NewType, Expr->Type,
0, "Pointer conversion to '%s' from '%s' discards qualifiers");
}
} else if (IsClassInt (Expr->Type)) {
@ -269,10 +277,6 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
if (HasError) {
TypeCompatibilityDiagnostic (NewType, OldType, 1, Msg);
} else {
if (HasWarning) {
TypeCompatibilityDiagnostic (NewType, OldType, 0, Msg);
}
/* Both types must be complete */
if (!IsIncompleteESUType (NewType) && !IsIncompleteESUType (Expr->Type)) {
/* Do the actual conversion */