This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

'*' operation and TYPE_MAIN_VARIANT()


While working on GCC recently, I ran into an area of code in c-typeck.c that
raised a question regarding the sementics of the '*' (indirect operation),
and whether the code in build_indirect() is exactly as it should be. In
gcc-3.1.1:

  1323        else
  1324          {
  1325            tree t = TREE_TYPE (type);
  1326            register tree ref = build1 (INDIRECT_REF,
  1327                                        TYPE_MAIN_VARIANT (t),
pointer);
  1328
  1329            if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
  1330              {
  1331                error ("dereferencing pointer to incomplete type");
  1332                return error_mark_node;
  1333              }
  1334            if (TREE_CODE (t) == VOID_TYPE)
  1335              warning ("dereferencing `void *' pointer");
  1336
  1337            /* We *must* set TREE_READONLY when dereferencing a
pointer to const,
  1338               so that we get the proper error message if the result
is used
  1339               to assign to.  Also, &* is supposed to be a no-op.
  1340               And ANSI C seems to specify that the type of the result
  1341               should be the const type.  */
  1342            /* A de-reference of a pointer to const is not a const.
It is valid
  1343               to change it via some other pointer.  */
  1344            TREE_READONLY (ref) = TYPE_READONLY (t);
  1345            TREE_SIDE_EFFECTS (ref)
  1346              = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) ||
flag_volatile;
  1347            TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
  1348            return ref;
  1349          }

The question that I have is whether the reference to TYPE_MAIN_VARIANT(t) at
line #1327 should simply refer to `t'?  As I understand the meaning of
TYPE_MAIN_VARIANT(), it is the type `t' with all of its qualifiers stripped.
Is it not the case that if P is a pointer to qualified type T, that *P
should yield T, and not T with the qualifiers stripped?

I did a little investigation, and it seems that other parts of the compiler
mask the use of TYPE_MAIN_VARIANT() above. The semantic checking for '*'
will check TREE_READ_ONLY() for example to see whether *p refers to a
read-only (i. e., "const") value, and TREE_READONLY() is derived directly
from type t's (and not t's main variant) TYPE_READONLY flag, which is in
turn derived from t's TYPE_QUAL_CONST qualifier. Further, the semantics for
the construct &*p look explicity for the
"address of an indirected pointer" sequence and in that circumstance, uses
the type of T (where p is a pointer to an object of type T), rather than
using the (unqualified) type assigned to the expression node built for *p.

In summary, it is probably the case that other parts of the compiler cancel
out, or mask the fact that TYPE_MAIN_VARIANT(t) of t was used, rather than
just `t'.  Then again, I might be wrong - this code has been this way since
at least 2.7.2 (I didn't check anything ealier). I'm wondering if there is a
C language rule that would dictate that *P should result in a value that has
the type T with qualifiers removed? Or should the resulting type simply be
T?  If the latter, then line 1326 above should not refer to
TYPE_MAIN_VARIANT() and should read:

           register tree ref = build1 (INDIRECT_REF, t pointer);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]