Bootstrap

Studying note of GCC-3.4.6 source (166)

5.13.5.1.3.        Prepare alias set

However, the entry point for creating alias set is get_alias_set below. Both node of type and node of declaration can claim for alias analysis, but declaration’s alias set is determined by the alias set of underlying type. Condition at line 467 selects out the node of declaration. In C++ front-end, hook get_alias_set at line 475 points to cxx_get_alias_set . However, the function majorly handles node of type definition, we leave the function for the moment.

 

449  HOST_WIDE_INT

450  get_alias_set (tree t)                                                                                    in alias.c

451  {

452    HOST_WIDE_INT set;

453 

454    /* If we're not doing any alias analysis, just assume everything

455      aliases everything else. Also return 0 if this or its type is

456      an error.  */

457    if (! flag_strict_aliasing || t == error_mark_node

458        || (! TYPE_P (t)

459          && (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node)))

460      return 0;

461 

462    /* We can be passed either an expression or a type. This and the

463      language-specific routine may make mutually-recursive calls to each other

464      to figure out what to do. At each juncture, we see if this is a tree

465      that the language may need to handle specially. First handle things that

466      aren't types.  */

467    if (! TYPE_P (t))

468    {

469      tree inner = t;

470      tree placeholder_ptr = 0;

471 

472      /* Remove any nops, then give the language a chance to do

473         something with this tree before we look at it.  */

474      STRIP_NOPS (t);

475      set = (*lang_hooks . get_alias_set ) (t);

476      if (set != -1)

477        return set;

478 

479      /* First see if the actual object referenced is an INDIRECT_REF from a

480          restrict-qualified pointer or a "void *". Replace

481         PLACEHOLDER_EXPRs.  */

482      while (TREE_CODE (inner) == PLACEHOLDER_EXPR

483            || handled_component_p (inner))

484      {

485        if (TREE_CODE (inner) == PLACEHOLDER_EXPR)

486           inner = find_placeholder (inner, &placeholder_ptr);

487        else

488           inner = TREE_OPERAND (inner, 0);

489 

490        STRIP_NOPS (inner);

491      }

492 

493      /* Check for accesses through restrict-qualified pointers.  */

494      if (TREE_CODE (inner) == INDIRECT_REF)

495      {

496        tree decl = find_base_decl (TREE_OPERAND (inner, 0));

497 

498        if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))

499        {

500          /* If we haven't computed the actual alias set, do it now.  */

501          if (DECL_POINTER_ALIAS_SET (decl) == -2)

502          {

503            tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));

504 

505            /* No two restricted pointers can point at the same thing.

506                However, a restricted pointer can point at the same thing

507               as an unrestricted pointer, if that unrestricted pointer

508               is based on the restricted pointer. So, we make the

509               alias set for the restricted pointer a subset of the

510               alias set for the type pointed to by the type of the

511               decl.  */

512            HOST_WIDE_INT pointed_to_alias_set

513                = get_alias_set (pointed_to_type);

514 

515            if (pointed_to_alias_set == 0)

516              /* It's not legal to make a subset of alias set zero.  */

517              DECL_POINTER_ALIAS_SET (decl) = 0;

518            else if (AGGREGATE_TYPE_P (pointed_to_type))

519              /* For an aggregate, we must treat the restricted

520                 pointer the same as an ordinary pointer. If we

521                 were to make the type pointed to by the

522                 restricted pointer a subset of the pointed-to

523                 type, then we would believe that other subsets

524                 of the pointed-to type (such as fields of that

525                 type) do not conflict with the type pointed to

526                 by the restricted pointer.   */

527              DECL_POINTER_ALIAS_SET (decl)

528                   = pointed_to_alias_set;

529            else

530            {

531              DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();

532              record_alias_subset (pointed_to_alias_set,

533                               DECL_POINTER_ALIAS_SET (decl));

534            }

535          }

536 

537           /* We use the alias set indicated in the declaration.  */

538          return DECL_POINTER_ALIAS_SET (decl);

539        }

540 

541         /* If we have an INDIRECT_REF via a void pointer, we don't

542           know anything about what that might alias.  */

543        else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE)

