raeburn@ATHENA.MIT.EDU (Ken Raeburn) (01/04/89)
According to my understanding, gcc should complain about the assignment in the following file, since the entire structure is volatile, but it accepts it without comment. If the assignment is changed to "& foo -> two", it complains properly about the incompatible pointers. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct frep_regs { int one, two, three; int seven[7]; }; extern volatile struct frep_regs * foo; extern int * bar; void quux (void) { bar = foo -> seven; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Aside from this problem, the following code seems to be helpful in catching casts that drop `volatile' or `const' qualifiers, for example, casting volatile caddr_t foo /* address of per-device regs */ to assign to struct quux_regs * qr /* regs for frobbing QUUX37 combo mag-tape drive and compact disk player */ without properly qualifying the latter as `volatile'. Another example, using the above source file, would be bar = (int *) & foo -> two; I changed toplev.c to set the variable warn_qual if -Wqual is specified in the argument list (okay, so it's not the greatest of names, but -Wcast sounds more like lint's "questionable cast"), and made the following change to c-typeck.c: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *************** *** 2677,2682 **** --- 2680,2686 ---- tree expr; { register tree value; + tree expr_type = TREE_TYPE (expr); if (type == error_mark_node) return error_mark_node; *************** *** 2690,2695 **** --- 2694,2719 ---- warning ("ANSI C forbids casting nonscalar to the same type"); } return expr; + } + + if (warn_qual + && (TREE_CODE (expr_type) == POINTER_TYPE + || TREE_CODE (expr_type) == ARRAY_TYPE) + && TREE_CODE (type) == POINTER_TYPE) + { + /* Attempt to determine whether the cast is going to drop any + 'volatile' or 'const' info. If we wanted to be masochistic, + we could examine structures pointed to, pointers they + contain, ad nauseam. For the moment, just make some minimal + attempt... We'll just look at the direct target of a + pointer. */ + tree target1, target2; + target1 = TREE_TYPE (expr_type); + target2 = TREE_TYPE (type); + if (TREE_VOLATILE (target1) && !TREE_VOLATILE (target2)) + warning ("pointer cast drops ``volatile'' qualifier"); + if (TREE_READONLY (target1) && !TREE_READONLY (target2)) + warning ("pointer cast drops ``const'' qualifier"); } value = convert (TYPE_MAIN_VARIANT (type), default_conversion (expr)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The declaration of warn_qual should be in flags.h, but I've had it in c-typeck.c to minimize the number of files that get recompiled. ~~ Ken