type_t *const points_to = skip_typeref(pointer_type->points_to);
unsigned elem_size = get_type_size_const(points_to);
- /* gcc extension */
- if (elem_size == 0 && is_type_atomic(points_to, ATOMIC_TYPE_VOID)) {
+ /* gcc extension: allow arithmetic with void * and function * */
+ if (elem_size == 0 &&
+ (is_type_atomic(points_to, ATOMIC_TYPE_VOID) ||
+ is_type_function(points_to))) {
elem_size = 1;
}
points_to = skip_typeref(points_to);
if (is_type_incomplete(points_to) &&
- (! (c_mode & _GNUC)
- || !is_type_atomic(points_to, ATOMIC_TYPE_VOID))) {
+ !((c_mode & _GNUC)
+ && is_type_atomic(points_to, ATOMIC_TYPE_VOID))) {
errorf(source_position,
- "arithmetic with pointer to incomplete type '%T' not allowed",
- orig_pointer_type);
+ "arithmetic with pointer to incomplete type '%T' not allowed",
+ orig_pointer_type);
return false;
- } else if (is_type_function(points_to)) {
+ } else if (!(c_mode & _GNUC) && is_type_function(points_to)) {
errorf(source_position,
- "arithmetic with pointer to function type '%T' not allowed",
- orig_pointer_type);
+ "arithmetic with pointer to function type '%T' not allowed",
+ orig_pointer_type);
return false;
}
+ if (warning.pointer_arith) {
+ if (is_type_atomic(points_to, ATOMIC_TYPE_VOID)) {
+ warningf(source_position,
+ "pointer of type '%T' used in arithmetic",
+ orig_pointer_type);
+ } else if (is_type_function(points_to)) {
+ warningf(source_position,
+ "pointer to a function '%T' used in arithmetic",
+ orig_pointer_type);
+ }
+ }
return true;
}
.nested_externs = false,
.nonnull = true,
.redundant_decls = true,
+ .pointer_arith = true,
.return_type = true,
.s_are_errors = false,
.shadow = false,
SET(main);
SET(nonnull);
SET(redundant_decls);
+ SET(pointer_arith);
SET(return_type);
SET(shadow);
SET(sign_compare);
OPT("nested-externs", nested_externs);
OPT("nonnull", nonnull);
OPT("redundant-decls", redundant_decls);
+ OPT("pointer_arith", pointer_arith);
OPT("return-type", return_type);
OPT("shadow", shadow);
OPT("sign-compare", sign_compare);
bool packed:1; /**< Warn if a structure is given the packed attribute, but the packed attribute has no effect on the layout or size of the structure */
bool padded:1; /**< Warn if padding is included in a structure, either to align an element of the structure or to align the whole structure */
bool parentheses:1; /**< Warn if parentheses are omitted in certain contexts (assignment where truth value is expected, if-else-braces) */
- bool pointer_arith:1; /**< Warn about anything that depends on the "size of" a function type or of 'void' */
#endif
+ bool pointer_arith:1; /**< Warn about anything that depends on the "size of" a function type or of 'void' */
bool redundant_decls:1; /**< Warn about redundant declarations */
bool return_type:1; /* TODO not fully implemented */ /**< Warn about function definitions with a return-type that defaults to 'int'. Also warn about any 'return' statement with no return-value in a function whose return-type is not 'void'. */
bool s_are_errors:1; /**< Treat warnings as errors */