544          return 0;

545      }

546 

547      /* Otherwise, pick up the outermost object that we could have a pointer

548         to, processing conversion and PLACEHOLDER_EXPR as above.  */

549      placeholder_ptr = 0;

550      while (TREE_CODE (t) == PLACEHOLDER_EXPR

551            || (handled_component_p (t) && ! can_address_p (t)))

552      {

553        if (TREE_CODE (t) == PLACEHOLDER_EXPR)

554          t = find_placeholder (t, &placeholder_ptr);

555        else

556          t = TREE_OPERAND (t, 0);

557 

558        STRIP_NOPS (t);

559      }

560 

561       /* If we've already determined the alias set for a decl, just return

562         it. This is necessary for C++ anonymous unions, whose component

563         variables don't look like union members (boo!).  */

564      if (TREE_CODE (t) == VAR_DECL

565         && DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)

566        return MEM_ALIAS_SET (DECL_RTL (t));

567 

568      /* Now all we care about is the type.  */

569      t = TREE_TYPE (t);

570    }

 

Above node of INDIRECT_REF in C++ language stands for an expression for a pointer or reference (for example, char *p;), clearly the alias set of the object referred is what we want. Thus find_base_decl finds the DECL on which this expression is based (For example, in `a[i]' this would be `a'). And if there is no such DECL, or a unique DECL cannot be determined, NULL_TREE is returned.

 

361  static tree

362  find_base_decl (tree t)                                                                                in alias.c

363  {

364    tree d0, d1, d2;

365 

366    if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))

367      return 0;

368 

369    /* If this is a declaration, return it.  */

370    if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')

371      return t;

372 

373    /* Handle general expressions. It would be nice to deal with

374      COMPONENT_REFs here. If we could tell that `a' and `b' were the

375      same, then `a->f' and `b->f' are also the same.  */

376    switch (TREE_CODE_CLASS (TREE_CODE (t)))

377    {

378      case '1':

379        return find_base_decl (TREE_OPERAND (t, 0));

380 

381      case '2':

382         /* Return 0 if found in neither or both are the same.  */

383        d0 = find_base_decl (TREE_OPERAND (t, 0));

384        d1 = find_base_decl (TREE_OPERAND (t, 1));

385        if (d0 == d1)

386          return d0;

387        else if (d0 == 0)

388          return d1;

389        else if (d1 == 0)

390          return d0;

391        else

392          return 0;

393 

394      case '3':

395        d0 = find_base_decl (TREE_OPERAND (t, 0));

396        d1 = find_base_decl (TREE_OPERAND (t, 1));

397        d2 = find_base_decl (TREE_OPERAND (t, 2));

398 

399        /* Set any nonzero values from the last, then from the first.  */

400        if (d1 == 0) d1 = d2;

401        if (d0 == 0) d0 = d1;

402        if (d1 == 0) d1 = d0;

403        if (d2 == 0) d2 = d1;

404 

405        /* At this point all are nonzero or all are zero. If all three are the

406          same, return it. Otherwise, return zero.  */

407        return (d0 == d1 && d1 == d2) ? d0 : 0;

408 

409      default :

410        return 0;

411    }

412  }

 

If we find the based DECL, back get_alias_set at line 498, if DECL_POINTER_ALIAS_SET doesn’t set with -1, DECL_POINTER_ALIAS_SET_KNOWN_P is true (-1 means the alias set for the declaration has not been yet computed). Further if DECL_POINTER_ALIAS_SET returns -2, it indicates that we need to make a unique alias set for this pointer (it is only applied to case of using GNU extension keyword restrict to restrict pointer alias, see c_apply_type_quals_to_decl ). It needs some special treatement.

The restrict pointer qualifier can be applied to a data pointer to indicate that, during the scope of that pointer declaration, all data accessed through it will be accessed only through that pointer but not through any other pointer. The __restrict__ keyword thus enables the compiler to perform certain optimizations based on the premise that a given object cannot be changed through another pointer. For example, declaration “int  f ( int  * restrict  x,  int  * restrict  y)” means changing the content of address pointed by pointer x can only via this pointer. So it is safe to compute alias set as below.

