g++ and aliasing bools
Daniel Berlin
dan@dberlin.org
Fri Jan 25 22:14:00 GMT 2002
>
> None the less, I'm happy to provide a sketch. I will do the version
> without restrict (that was added later) and without the assignment of
> alias sets to structs (Kenner added that later), and without
> type-punning for unions (this is optional under ANSI/ISO C).
>
> This is from memory; there might be minor mistakes. Also note that
> the code has changed considerably from my original version, which
> makes it harder to see the structure.
>
> 1. The C aliasing rules say that if you reference memory using one
> type, you may not reference it using another types, unless:
>
> - The types are signed/unsigned variants of each other.
>
> - The types very only in their cv-qualification.
>
> - One of them is (possibly cv-qualified) "char"
The void * type, as well, because it says "A type compatible with the
effective type of the object." and " [#1] A pointer to void may be
converted to or from a pointer
to any incomplete or object type. A pointer to any
incomplete or object type may be converted to a pointer to
void and back again; the result shall compare equal to the
original pointer." and " [#2] Conversion of an operand value to
a compatible type causes no change to the value or the
representation." and "[#2] For two pointer types to be compatible, both
shall be identically qualified and both shall be pointers to
compatible types."
Which seems to imply that the void * type can legally alias anything,
because it's compatible with everything (though it only appears to have
all the properties of compatible types, i can't find a specific phrase to
support that it *is* a compatible type of everything )
Pro64 (I haven't looked at other compilers) seems to agree with me too:
* C.1: (ANSI Rules)
*
* An object shall have its stored value accessed only by an lvalue
that
* has one of the following types:
* *) the declared type of the object,
* *) a qualified version of the declared type of the object,
* *) a type that is signed or unsigned type corresponding to the
declared type
* of the object,
* *) a type that is signed or unsigned type corresponding to a
* qualified version of the declared type of the object,
* *) an aggregrate or union type that includes one of the
aforementioned types
* among its members (including, recursively, a member of a
subaggregate
* or contained union),
* *) a character type, or
* *) a void type.
*
^^^^^^^^^^^^^^^^^^^^^
* Use the Ragnarok interpretation here. Objects are aliased if
* their base types (MTYPES), after stripping off the qualifiers and
* signed-ness, are equal. See ANSI C 3.3 and 3.2.2.3.
*
* C.2: (C Qualifier Rule)
*
* C.2.1: (restricted pointer)
* If both memory operations are restricted pointer dereference,
* they are not aliased if their based pointer are different.
*
>
> 2. Alias sets have the following semantics:
>
> - Two things in the same alias set may alias one another.
>
> - Things in two distinct alias sets may alias if one is
> a "subset" of another, under transitive closure.
>
> - All alias sets are a subset of a special alias set
> called "alias set zero". (An immediate consequence is
> that something in alias set zero can alias everything.)
>
> Let T be the set of all C types. Let TA be a relation on TxT such
> that (t1, t2) \in TA if and only if t and u may alias.
>
> Similarly, let S be the set of all alias sets. Let SA be relation on
> SxS that (s1, s2) \in SA if and only if s1 and s2 may alias. (Note
> that in the original incarnation, there were no subsets other than
> the fact that everything was a subset of alias set zero, so this
> relation is well-defined statically.)
>
> What we wish to prove is that C's lang_get_alias_set assigns
> alias sets to type safely. In particular, let f be
> c_get_alias_set, and then:
>
> Then, we wish to show that, for all t, u \in T:
>
> (t, u) \in TA \implies f(t), f(u)) \in SA
>
> (We do not need if and only if for correctness.)
>
> The proof is by induction. All aggregate types are mapped
> to alias set zero which aliases everything; therefore, we
> need only consider non-aggregate types. The code says:
>
> if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))
> {
> tree t1 = signed_type (t);
>
> return get_alias_set (t1);
> }
>
> Therefore, signed and unsigned variants of types get the same alias
> set.
>
> The code says:
>
> t = TYPE_MAIN_VARIANT (t);
> if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t))
> return TYPE_ALIAS_SET (t);
>
> Therefore, if a cv-qualified type and its unqualified variant will
> get the same alias set. By transitivity, so will all cv-qualified
> variants of the type.
>
> The code says that:
>
> /* If this is a char *, the ANSI C standard says it can alias
> anything. Note that all references need do this. */
> if (TREE_CODE_CLASS (TREE_CODE (t)) == 'r'
> && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
> && TYPE_PRECISION (TREE_TYPE (t)) == TYPE_PRECISION (char_type_node))
> return 0;
>
> Therefore, "char" is mapped to alias set zero, completing the proof.
What about void * types, we never seem to handle that specifically?
>
> --
> Mark Mitchell mark@codesourcery.com
> CodeSourcery, LLC http://www.codesourcery.com
>
More information about the Gcc
mailing list