https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114959

            Bug ID: 114959
           Summary: incorrect TBAA for drived types involving function
                    types
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: muecker at gwdg dot de
  Target Milestone: ---

The  example below shows that aliasing analysis treats some derived types as
incompatible even though they are derived from compatible types char (*)[1] and
char (*)[] and should then be compatible themselves.


The effect type rules are defined in "6.5 Expressions" and allows accesses with 

— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the
object,
— a type that is the signed or unsigned type corresponding to the effective
type of the object,
— a type that is the signed or unsigned type corresponding to a qualified
version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types
among its members
(including, recursively, a member of a subaggregate or contained union), or
— a character type.

The relevant condition is the first which refers to type compatibility.
Type compatibility rules are defined in "6.2.7 Type compatibility and composite
type"

"Two types are compatible types if they are the same. Additional rules for
determining whether two types are compatible are described in 6.7.2 for type
specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators.58)
Moreover, two complete structure, union, or enumerated types declared..."

In 6.7.6 we then have

"For two pointer types to be compatible, both shall be identically qualified
and both shall be pointers to compatible types."

"For two array types to be compatible, both shall have compatible element
types, and if both size specifiers are present, and are integer constant
expressions, then both size specifiers shall have the same constant value."

"For two function types to be compatible, both shall specify compatible return
types. Moreover, the parameter type lists shall agree in the number of
parameters and in use of the final ellipsis; corresponding parameters shall
have compatible types. In the determination of type compatibility and of a
composite type, each parameter declared with function or array type is taken as
having the adjusted type and each parameter declared with qualified type is
taken as having the unqualified version of its declared type."


So type compatibility builds up recursively and types derived in the same way
from different but compatible types are compatible.



Example:


https://godbolt.org/z/rTsE3PhKc


#define COMPAT

typedef char (*(*t0)())[];
typedef char (*(*t1)())[1];
#ifdef COMPAT
typedef char (*(*t2)())[/*2*/];
#else
typedef char (*(*t2)())[2];
#endif

//[[gnu::noinline]]
t0 foo(t0 *x, t0 *y, t0 u, t0 v)
{
    t1 *a = x;
    t2 *b = y;
#ifdef COMPAT
    _Static_assert(_Generic(*b, typeof(*a): 1, default: 0), "");
#endif
    (*a) = u;
    // since *a and *b alias and the types are compatible,
    // this should overwrite the result
    (*b) = v;   
    return *a;
}


char (*(a()))[1] { return 0; }
char (*(b()))[2] { return 0; }

int main()
{
    t0 t;
    return &a == foo(&t, &t, &a, &b);
}

Reply via email to