Then at line 503 in get_alias_set , here decl is the based DECL, it must have type of indirect type (pointer or reference), so pointed_to_type holds the type the indirect type refers to. Next get_alias_set invoked at line 512 recursively works out the alias set for the type. So at line 518, if pointed_to_type points to aggregate type, the alias set for this type should have been computed in the invocation at line 512, uses this alias set for the pointer (computing alias set for aggregate type is done by record_component_aliases , we will see it soon).

While if the pointer is not of aggregate type, it enters block at line 529 in get_alias_set , to be conservative but correct, combines all declarations pointed by pointer of this type into the same tree of alias set rooted by the pointer type (but note that the alias set of decl aliases nothing but it self, since it is delcared as “restrict”).

Then if it comes at line 549 in get_alias_set , because either inner is not INDIRECT_REF or its alias set is unknown. For the case, we get the alias set from its type.

Node of WITH_RECORD_EXPR and PLACEHOLDER_EXPR are used in languages that have types where some field in an object of the type contains a value that is used in the computation of another field's offset or size and/or the size of the type. The positions and/or sizes of fields can vary from object to object of the same type or even for one and the same object within its scope. Record types with discriminants in Ada or schema types in Pascal are examples of such types. For C++ front-end, we don’t need worry about these nodes.

 

get_alias_set (continue)

 

572    /* Variant qualifiers don't affect the alias set, so get the main

573      variant. If this is a type with a known alias set, return it.  */

574    t = TYPE_MAIN_VARIANT (t);

575    if (TYPE_ALIAS_SET_KNOWN_P (t))

576       return TYPE_ALIAS_SET (t);

577 

578    /* See if the language has special handling for this type.  */

579    set = (*lang_hooks . get_alias_set ) (t);

580    if (set != -1)

581      return set;

582 

583    /* There are no objects of FUNCTION_TYPE, so there's no point in

584      using up an alias set for them. (There are, of course, pointers

585      and references to functions, but that's different.)  */

586    else if (TREE_CODE (t) == FUNCTION_TYPE)

587      set = 0;

588 

589    /* Unless the language specifies otherwise, let vector types alias

590      their components. This avoids some nasty type punning issues in

591      normal usage. And indeed lets vectors be treated more like an

592      array slice.  */

593    else if (TREE_CODE (t) == VECTOR_TYPE)

594      set = get_alias_set (TREE_TYPE (t));

595 

596    else

597      /* Otherwise make a new alias set for this type.  */

598      set = new_alias_set ();

599 

600    TYPE_ALIAS_SET (t) = set;

601 

602    /* If this is an aggregate type, we must record any component aliasing

603      information.  */

604    if (AGGREGATE_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)

605      record_component_aliases (t);

606 

607    return set;

608  }

 

First, it sees if there is any suggestion from the language. Hook get_alias_set refers to cxx_get_alias_set below for C++.

Recall that for non-POD class, CLASSTYPE_AS_BASE is an RECORD_TYPE node with virtual bases stripped and its TYPE_CONTEXT refers to the RECORD_TYPE of the class, so predicate “CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t” is true if t is the node of CLASSTYPE_AS_BASE of non-POD class (while for POD class, CLASSTYPE_AS_BASE is the RECORD_TYPE of the class, so the mentioned predicate is false).

So condition at line 295 tells that t is enclosed within a class, and it is the base part of enclosing class.

 

292  static HOST_WIDE_INT

293  cxx_get_alias_set (tree t)                                                                            in cp-lang.c

294  {

295    if (TREE_CODE (t) == RECORD_TYPE

296        && TYPE_CONTEXT (t) && CLASS_TYPE_P (TYPE_CONTEXT (t))

297        && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)

298      /* The base variant of a type must be in the same alias set as the

299        complete type.  */

300      return get_alias_set (TYPE_CONTEXT (t));

301   

302    if (/* It's not yet safe to use alias sets for some classes in C++.  */

303      !ok_to_generate_alias_set_for_type (t)

304        /* Nor is it safe to use alias sets for pointers-to-member

305         functions, due to the fact that there may be more than one

306         RECORD_TYPE type corresponding to the same pointer-to-member

307         type.  */

308       || TYPE_PTRMEMFUNC_P (t))

309      return 0;

310 

311    return c_common_get_alias_set (t);

312  }

 

Then for the cases come at line 302, ok_to_generate_alias_set_for_type checks if the type is safe for aliasing.

First, class having virtual base is unsafe for aliasing. For example :

class A { ... };

class B : public virtual A { ... } ;

class C : public virtual A { ... } ;

class D : public B, C { ... } ;

Though D derives from B, in D the base B has different layout than class B even if B is empty class. Remember predicate CLASS_TYPE_P at line 250 is false for CLASSTYPE_AS_BASE of non-POD class.

Similarly, if a class contains a field of another class containing virtual base, it is unsafe to alias this type (both cases considered as may-alias).

 

239  static bool

240  ok_to_generate_alias_set_for_type (tree t)                                                    in cp-lang.c

241  {

242    if (TYPE_PTRMEMFUNC_P (t))

243      return true;

244    if (AGGREGATE_TYPE_P (t))

245    {

246      if ((TREE_CODE (t) == RECORD_TYPE) || (TREE_CODE (t) == UNION_TYPE))

247      {

248        tree fields;

249        /* Backend-created structs are safe.  */

250        if (! CLASS_TYPE_P (t))

251          return true;

252         /* PODs are safe.  */

253         if (! CLASSTYPE_NON_POD_P(t))

254          return true;

255         /* Classes with virtual baseclasses are not.  */

256        if (TYPE_USES_VIRTUAL_BASECLASSES (t))

257          return false;

258        /* Recursively check the base classes.  */

259        if (TYPE_BINFO (t) != NULL && TYPE_BINFO_BASETYPES (t) != NULL)

260        {

261          int i;

262          for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); i++)

263          {

264            tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);

265            if (!ok_to_generate_alias_set_for_type (BINFO_TYPE (binfo)))

266              return false;

267          }

268        }

269        /* Check all the fields.  */

270        for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))

271        {

272          if (TREE_CODE (fields) != FIELD_DECL)

273             continue ;

274          if (! ok_to_generate_alias_set_for_type (TREE_TYPE (fields)))

275            return false;

276        }

277        return true;

278      }

279      else if (TREE_CODE (t) == ARRAY_TYPE)

280        return ok_to_generate_alias_set_for_type (TREE_TYPE (t));

281      else

282        /* This should never happen, we dealt with all the aggregate

283          types that can appear in C++ above.  */

284        abort ();

285    }

286    else

287      return true;

288  }

 

Further considering following example:

extern "C" int printf(const char *,...);

class A {

protected  : int i ;

    public :

void f1 () { printf ("%d/n", i); }

        A () : i (0) {}

};

class B : public A {

    public :

void f1 () { printf ("%d/n", i); }

        B () { i = 2 ; }

};

int main () {

    void (A::*pf1) () = &A::f1;

    B b;

    (b.*pf1)();              // output “2”

    A a ;

    (a.*pf1)() ;      // output “0”

    return 0;

}

It prints out “2, 0”, no doubt pf1 accesses different objects in both times. So be careful in treating alias set for member pointer. Here such pointer is regarded as may-alias (line 308 in cxx_get_alias_set ).

Except the treatment of class, C++ front-end shares following routine with C front-end to handle types also available in C. First for direct accessing of union member, it aliases to the other members of the union. The comment of the case says that setting the field via taking address is not permitted in C standard and it has implementation-defined behave, [6] also gives an explaination.

-fstrict-aliasing

²        Allows the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C ++ ), this activates optimizations based on the type of expressions. In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. For example, an unsigned int can alias an int , but not a void* or a double . A character type may alias any other type.

Pay special attention to code like this:

union a_union {

int i;

double d;

};

int f() {

a_union t;

t.d = 3.0;

return t.i;

}

The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with ‘ -fstrict-aliasing ’, type-punning is allowed, provided the memory is accessed through the union type. So, the code above will work as expected. However, this code might not:

int f() {

a_union t;

int* ip;

t.d = 3.0;

ip = &t.i;

return *ip;

}

Similarly, access by taking the address, casting the resulting pointer and dereferencing the result has undefined behavior, even if the cast uses a union type, e.g.:

int f() {

double d = 3.0;

return ((union a_union *) &d)->i;

}

The ‘ -fstrict-aliasing ’ option is enabled at levels ‘ -O2 ’, ‘ -O3 ’, ‘ -Os ’.

Immediately in below, we will see an example of incorrect code generated out of type-punning. And that example can explain well why there may be undefined behavior. However, GCC give NO warning if we behave badly as above. Except this case, t of non-type is kicked off.

 

2848 HOST_WIDE_INT

2849 c_common_get_alias_set (tree t)                                                          n c-common.c

2850 {

2851   tree u;

2852

2853   /* Permit type-punning when accessing a union, provided the access

2854     is directly through the union. For example, this code does not

2855     permit taking the address of a union member and then storing

2856     through it. Even the type-punning allowed here is a GCC

2857     extension, albeit a common and useful one; the C standard says

2858     that such accesses have implementation-defined behavior.  */

2859   for (u = t;

2860        TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;

2861        u = TREE_OPERAND (u, 0))

2862     if (TREE_CODE (u) == COMPONENT_REF

2863        && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)

2864       return 0;

2865

2866   /* That's all the expressions we handle specially.  */

2867   if (! TYPE_P (t))

2868     return -1;

2869

2870   /* The C standard guarantees that any object may be accessed via an

2871     lvalue that has character type.  */

2872   if (t == char_type_node

2873       || t == signed_char_type_node

2874       || t == unsigned_char_type_node)

2875     return 0;

2876

2877   /* If it has the may_alias attribute, it can alias anything.  */

2878   if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))

2879     return 0;

2880

2881   /* The C standard specifically allows aliasing between signed and

2882     unsigned variants of the same type. We treat the signed

2883     variant as canonical.  */

2884   if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))

2885   {

2886     tree t1 = c_common_signed_type (t);

2887

2888     /* t1 == t can happen for boolean nodes which are always unsigned.  */

2889     if (t1 != t)

2890       return get_alias_set (t1);

2891   }

2892   else if (POINTER_TYPE_P (t))

2893   {

2894     tree t1;

2895

2896      /* Unfortunately, there is no canonical form of a pointer type.

2897       I n particular, if we have `typedef int I', then `int *', and

2898       `I *' are different types. So, we have to pick a canonical

2899       representative. We do this below.

2900

2901       Technically, this approach is actually more conservative that

2902       it needs to be. In particular, `const int *' and `int *'

2903       should be in different alias sets, according to the C and C++

2904       standard, since their types are not the same, and so,

2905       technically, an `int **' and `const int **' cannot point at

2906       the same thing.

2907

2908        But, the standard is wrong. In particular, this code is

2909       legal C++:

2910

2911          int *ip;

2912          int **ipp = &ip;

2913          const int* const* cipp = &ipp;

2914

2915       And, it doesn't make sense for that to be legal unless you

2916       can dereference IPP and CIPP. So, we ignore cv-qualifiers on

2917       the pointed-to types. This issue has been reported to the

2918       C++ committee.  */

2919     t1 = build_type_no_quals (t);

2920     if (t1 != t)

2921       return get_alias_set (t1);

2922   }

2923

2924   return -1;

2925 }

 

Above at line 2872, there are two case in fact would be covered. That is declaration like : char c; and char *pc; for the former case, c can’t alias other and no need create alias set (and consider the case of short type, it a group of 2 bytes, thus these two bytes can alias short type and must have alias set within the alias set of short, the front-end must prepare an alias set for this type as we see in the code), while rear one aliases any object that can be accessed via a lvalue. But for rear case, every time it points to specific object, it will get its alias set through block at line 494 in get_alias_set , and mayn’t be zero any more (it returns 0 for c style type cast).

At here, it is clear that declarations other than indirect reference (those pointer type or reference type) will share the alias set of their based type. For example : “short j , k, l; ”, in this statement, variables j, k, and l will have the same alias set of type short. However, the alias set will be ignored as these variables can’t alias each other. Now if we change the statement as : “short j, k, l, *p;”, now j, k, l and pointer p will share the alias set of short. So the front-end can know that p may alias to j, k or l.

Next consider statement “short j, k; char *p;”, j and k share the same alias set of short, but now p hasn’t alias set because get_alias_set (more precisely c_common_get_alias_set ) returns 0 for it. For this statement alone, the front-end won’t alias p to j or k. If we add a statement : “p = &j;”, in C++, it will trigger implicit conversion error. Then if we add instead a statement: “p = (char*)&j;”, alias set of p and j will be checked for intersection by front-end. It will pass since p has a superset of 0 (keep in mind there is no real superset of 0 created), and generate code for the conversion. However, the alias set of p always keeps as 0, which means it may-alias to everything can be accessed via lvalue. This assumption prevents compiler from taking error-prone too aggressive optimization. But it also a point as further improvement to discriminate alias set finer.

And at line 2884 above, integer types with difference signed also shares the same alias set.

Line 2878 mentions an interesting GNU C++ attribution “may_alias”. [6] gives a detail.

may_alias

²        Accesses through pointers to types with this attribute are NOT subject to type based alias analysis, but are instead assumed to be able to alias any other type of objects. In the context of 6.5/7 an lvalue expression dereferencing such a pointer is treated like having a character type. See ‘-fstrict-aliasing’ for more information on aliasing issues. This extension exists to support some vector APIs, in which pointers to one vector type are permitted to alias pointers to a different vector type. Note that an object of a type with this attribute does not have any special semantics. Example of use:

typedef short __attribute__ ((__may_alias__ )) short_a;

int main (void) {

int a = 0x12345678;

short_a *b = (short_a *) &a;

b[1] = 0;

if (a == 0x12345678)

abort();

exit(0);

}

If you replaced short_a with short in the variable declaration, the above program would abort when compiled with ‘-fstrict-aliasing’, which is on by default at ‘-O2’ or above in recent GCC versions.

In above example, in other words, replacing short_a with short generates incorrect code. However you can use –Wstrict-aliasing to find out pointer that may break the alias. For example, here with the option, the compiler gives a warning as : “test2.cpp:4: warning: dereferencing type-punned pointer will break strict-aliasing rules ”.

Then, if cxx_get_alias_set returns value other than -1, either the alias set is found, or the object can alias nothing (i.e, char type). Otherwise, it needs go ahead. See that at line 598 in get_alias_set , the type is assigned with unique alias set and will be shared by declarations of the type. And for aggregate type or type containing more than 1 component, the alias set should contain alias sets of its fields. Below function record_omponent_aliases builds the alias tree in this way. Predicate TYPE_NONALIASED_COMPONENT at line 709 if true, indicates that it is not permitted to take the address of a component of the type.

 

697  void

698  record_component_aliases (tree type)                                                           in alias.c

699  {

700    HOST_WIDE_INT superset = get_alias_set (type);

701    tree field;

702 

703    if (superset == 0)

704      return ;

705 

706    switch (TREE_CODE (type))

707    {

708      case ARRAY_TYPE:

709        if (! TYPE_NONALIASED_COMPONENT (type))

710          record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));

711        break ;

712 

713      case RECORD_TYPE:

714      case UNION_TYPE:

715      case QUAL_UNION_TYPE:

716        /* Recursively record aliases for the base classes, if there are any.  */

717        if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)

718        {

719          int i;

720          for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); i++)

721          {

722            tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);

723            record_alias_subset (superset,

724                             get_alias_set (BINFO_TYPE (binfo)));

725          }

726        }

727        for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))

728          if (TREE_CODE (field) == FIELD_DECL && ! DECL_NONADDRESSABLE_P (field))

729            record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));

730        break ;

731 

732      case COMPLEX_TYPE:

733         record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));

734        break ;

735 

736      default :

737        break ;

738    }

739  }

 

Notice that in the aggregate type, for example, field of type of short will use alias set of type short, which means it will share this alias set with other declarations of this type. By this way, if there is a pointer of short type, the compiler can tell that the pointer may alias to this field and other declarations, and prevent too heavy optimization.

;