LCOV - code coverage report
Current view: top level - gcc - ipa-polymorphic-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.7 % 1205 996
Test Date: 2026-02-28 14:20:25 Functions: 96.6 % 29 28
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Analysis of polymorphic call context.
       2              :    Copyright (C) 2013-2026 Free Software Foundation, Inc.
       3              :    Contributed by Jan Hubicka
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "gimple.h"
      28              : #include "tree-pass.h"
      29              : #include "tree-ssa-operands.h"
      30              : #include "streamer-hooks.h"
      31              : #include "cgraph.h"
      32              : #include "data-streamer.h"
      33              : #include "diagnostic.h"
      34              : #include "alias.h"
      35              : #include "fold-const.h"
      36              : #include "calls.h"
      37              : #include "ipa-utils.h"
      38              : #include "tree-dfa.h"
      39              : #include "gimple-pretty-print.h"
      40              : #include "tree-into-ssa.h"
      41              : #include "alloc-pool.h"
      42              : #include "symbol-summary.h"
      43              : #include "symtab-thunks.h"
      44              : 
      45              : /* Return true when TYPE contains an polymorphic type and thus is interesting
      46              :    for devirtualization machinery.  */
      47              : 
      48              : static bool contains_type_p (tree, HOST_WIDE_INT, tree,
      49              :                              bool consider_placement_new = true,
      50              :                              bool consider_bases = true);
      51              : 
      52              : bool
      53     37349632 : contains_polymorphic_type_p (const_tree type)
      54              : {
      55     42579159 :   type = TYPE_MAIN_VARIANT (type);
      56              : 
      57     42579159 :   if (RECORD_OR_UNION_TYPE_P (type))
      58              :     {
      59     10365646 :       if (TYPE_BINFO (type)
      60     10365646 :           && polymorphic_type_binfo_p (TYPE_BINFO (type)))
      61              :         return true;
      62    475411302 :       for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
      63    466746288 :         if (TREE_CODE (fld) == FIELD_DECL
      64     33207516 :             && !DECL_ARTIFICIAL (fld)
      65    497271964 :             && contains_polymorphic_type_p (TREE_TYPE (fld)))
      66              :           return true;
      67              :       return false;
      68              :     }
      69     32213513 :   if (TREE_CODE (type) == ARRAY_TYPE)
      70      5229527 :     return contains_polymorphic_type_p (TREE_TYPE (type));
      71              :   return false;
      72              : }
      73              : 
      74              : /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
      75              :    at position CUR_OFFSET within TYPE.
      76              : 
      77              :    POD can be changed to an instance of a polymorphic type by
      78              :    placement new.  Here we play safe and assume that any
      79              :    non-polymorphic type is POD.  */
      80              : bool
      81       131880 : possible_placement_new (tree type, tree expected_type,
      82              :                         HOST_WIDE_INT cur_offset)
      83              : {
      84       131880 :   if (cur_offset < 0)
      85              :     return true;
      86       128423 :   return ((TREE_CODE (type) != RECORD_TYPE
      87        20227 :            || !TYPE_BINFO (type)
      88        20259 :            || cur_offset >= POINTER_SIZE
      89        17961 :            || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
      90       148554 :           && (!TYPE_SIZE (type)
      91       128327 :               || !tree_fits_shwi_p (TYPE_SIZE (type))
      92       256654 :               || (cur_offset
      93       128327 :                   + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
      94       117187 :                      : POINTER_SIZE)
      95       128327 :                   <= tree_to_uhwi (TYPE_SIZE (type)))));
      96              : }
      97              : 
      98              : /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
      99              :    is contained at THIS->OFFSET.  Walk the memory representation of
     100              :    THIS->OUTER_TYPE and find the outermost class type that match
     101              :    OTR_TYPE or contain OTR_TYPE as a base.  Update THIS
     102              :    to represent it.
     103              : 
     104              :    If OTR_TYPE is NULL, just find outermost polymorphic type with
     105              :    virtual table present at position OFFSET.
     106              : 
     107              :    For example when THIS represents type
     108              :    class A
     109              :      {
     110              :        int a;
     111              :        class B b;
     112              :      }
     113              :    and we look for type at offset sizeof(int), we end up with B and offset 0.
     114              :    If the same is produced by multiple inheritance, we end up with A and offset
     115              :    sizeof(int).
     116              : 
     117              :    If we cannot find corresponding class, give up by setting
     118              :    THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL.
     119              :    Return true when lookup was successful.
     120              : 
     121              :    When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
     122              :    valid only via allocation of new polymorphic type inside by means
     123              :    of placement new.
     124              : 
     125              :    When CONSIDER_BASES is false, only look for actual fields, not base types
     126              :    of TYPE.  */
     127              : 
     128              : bool
     129      2333989 : ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
     130              :                                                        bool consider_placement_new,
     131              :                                                        bool consider_bases)
     132              : {
     133      2333989 :   tree type = outer_type;
     134      2333989 :   HOST_WIDE_INT cur_offset = offset;
     135      2333989 :   bool speculative = false;
     136      2333989 :   bool size_unknown = false;
     137      2333989 :   unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
     138              : 
     139              :   /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set.  */
     140      2333989 :   if (!outer_type)
     141              :     {
     142       138976 :       clear_outer_type (otr_type);
     143       138976 :       type = otr_type;
     144       138976 :       cur_offset = 0;
     145              :     }
     146              :  /* See if OFFSET points inside OUTER_TYPE.  If it does not, we know
     147              :     that the context is either invalid, or the instance type must be
     148              :     derived from OUTER_TYPE.
     149              : 
     150              :     Because the instance type may contain field whose type is of OUTER_TYPE,
     151              :     we cannot derive any effective information about it.
     152              : 
     153              :     TODO: In the case we know all derived types, we can definitely do better
     154              :     here.  */
     155      2195013 :   else if (TYPE_SIZE (outer_type)
     156      2194990 :            && tree_fits_shwi_p (TYPE_SIZE (outer_type))
     157      2194990 :            && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
     158      4390003 :            && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
     159              :    {
     160         4326 :      bool der = maybe_derived_type; /* clear_outer_type will reset it.  */
     161         4326 :      bool dyn = dynamic;
     162         4326 :      clear_outer_type (otr_type);
     163         4326 :      type = otr_type;
     164         4326 :      cur_offset = 0;
     165              : 
     166              :      /* If derived type is not allowed, we know that the context is invalid.
     167              :         For dynamic types, we really do not have information about
     168              :         size of the memory location.  It is possible that completely
     169              :         different type is stored after outer_type.  */
     170         4326 :      if (!der && !dyn)
     171              :        {
     172         2706 :          clear_speculation ();
     173         2706 :          invalid = true;
     174         2706 :          return false;
     175              :        }
     176              :    }
     177              : 
     178      2210146 :   if (otr_type && TYPE_SIZE (otr_type)
     179      4541424 :       && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
     180      2210141 :     otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
     181              : 
     182      2331283 :   if (!type || offset < 0)
     183         3457 :     goto no_useful_type_info;
     184              : 
     185              :   /* Find the sub-object the constant actually refers to and mark whether it is
     186              :      an artificial one (as opposed to a user-defined one).
     187              : 
     188              :      This loop is performed twice; first time for outer_type and second time
     189              :      for speculative_outer_type.  The second run has SPECULATIVE set.  */
     190      2930835 :   while (true)
     191              :     {
     192      2930835 :       unsigned HOST_WIDE_INT pos, size;
     193      2930835 :       tree fld;
     194              : 
     195              :       /* If we do not know size of TYPE, we need to be more conservative
     196              :          about accepting cases where we cannot find EXPECTED_TYPE.
     197              :          Generally the types that do matter here are of constant size.
     198              :          Size_unknown case should be very rare.  */
     199      2930835 :       if (TYPE_SIZE (type)
     200      2930812 :           && tree_fits_shwi_p (TYPE_SIZE (type))
     201      5861647 :           && tree_to_shwi (TYPE_SIZE (type)) >= 0)
     202              :         size_unknown = false;
     203              :       else
     204              :         size_unknown = true;
     205              : 
     206              :       /* On a match, just return what we found.  */
     207      2930835 :       if ((otr_type
     208      2529595 :            && types_odr_comparable (type, otr_type)
     209      2529595 :            && types_same_for_odr (type, otr_type))
     210      2930835 :           || (!otr_type
     211       401240 :               && TREE_CODE (type) == RECORD_TYPE
     212       303863 :               && TYPE_BINFO (type)
     213       303147 :               && polymorphic_type_binfo_p (TYPE_BINFO (type))))
     214              :         {
     215      1815503 :           if (speculative)
     216              :             {
     217              :               /* If we did not match the offset, just give up on speculation.  */
     218         9315 :               if (cur_offset != 0
     219              :                   /* Also check if speculation did not end up being same as
     220              :                      non-speculation.  */
     221         9315 :                   || (types_must_be_same_for_odr (speculative_outer_type,
     222              :                                                   outer_type)
     223           38 :                       && (maybe_derived_type
     224           38 :                           == speculative_maybe_derived_type)))
     225            0 :                 clear_speculation ();
     226         9315 :               return true;
     227              :             }
     228              :           else
     229              :             {
     230              :               /* If type is known to be final, do not worry about derived
     231              :                  types.  Testing it here may help us to avoid speculation.  */
     232      1803745 :               if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
     233      1803745 :                   && (!in_lto_p || odr_type_p (outer_type))
     234      1803745 :                   && type_with_linkage_p (outer_type)
     235      3609933 :                   && type_known_to_have_no_derivations_p (outer_type))
     236         8311 :                 maybe_derived_type = false;
     237              : 
     238              :               /* Type cannot contain itself on an non-zero offset.  In that case
     239              :                  just give up.  Still accept the case where size is now known.
     240              :                  Either the second copy may appear past the end of type or within
     241              :                  the non-POD buffer located inside the variably sized type
     242              :                  itself.  */
     243      1806188 :               if (cur_offset != 0)
     244         1919 :                 goto no_useful_type_info;
     245              :               /* If we determined type precisely or we have no clue on
     246              :                  speculation, we are done.  */
     247      1433007 :               if (!maybe_derived_type || !speculative_outer_type
     248      1944951 :                   || !speculation_consistent_p (speculative_outer_type,
     249              :                                                 speculative_offset,
     250              :                                                 speculative_maybe_derived_type,
     251              :                                                 otr_type))
     252              :                 {
     253      1794958 :                   clear_speculation ();
     254      1794958 :                   return true;
     255              :                 }
     256              :               /* Otherwise look into speculation now.  */
     257              :               else
     258              :                 {
     259         9311 :                   speculative = true;
     260         9311 :                   type = speculative_outer_type;
     261         9311 :                   cur_offset = speculative_offset;
     262         9311 :                   continue;
     263              :                 }
     264              :             }
     265              :         }
     266              : 
     267              :       /* Walk fields and find corresponding on at OFFSET.  */
     268      1115332 :       if (TREE_CODE (type) == RECORD_TYPE)
     269              :         {
     270     15784144 :           for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
     271              :             {
     272     29402953 :               if (TREE_CODE (fld) != FIELD_DECL
     273     15513739 :                   || TREE_TYPE (fld) == error_mark_node)
     274     13889214 :                 continue;
     275              : 
     276      1624525 :               pos = int_bit_position (fld);
     277      1624525 :               if (pos > (unsigned HOST_WIDE_INT)cur_offset)
     278       407736 :                 continue;
     279              : 
     280              :               /* Do not consider vptr itself.  Not even for placement new.  */
     281      1182327 :               if (!pos && DECL_ARTIFICIAL (fld)
     282       939632 :                   && POINTER_TYPE_P (TREE_TYPE (fld))
     283       185742 :                   && TYPE_BINFO (type)
     284      1402531 :                   && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     285       185742 :                 continue;
     286              : 
     287      1031047 :               if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
     288            0 :                 goto no_useful_type_info;
     289      1031047 :               size = tree_to_uhwi (DECL_SIZE (fld));
     290              : 
     291              :               /* We can always skip types smaller than pointer size:
     292              :                  those cannot contain a virtual table pointer.
     293              : 
     294              :                  Disqualifying fields that are too small to fit OTR_TYPE
     295              :                  saves work needed to walk them for no benefit.
     296              :                  Because of the way the bases are packed into a class, the
     297              :                  field's size may be smaller than type size, so it needs
     298              :                  to be done with a care.  */
     299              : 
     300      1031047 :               if (pos <= (unsigned HOST_WIDE_INT)cur_offset
     301      2062094 :                   && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
     302      1052276 :                                      + POINTER_SIZE
     303       803161 :                   && (!otr_type
     304       519632 :                       || !TYPE_SIZE (TREE_TYPE (fld))
     305       519632 :                       || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
     306       519632 :                       || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
     307       519632 :                           >= cur_offset + otr_type_size))
     308              :                 break;
     309              :             }
     310              : 
     311      1006786 :           if (!fld)
     312       270405 :             goto no_useful_type_info;
     313              : 
     314       736381 :           type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
     315       736381 :           cur_offset -= pos;
     316              :           /* DECL_ARTIFICIAL represents a basetype.  */
     317       736381 :           if (!DECL_ARTIFICIAL (fld))
     318              :             {
     319       253207 :               if (!speculative)
     320              :                 {
     321       252811 :                   outer_type = type;
     322       252811 :                   offset = cur_offset;
     323              :                   /* As soon as we see an field containing the type,
     324              :                      we know we are not looking for derivations.  */
     325       252811 :                   maybe_derived_type = false;
     326              :                 }
     327              :               else
     328              :                 {
     329          396 :                   speculative_outer_type = type;
     330          396 :                   speculative_offset = cur_offset;
     331          396 :                   speculative_maybe_derived_type = false;
     332              :                 }
     333              :             }
     334       483174 :           else if (!consider_bases)
     335       142713 :             goto no_useful_type_info;
     336              :         }
     337       108546 :       else if (TREE_CODE (type) == ARRAY_TYPE)
     338              :         {
     339        10885 :           tree subtype = TYPE_MAIN_VARIANT (TREE_TYPE (type));
     340              : 
     341              :           /* Give up if we don't know array field size.
     342              :              Also give up on non-polymorphic types as they are used
     343              :              as buffers for placement new.  */
     344        10885 :           if (!TYPE_SIZE (subtype)
     345        10885 :               || !tree_fits_shwi_p (TYPE_SIZE (subtype))
     346        10885 :               || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
     347        21770 :               || !contains_polymorphic_type_p (subtype))
     348        10502 :             goto no_useful_type_info;
     349              : 
     350          383 :           HOST_WIDE_INT new_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
     351              : 
     352              :           /* We may see buffer for placement new.  In this case the expected type
     353              :              can be bigger than the subtype.  */
     354          383 :           if (TYPE_SIZE (subtype)
     355          383 :               && (cur_offset + otr_type_size
     356          383 :                   > tree_to_uhwi (TYPE_SIZE (subtype))))
     357          357 :             goto no_useful_type_info;
     358              : 
     359           26 :           cur_offset = new_offset;
     360           26 :           type = TYPE_MAIN_VARIANT (subtype);
     361           26 :           if (!speculative)
     362              :             {
     363           26 :               outer_type = type;
     364           26 :               offset = cur_offset;
     365           26 :               maybe_derived_type = false;
     366              :             }
     367              :           else
     368              :             {
     369            0 :               speculative_outer_type = type;
     370            0 :               speculative_offset = cur_offset;
     371            0 :               speculative_maybe_derived_type = false;
     372              :             }
     373              :         }
     374              :       /* Give up on anything else.  */
     375              :       else
     376              :         {
     377        97661 : no_useful_type_info:
     378          336 :           if (maybe_derived_type && !speculative
     379          336 :               && TREE_CODE (outer_type) == RECORD_TYPE
     380          336 :               && TREE_CODE (otr_type) == RECORD_TYPE
     381          336 :               && TYPE_BINFO (otr_type)
     382          336 :               && !offset
     383       527350 :               && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
     384              :             {
     385          336 :               clear_outer_type (otr_type);
     386          336 :               if (!speculative_outer_type
     387          336 :                   || !speculation_consistent_p (speculative_outer_type,
     388              :                                                 speculative_offset,
     389            0 :                                                 speculative_maybe_derived_type,
     390              :                                                 otr_type))
     391          336 :                 clear_speculation ();
     392          336 :               if (speculative_outer_type)
     393              :                 {
     394            0 :                   speculative = true;
     395            0 :                   type = speculative_outer_type;
     396            0 :                   cur_offset = speculative_offset;
     397              :                 }
     398              :               else
     399              :                 return true;
     400              :             }
     401              :           /* We found no way to embed EXPECTED_TYPE in TYPE.
     402              :              We still permit two special cases - placement new and
     403              :              the case of variadic types containing themselves.  */
     404       526678 :           if (!speculative
     405       526678 :               && consider_placement_new
     406       526678 :               && (size_unknown || !type || maybe_derived_type
     407       131880 :                   || possible_placement_new (type, otr_type, cur_offset)))
     408              :             {
     409              :               /* In these weird cases we want to accept the context.
     410              :                  In non-speculative run we have no useful outer_type info
     411              :                  (TODO: we may eventually want to record upper bound on the
     412              :                   type size that can be used to prune the walk),
     413              :                  but we still want to consider speculation that may
     414              :                  give useful info.  */
     415       129760 :               if (!speculative)
     416              :                 {
     417       129760 :                   clear_outer_type (otr_type);
     418       129760 :                   if (!speculative_outer_type
     419       129766 :                       || !speculation_consistent_p (speculative_outer_type,
     420              :                                                     speculative_offset,
     421            6 :                                                     speculative_maybe_derived_type,
     422              :                                                     otr_type))
     423       129756 :                     clear_speculation ();
     424       129760 :                   if (speculative_outer_type)
     425              :                     {
     426            4 :                       speculative = true;
     427            4 :                       type = speculative_outer_type;
     428            4 :                       cur_offset = speculative_offset;
     429              :                     }
     430              :                   else
     431              :                     return true;
     432              :                 }
     433              :               else
     434              :                 {
     435              :                   clear_speculation ();
     436              :                   return true;
     437              :                 }
     438              :             }
     439              :           else
     440              :             {
     441       396918 :               clear_speculation ();
     442       396918 :               if (speculative)
     443              :                 return true;
     444       396918 :               clear_outer_type (otr_type);
     445       396918 :               invalid = true;
     446       396918 :               return false;
     447              :             }
     448              :         }
     449              :     }
     450              : }
     451              : 
     452              : /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
     453              :    CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
     454              :    be built within OUTER_TYPE by means of placement new.  CONSIDER_BASES makes
     455              :    function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
     456              :    base of one of fields of OUTER_TYPE.  */
     457              : 
     458              : static bool
     459       727313 : contains_type_p (tree outer_type, HOST_WIDE_INT offset,
     460              :                  tree otr_type,
     461              :                  bool consider_placement_new,
     462              :                  bool consider_bases)
     463              : {
     464       727313 :   ipa_polymorphic_call_context context;
     465              : 
     466              :   /* Check that type is within range.  */
     467       727313 :   if (offset < 0)
     468              :     return false;
     469              : 
     470              :   /* PR ipa/71207
     471              :      As OUTER_TYPE can be a type which has a diamond virtual inheritance,
     472              :      it's not necessary that INNER_TYPE will fit within OUTER_TYPE with
     473              :      a given offset.  It can happen that INNER_TYPE also contains a base object,
     474              :      however it would point to the same instance in the OUTER_TYPE.  */
     475              : 
     476       721115 :   context.offset = offset;
     477       721115 :   context.outer_type = TYPE_MAIN_VARIANT (outer_type);
     478       721115 :   context.maybe_derived_type = false;
     479       721115 :   context.dynamic = false;
     480       721115 :   return context.restrict_to_inner_class (otr_type, consider_placement_new,
     481       721115 :                                           consider_bases);
     482              : }
     483              : 
     484              : 
     485              : /* Return a FUNCTION_DECL if FN represent a constructor or destructor.
     486              :    If CHECK_CLONES is true, also check for clones of ctor/dtors.  */
     487              : 
     488              : tree
     489     63520805 : polymorphic_ctor_dtor_p (tree fn, bool check_clones)
     490              : {
     491     63520805 :   if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     492    105245899 :       || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     493              :     {
     494     45518021 :       if (!check_clones)
     495              :         return NULL_TREE;
     496              : 
     497              :       /* Watch for clones where we constant propagated the first
     498              :          argument (pointer to the instance).  */
     499     45473826 :       fn = DECL_ABSTRACT_ORIGIN (fn);
     500     45473826 :       if (!fn
     501     32697758 :           || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
     502     66180690 :           || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
     503              :         return NULL_TREE;
     504              :     }
     505              : 
     506     18003095 :   if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
     507              :     return NULL_TREE;
     508              : 
     509              :   return fn;
     510              : }
     511              : 
     512              : /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
     513              :    If CHECK_CLONES is true, also check for clones of ctor/dtors.  */
     514              : 
     515              : tree
     516    177735241 : inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
     517              : {
     518    177735241 :   tree fn = block_ultimate_origin (block);
     519    177735241 :   if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
     520              :     return NULL_TREE;
     521              : 
     522     51970980 :   return polymorphic_ctor_dtor_p (fn, check_clones);
     523              : }
     524              : 
     525              : 
     526              : /* We know that the instance is stored in variable or parameter
     527              :    (not dynamically allocated) and we want to disprove the fact
     528              :    that it may be in construction at invocation of CALL.
     529              : 
     530              :    BASE represents memory location where instance is stored.
     531              :    If BASE is NULL, it is assumed to be global memory.
     532              :    OUTER_TYPE is known type of the instance or NULL if not
     533              :    known.
     534              : 
     535              :    For the variable to be in construction we actually need to
     536              :    be in constructor of corresponding global variable or
     537              :    the inline stack of CALL must contain the constructor.
     538              :    Check this condition.  This check works safely only before
     539              :    IPA passes, because inline stacks may become out of date
     540              :    later.  */
     541              : 
     542              : bool
     543     29592577 : decl_maybe_in_construction_p (tree base, tree outer_type,
     544              :                               gimple *call, tree function)
     545              : {
     546     29592577 :   if (outer_type)
     547        45809 :     outer_type = TYPE_MAIN_VARIANT (outer_type);
     548     29592577 :   gcc_assert (!base || DECL_P (base));
     549              : 
     550              :   /* After inlining the code unification optimizations may invalidate
     551              :      inline stacks.  Also we need to give up on global variables after
     552              :      IPA, because addresses of these may have been propagated to their
     553              :      constructors.  */
     554     29592577 :   if (DECL_STRUCT_FUNCTION (function)->after_inlining)
     555              :     return true;
     556              : 
     557              :   /* Pure functions cannot do any changes on the dynamic type;
     558              :      that require writing to memory.  */
     559        36816 :   if ((!base || !auto_var_in_fn_p (base, function))
     560     29555299 :       && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
     561              :     return false;
     562              : 
     563     29232072 :   bool check_clones = !base || is_global_var (base);
     564    153601726 :   for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
     565     62184827 :        block = BLOCK_SUPERCONTEXT (block))
     566     62212190 :     if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
     567              :       {
     568       338305 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
     569              : 
     570       338305 :         if (!outer_type || !types_odr_comparable (type, outer_type))
     571              :           {
     572       329257 :             if (TREE_CODE (type) == RECORD_TYPE
     573       327813 :                 && TYPE_BINFO (type)
     574       654611 :                 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     575              :               return true;
     576              :           }
     577         9048 :         else if (types_same_for_odr (type, outer_type))
     578              :           return true;
     579              :       }
     580              : 
     581     29204709 :   if (!base || (VAR_P (base) && is_global_var (base)))
     582              :     {
     583     29178117 :       if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     584     37185204 :           || (!DECL_CXX_CONSTRUCTOR_P (function)
     585      6756681 :               && !DECL_CXX_DESTRUCTOR_P (function)))
     586              :         {
     587     27415175 :           if (!DECL_ABSTRACT_ORIGIN (function))
     588              :             return false;
     589              :           /* Watch for clones where we constant propagated the first
     590              :              argument (pointer to the instance).  */
     591        85312 :           function = DECL_ABSTRACT_ORIGIN (function);
     592        85312 :           if (!function
     593        85312 :               || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
     594       132639 :               || (!DECL_CXX_CONSTRUCTOR_P (function)
     595        47295 :                   && !DECL_CXX_DESTRUCTOR_P (function)))
     596              :             return false;
     597              :         }
     598      1762974 :       tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
     599      1762974 :       if (!outer_type || !types_odr_comparable (type, outer_type))
     600              :         {
     601      1762938 :           if (TREE_CODE (type) == RECORD_TYPE
     602      1761608 :               && TYPE_BINFO (type)
     603      3515946 :               && polymorphic_type_binfo_p (TYPE_BINFO (type)))
     604              :             return true;
     605              :         }
     606           36 :       else if (types_same_for_odr (type, outer_type))
     607              :         return true;
     608              :     }
     609              :   return false;
     610              : }
     611              : 
     612              : /* Dump human readable context to F.  If NEWLINE is true, it will be terminated
     613              :    by a newline.  */
     614              : 
     615              : void
     616         1411 : ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
     617              : {
     618         1411 :   fprintf (f, "    ");
     619         1411 :   if (invalid)
     620            0 :     fprintf (f, "Call is known to be undefined");
     621              :   else
     622              :     {
     623         1411 :       if (useless_p ())
     624            1 :         fprintf (f, "nothing known");
     625         1411 :       if (outer_type || offset)
     626              :         {
     627         1600 :           fprintf (f, "Outer type%s:", dynamic ? " (dynamic)" : "");
     628         1247 :           print_generic_expr (f, outer_type, TDF_SLIM);
     629         1247 :           if (maybe_derived_type)
     630          737 :             fprintf (f, " (or a derived type)");
     631         1247 :           if (maybe_in_construction)
     632          190 :             fprintf (f, " (maybe in construction)");
     633         1247 :           fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
     634         1247 :                    offset);
     635              :         }
     636         1411 :       if (speculative_outer_type)
     637              :         {
     638          306 :           if (outer_type || offset)
     639          143 :             fprintf (f, " ");
     640          306 :           fprintf (f, "Speculative outer type:");
     641          306 :           print_generic_expr (f, speculative_outer_type, TDF_SLIM);
     642          306 :           if (speculative_maybe_derived_type)
     643          273 :             fprintf (f, " (or a derived type)");
     644          306 :           fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
     645          306 :                    speculative_offset);
     646              :         }
     647              :     }
     648         1411 :   if (newline)
     649          685 :     fprintf(f, "\n");
     650         1411 : }
     651              : 
     652              : /* Print context to stderr.  */
     653              : 
     654              : void
     655            0 : ipa_polymorphic_call_context::debug () const
     656              : {
     657            0 :   dump (stderr);
     658            0 : }
     659              : 
     660              : /* Stream out the context to OB.  */
     661              : 
     662              : void
     663         4616 : ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
     664              : {
     665         4616 :   struct bitpack_d bp = bitpack_create (ob->main_stream);
     666              : 
     667         4616 :   bp_pack_value (&bp, invalid, 1);
     668         4616 :   bp_pack_value (&bp, maybe_in_construction, 1);
     669         4616 :   bp_pack_value (&bp, maybe_derived_type, 1);
     670         4616 :   bp_pack_value (&bp, speculative_maybe_derived_type, 1);
     671         4616 :   bp_pack_value (&bp, dynamic, 1);
     672         4616 :   bp_pack_value (&bp, outer_type != NULL, 1);
     673         4616 :   bp_pack_value (&bp, offset != 0, 1);
     674         4616 :   bp_pack_value (&bp, speculative_outer_type != NULL, 1);
     675         4616 :   streamer_write_bitpack (&bp);
     676              : 
     677         4616 :   if (outer_type != NULL)
     678         2255 :     stream_write_tree (ob, outer_type, true);
     679         4616 :   if (offset)
     680          547 :     streamer_write_hwi (ob, offset);
     681         4616 :   if (speculative_outer_type != NULL)
     682              :     {
     683         1695 :       stream_write_tree (ob, speculative_outer_type, true);
     684         1695 :       streamer_write_hwi (ob, speculative_offset);
     685              :     }
     686              :   else
     687         2921 :     gcc_assert (!speculative_offset);
     688         4616 : }
     689              : 
     690              : /* Stream in the context from IB and DATA_IN.  */
     691              : 
     692              : void
     693         1377 : ipa_polymorphic_call_context::stream_in (class lto_input_block *ib,
     694              :                                          class data_in *data_in)
     695              : {
     696         1377 :   struct bitpack_d bp = streamer_read_bitpack (ib);
     697              : 
     698         1377 :   invalid = bp_unpack_value (&bp, 1);
     699         1377 :   maybe_in_construction = bp_unpack_value (&bp, 1);
     700         1377 :   maybe_derived_type = bp_unpack_value (&bp, 1);
     701         1377 :   speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
     702         1377 :   dynamic = bp_unpack_value (&bp, 1);
     703         1377 :   bool outer_type_p = bp_unpack_value (&bp, 1);
     704         1377 :   bool offset_p = bp_unpack_value (&bp, 1);
     705         1377 :   bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
     706              : 
     707         1377 :   if (outer_type_p)
     708          669 :     outer_type = stream_read_tree (ib, data_in);
     709              :   else
     710          708 :     outer_type = NULL;
     711         1377 :   if (offset_p)
     712          384 :     offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     713              :   else
     714          993 :     offset = 0;
     715         1377 :   if (speculative_outer_type_p)
     716              :     {
     717          516 :       speculative_outer_type = stream_read_tree (ib, data_in);
     718          516 :       speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
     719              :     }
     720              :   else
     721              :     {
     722          861 :       speculative_outer_type = NULL;
     723          861 :       speculative_offset = 0;
     724              :     }
     725         1377 : }
     726              : 
     727              : /* Produce polymorphic call context for call method of instance
     728              :    that is located within BASE (that is assumed to be a decl) at offset OFF. */
     729              : 
     730              : void
     731      1262725 : ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
     732              : {
     733      1262725 :   gcc_assert (DECL_P (base));
     734      1262725 :   clear_speculation ();
     735              : 
     736      1262725 :   if (!contains_polymorphic_type_p (TREE_TYPE (base)))
     737              :     {
     738      1215784 :       clear_outer_type ();
     739      1215784 :       offset = off;
     740      1215784 :       return;
     741              :     }
     742        46941 :   outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
     743        46941 :   offset = off;
     744              :   /* Make very conservative assumption that all objects
     745              :      may be in construction.
     746              : 
     747              :      It is up to caller to revisit this via
     748              :      get_dynamic_type or decl_maybe_in_construction_p.  */
     749        46941 :   maybe_in_construction = true;
     750        46941 :   maybe_derived_type = false;
     751        46941 :   dynamic = false;
     752              : }
     753              : 
     754              : /* CST is an invariant (address of decl), try to get meaningful
     755              :    polymorphic call context for polymorphic call of method
     756              :    if instance of OTR_TYPE that is located at offset OFF of this invariant.
     757              :    Return FALSE if nothing meaningful can be found.  */
     758              : 
     759              : bool
     760        13161 : ipa_polymorphic_call_context::set_by_invariant (tree cst,
     761              :                                                 tree otr_type,
     762              :                                                 HOST_WIDE_INT off)
     763              : {
     764        13161 :   poly_int64 offset2, size, max_size;
     765        13161 :   bool reverse;
     766        13161 :   tree base;
     767              : 
     768        13161 :   invalid = false;
     769        13161 :   clear_outer_type (otr_type);
     770              : 
     771        13161 :   if (TREE_CODE (cst) != ADDR_EXPR)
     772              :     return false;
     773              : 
     774         3701 :   cst = TREE_OPERAND (cst, 0);
     775         3701 :   base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
     776         3701 :   if (!DECL_P (base) || !known_size_p (max_size) || maybe_ne (max_size, size))
     777              :     return false;
     778              : 
     779              :   /* Only type inconsistent programs can have otr_type that is
     780              :      not part of outer type.  */
     781         3692 :   if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
     782              :     return false;
     783              : 
     784         2653 :   set_by_decl (base, off);
     785         2653 :   return true;
     786              : }
     787              : 
     788              : /* See if OP is SSA name initialized as a copy or by single assignment.
     789              :    If so, walk the SSA graph up.  Because simple PHI conditional is considered
     790              :    copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
     791              :    graph.  */
     792              : 
     793              : static tree
     794      6830969 : walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
     795              : {
     796      6830969 :   hash_set <tree> *visited = NULL;
     797      6830969 :   STRIP_NOPS (op);
     798      6830969 :   while (TREE_CODE (op) == SSA_NAME
     799      3429215 :          && !SSA_NAME_IS_DEFAULT_DEF (op)
     800              :          /* We might be called via fold_stmt during cfgcleanup where
     801              :             SSA form need not be up-to-date.  */
     802      2371617 :          && !name_registered_for_update_p (op)
     803      9644816 :          && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
     804       492609 :              || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
     805              :     {
     806      2024824 :       if (global_visited)
     807              :         {
     808      1344953 :           if (!*global_visited)
     809      1261928 :             *global_visited = new hash_set<tree>;
     810      1344953 :           if ((*global_visited)->add (op))
     811            0 :             goto done;
     812              :         }
     813              :       else
     814              :         {
     815       679871 :           if (!visited)
     816       662699 :             visited = new hash_set<tree>;
     817       679871 :           if (visited->add (op))
     818            0 :             goto done;
     819              :         }
     820              :       /* Special case
     821              :          if (ptr == 0)
     822              :            ptr = 0;
     823              :          else
     824              :            ptr = ptr.foo;
     825              :          This pattern is implicitly produced for casts to non-primary
     826              :          bases.  When doing context analysis, we do not really care
     827              :          about the case pointer is NULL, because the call will be
     828              :          undefined anyway.  */
     829      2024824 :       if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
     830              :         {
     831       145816 :           gimple *phi = SSA_NAME_DEF_STMT (op);
     832              : 
     833       145816 :           if (gimple_phi_num_args (phi) > 2)
     834        33023 :             goto done;
     835       112793 :           if (gimple_phi_num_args (phi) == 1)
     836          821 :             op = gimple_phi_arg_def (phi, 0);
     837       111972 :           else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
     838         5148 :             op = gimple_phi_arg_def (phi, 1);
     839       106824 :           else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
     840        19524 :             op = gimple_phi_arg_def (phi, 0);
     841              :           else
     842        87300 :             goto done;
     843              :         }
     844              :       else
     845              :         {
     846      1879008 :           if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
     847      1462271 :             goto done;
     848       416737 :           op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
     849              :         }
     850       442230 :       STRIP_NOPS (op);
     851              :     }
     852      6830969 : done:
     853      6830969 :   if (visited)
     854       662699 :     delete (visited);
     855      6830969 :   return op;
     856              : }
     857              : 
     858              : /* Create polymorphic call context from IP invariant CST.
     859              :    This is typically &global_var.
     860              :    OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
     861              :    is offset of call.  */
     862              : 
     863        13161 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
     864              :                                                             tree otr_type,
     865        13161 :                                                             HOST_WIDE_INT off)
     866              : {
     867        13161 :   clear_speculation ();
     868        13161 :   set_by_invariant (cst, otr_type, off);
     869        13161 : }
     870              : 
     871              : /* Build context for pointer REF contained in FNDECL at statement STMT.
     872              :    if INSTANCE is non-NULL, return pointer to the object described by
     873              :    the context or DECL where context is contained in.  */
     874              : 
     875      4137508 : ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
     876              :                                                             tree ref,
     877              :                                                             gimple *stmt,
     878      4137508 :                                                             tree *instance)
     879              : {
     880      4137508 :   tree otr_type = NULL;
     881      4137508 :   tree base_pointer;
     882      4137508 :   hash_set <tree> *visited = NULL;
     883              : 
     884      4137508 :   if (TREE_CODE (ref) == OBJ_TYPE_REF)
     885              :     {
     886       938213 :       otr_type = obj_type_ref_class (ref);
     887       938213 :       base_pointer = OBJ_TYPE_REF_OBJECT (ref);
     888              :     }
     889              :   else
     890              :     base_pointer = ref;
     891              : 
     892              :   /* Set up basic info in case we find nothing interesting in the analysis.  */
     893      4137508 :   clear_speculation ();
     894      4137508 :   clear_outer_type (otr_type);
     895      4137508 :   invalid = false;
     896              : 
     897              :   /* Walk SSA for outer object.  */
     898      4417070 :   while (true)
     899              :     {
     900      4417070 :       base_pointer = walk_ssa_copies (base_pointer, &visited);
     901      4417070 :       if (TREE_CODE (base_pointer) == ADDR_EXPR)
     902              :         {
     903      1965413 :           HOST_WIDE_INT offset2, size;
     904      1965413 :           bool reverse;
     905      1965413 :           tree base
     906      1965413 :             = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
     907              :                                            &offset2, &size, &reverse);
     908      1965413 :           if (!base)
     909              :             break;
     910              : 
     911      1942351 :           combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
     912      1942351 :                                     offset + offset2,
     913              :                                     true,
     914              :                                     NULL /* Do not change outer type.  */);
     915              : 
     916              :           /* If this is a varying address, punt.  */
     917      1942351 :           if (TREE_CODE (base) == MEM_REF || DECL_P (base))
     918              :             {
     919              :               /* We found dereference of a pointer.  Type of the pointer
     920              :                  and MEM_REF is meaningless, but we can look further.  */
     921      1539642 :               offset_int mem_offset;
     922      1539642 :               if (TREE_CODE (base) == MEM_REF
     923      1539642 :                   && mem_ref_offset (base).is_constant (&mem_offset))
     924              :                 {
     925       279570 :                   offset_int o = mem_offset * BITS_PER_UNIT;
     926       279570 :                   o += offset;
     927       279570 :                   o += offset2;
     928       279570 :                   if (!wi::fits_shwi_p (o))
     929              :                     break;
     930       279562 :                   base_pointer = TREE_OPERAND (base, 0);
     931       279562 :                   offset = o.to_shwi ();
     932       279562 :                   outer_type = NULL;
     933              :                 }
     934              :               /* We found base object.  In this case the outer_type
     935              :                  is known.  */
     936      1260072 :               else if (DECL_P (base))
     937              :                 {
     938      1260072 :                   if (visited)
     939          712 :                     delete (visited);
     940              :                   /* Only type inconsistent programs can have otr_type that is
     941              :                      not part of outer type.  */
     942      1260072 :                   if (otr_type
     943      1274230 :                       && !contains_type_p (TREE_TYPE (base),
     944        14158 :                                            offset + offset2, otr_type))
     945              :                     {
     946            0 :                       invalid = true;
     947            0 :                       if (instance)
     948            0 :                         *instance = base_pointer;
     949      1260072 :                       return;
     950              :                     }
     951      1260072 :                   set_by_decl (base, offset + offset2);
     952      1260072 :                   if (outer_type && maybe_in_construction && stmt)
     953        45809 :                     maybe_in_construction
     954        45809 :                      = decl_maybe_in_construction_p (base,
     955              :                                                      outer_type,
     956              :                                                      stmt,
     957              :                                                      fndecl);
     958      1260072 :                   if (instance)
     959      1249870 :                     *instance = base;
     960      1260072 :                   return;
     961              :                 }
     962              :               else
     963              :                 break;
     964              :             }
     965              :           else
     966              :             break;
     967              :         }
     968      2451657 :       else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
     969      2451657 :                && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
     970              :         {
     971            0 :           offset_int o
     972            0 :             = offset_int::from (wi::to_wide (TREE_OPERAND (base_pointer, 1)),
     973              :                                 SIGNED);
     974            0 :           o *= BITS_PER_UNIT;
     975            0 :           o += offset;
     976            0 :           if (!wi::fits_shwi_p (o))
     977              :             break;
     978            0 :           offset = o.to_shwi ();
     979            0 :           base_pointer = TREE_OPERAND (base_pointer, 0);
     980              :         }
     981              :       else
     982              :         break;
     983              :     }
     984              : 
     985      2877436 :   if (visited)
     986      1261216 :     delete (visited);
     987              : 
     988              :   /* Try to determine type of the outer object.  */
     989      2877436 :   if (TREE_CODE (base_pointer) == SSA_NAME
     990      2348118 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
     991      3891693 :       && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
     992              :     {
     993              :       /* See if parameter is THIS pointer of a method.  */
     994      1002843 :       if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
     995      1563710 :           && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
     996              :         {
     997       431271 :           outer_type
     998       431271 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
     999       431271 :           cgraph_node *node = cgraph_node::get (current_function_decl);
    1000       431271 :           gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE
    1001              :                       || TREE_CODE (outer_type) == UNION_TYPE);
    1002              : 
    1003              :           /* Handle the case we inlined into a thunk.  In this case
    1004              :              thunk has THIS pointer of type bar, but it really receives
    1005              :              address to its base type foo which sits in bar at
    1006              :              0-thunk.fixed_offset.  It starts with code that adds
    1007              :              think.fixed_offset to the pointer to compensate for this.
    1008              : 
    1009              :              Because we walked all the way to the beginning of thunk, we now
    1010              :              see pointer &bar-thunk.fixed_offset and need to compensate
    1011              :              for it.  */
    1012       431271 :           thunk_info *info = thunk_info::get (node);
    1013       431271 :           if (info && info->fixed_offset)
    1014            7 :             offset -= info->fixed_offset * BITS_PER_UNIT;
    1015              : 
    1016              :           /* Dynamic casting has possibly upcasted the type
    1017              :              in the hierarchy.  In this case outer type is less
    1018              :              informative than inner type and we should forget
    1019              :              about it.  */
    1020       431271 :           if ((otr_type
    1021       162174 :                && !contains_type_p (outer_type, offset,
    1022              :                                     otr_type))
    1023       429238 :               || !contains_polymorphic_type_p (outer_type)
    1024              :               /* If we compile thunk with virtual offset, the THIS pointer
    1025              :                  is adjusted by unknown value.  We can't thus use outer info
    1026              :                  at all.  */
    1027       653538 :               || (info && info->virtual_offset_p))
    1028              :             {
    1029       209004 :               outer_type = NULL;
    1030       209004 :               if (instance)
    1031       207270 :                 *instance = base_pointer;
    1032       209004 :               return;
    1033              :             }
    1034              : 
    1035       222267 :           dynamic = true;
    1036              : 
    1037              :           /* If the function is constructor or destructor, then
    1038              :              the type is possibly in construction, but we know
    1039              :              it is not derived type.  */
    1040       222267 :           if (DECL_CXX_CONSTRUCTOR_P (fndecl)
    1041       222267 :               || DECL_CXX_DESTRUCTOR_P (fndecl))
    1042              :             {
    1043        30739 :               maybe_in_construction = true;
    1044        30739 :               maybe_derived_type = false;
    1045              :             }
    1046              :           else
    1047              :             {
    1048       191528 :               maybe_derived_type = true;
    1049       191528 :               maybe_in_construction = false;
    1050              :             }
    1051       222267 :           if (instance)
    1052              :             {
    1053        99772 :               thunk_info *info = thunk_info::get (node);
    1054              :               /* If method is expanded thunk, we need to apply thunk offset
    1055              :                  to instance pointer.  */
    1056        99772 :               if (info && (info->virtual_offset_p || info->fixed_offset))
    1057            5 :                 *instance = NULL;
    1058              :               else
    1059        99767 :                 *instance = base_pointer;
    1060              :             }
    1061       222267 :           return;
    1062              :         }
    1063              :       /* Non-PODs passed by value are really passed by invisible
    1064              :          reference.  In this case we also know the type of the
    1065              :          object.  */
    1066       571572 :       if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
    1067              :         {
    1068        19551 :           outer_type
    1069        19551 :              = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
    1070              :           /* Only type inconsistent programs can have otr_type that is
    1071              :              not part of outer type.  */
    1072        19551 :           if (otr_type && !contains_type_p (outer_type, offset,
    1073              :                                             otr_type))
    1074              :             {
    1075            0 :               invalid = true;
    1076            0 :               if (instance)
    1077            0 :                 *instance = base_pointer;
    1078            0 :               return;
    1079              :             }
    1080              :           /* Non-polymorphic types have no interest for us.  */
    1081        19551 :           else if (!otr_type && !contains_polymorphic_type_p (outer_type))
    1082              :             {
    1083        19463 :               outer_type = NULL;
    1084        19463 :               if (instance)
    1085        19463 :                 *instance = base_pointer;
    1086        19463 :               return;
    1087              :             }
    1088           88 :           maybe_derived_type = false;
    1089           88 :           maybe_in_construction = false;
    1090           88 :           if (instance)
    1091           69 :             *instance = base_pointer;
    1092           88 :           return;
    1093              :         }
    1094              :     }
    1095              : 
    1096      2426614 :   tree base_type = TREE_TYPE (base_pointer);
    1097              : 
    1098      2426614 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1099      1897296 :       && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
    1100      2990049 :       && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
    1101        11414 :            || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
    1102              :     {
    1103          352 :       invalid = true;
    1104          352 :       if (instance)
    1105          236 :         *instance = base_pointer;
    1106          352 :       return;
    1107              :     }
    1108      2426262 :   if (TREE_CODE (base_pointer) == SSA_NAME
    1109      1896944 :       && SSA_NAME_DEF_STMT (base_pointer)
    1110      4323206 :       && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
    1111       932955 :     base_type = TREE_TYPE (gimple_assign_rhs1
    1112              :                             (SSA_NAME_DEF_STMT (base_pointer)));
    1113              : 
    1114      2426262 :   if (base_type && POINTER_TYPE_P (base_type))
    1115      2426262 :     combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)),
    1116              :                               offset,
    1117              :                               true, NULL /* Do not change type here */);
    1118              :   /* TODO: There are multiple ways to derive a type.  For instance
    1119              :      if BASE_POINTER is passed to an constructor call prior our reference.
    1120              :      We do not make this type of flow sensitive analysis yet.  */
    1121      2426262 :   if (instance)
    1122      1841099 :     *instance = base_pointer;
    1123              :   return;
    1124              : }
    1125              : 
    1126              : /* Structure to be passed in between detect_type_change and
    1127              :    check_stmt_for_type_change.  */
    1128              : 
    1129              : struct type_change_info
    1130              : {
    1131              :   /* Offset into the object where there is the virtual method pointer we are
    1132              :      looking for.  */
    1133              :   HOST_WIDE_INT offset;
    1134              :   /* The declaration or SSA_NAME pointer of the base that we are checking for
    1135              :      type change.  */
    1136              :   tree instance;
    1137              :   /* The reference to virtual table pointer used.  */
    1138              :   tree vtbl_ptr_ref;
    1139              :   tree otr_type;
    1140              :   /* If we actually can tell the type that the object has changed to, it is
    1141              :      stored in this field.  Otherwise it remains NULL_TREE.  */
    1142              :   tree known_current_type;
    1143              :   HOST_WIDE_INT known_current_offset;
    1144              : 
    1145              :   /* Set to nonzero if we possibly missed some dynamic type changes and we
    1146              :      should consider the set to be speculative.  */
    1147              :   unsigned speculative;
    1148              : 
    1149              :   /* Set to true if dynamic type change has been detected.  */
    1150              :   bool type_maybe_changed;
    1151              :   /* Set to true if multiple types have been encountered.  known_current_type
    1152              :      must be disregarded in that case.  */
    1153              :   bool multiple_types_encountered;
    1154              :   bool seen_unanalyzed_store;
    1155              : };
    1156              : 
    1157              : /* Return true if STMT is not call and can modify a virtual method table pointer.
    1158              :    We take advantage of fact that vtable stores must appear within constructor
    1159              :    and destructor functions.  */
    1160              : 
    1161              : static bool
    1162      7400125 : noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
    1163              : {
    1164      7400125 :   if (is_gimple_assign (stmt))
    1165              :     {
    1166      7253922 :       tree lhs = gimple_assign_lhs (stmt);
    1167              : 
    1168      7253922 :       if (gimple_clobber_p (stmt))
    1169              :         return false;
    1170      6236742 :       if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
    1171              :         {
    1172      5531767 :           if (flag_strict_aliasing
    1173      5531767 :               && !POINTER_TYPE_P (TREE_TYPE (lhs)))
    1174              :             return false;
    1175              : 
    1176      2536574 :           if (TREE_CODE (lhs) == COMPONENT_REF
    1177      2536574 :               && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1178              :             return false;
    1179              :           /* In the future we might want to use get_ref_base_and_extent to find
    1180              :              if there is a field corresponding to the offset and if so, proceed
    1181              :              almost like if it was a component ref.  */
    1182              :         }
    1183              :     }
    1184              : 
    1185              :   /* Code unification may mess with inline stacks.  */
    1186      1481452 :   if (cfun->after_inlining)
    1187              :     return true;
    1188              : 
    1189              :   /* Walk the inline stack and watch out for ctors/dtors.
    1190              :      TODO: Maybe we can require the store to appear in toplevel
    1191              :      block of CTOR/DTOR.  */
    1192     11481520 :   for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
    1193      5020078 :        block = BLOCK_SUPERCONTEXT (block))
    1194      5075361 :     if (BLOCK_ABSTRACT_ORIGIN (block)
    1195      5075361 :         && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
    1196        55283 :       return inlined_polymorphic_ctor_dtor_block_p (block, false);
    1197      1386081 :   return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
    1198      1386081 :           && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
    1199        86747 :               || DECL_CXX_DESTRUCTOR_P (current_function_decl)));
    1200              : }
    1201              : 
    1202              : /* If STMT can be proved to be an assignment to the virtual method table
    1203              :    pointer of ANALYZED_OBJ and the type associated with the new table
    1204              :    identified, return the type.  Otherwise return NULL_TREE if type changes
    1205              :    in unknown way or ERROR_MARK_NODE if type is unchanged.  */
    1206              : 
    1207              : static tree
    1208        75426 : extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
    1209              :                                HOST_WIDE_INT *type_offset)
    1210              : {
    1211        75426 :   poly_int64 offset, size, max_size;
    1212        75426 :   tree lhs, rhs, base;
    1213        75426 :   bool reverse;
    1214              : 
    1215        75426 :   if (!gimple_assign_single_p (stmt))
    1216              :     return NULL_TREE;
    1217              : 
    1218        75363 :   lhs = gimple_assign_lhs (stmt);
    1219        75363 :   rhs = gimple_assign_rhs1 (stmt);
    1220        75363 :   if (TREE_CODE (lhs) != COMPONENT_REF
    1221        75363 :       || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
    1222              :      {
    1223        30194 :         if (dump_file)
    1224            0 :           fprintf (dump_file, "  LHS is not virtual table.\n");
    1225        30194 :         return NULL_TREE;
    1226              :      }
    1227              : 
    1228        45169 :   if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
    1229              :     ;
    1230              :   else
    1231              :     {
    1232        45095 :       base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
    1233        45095 :       if (DECL_P (tci->instance))
    1234              :         {
    1235         2025 :           if (base != tci->instance)
    1236              :             {
    1237           14 :               if (dump_file)
    1238              :                 {
    1239            0 :                   fprintf (dump_file, "    base:");
    1240            0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1241            0 :                   fprintf (dump_file, " does not match instance:");
    1242            0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1243            0 :                   fprintf (dump_file, "\n");
    1244              :                 }
    1245           14 :               return NULL_TREE;
    1246              :             }
    1247              :         }
    1248        43070 :       else if (TREE_CODE (base) == MEM_REF)
    1249              :         {
    1250        35773 :           if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
    1251              :             {
    1252        23763 :               if (dump_file)
    1253              :                 {
    1254            0 :                   fprintf (dump_file, "    base mem ref:");
    1255            0 :                   print_generic_expr (dump_file, base, TDF_SLIM);
    1256            0 :                   fprintf (dump_file, " does not match instance:");
    1257            0 :                   print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1258            0 :                   fprintf (dump_file, "\n");
    1259              :                 }
    1260        23763 :               return NULL_TREE;
    1261              :             }
    1262        12010 :           if (!integer_zerop (TREE_OPERAND (base, 1)))
    1263              :             {
    1264         1421 :               if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
    1265              :                 {
    1266            0 :                   if (dump_file)
    1267              :                     {
    1268            0 :                       fprintf (dump_file, "    base mem ref:");
    1269            0 :                       print_generic_expr (dump_file, base, TDF_SLIM);
    1270            0 :                       fprintf (dump_file, " has non-representable offset:");
    1271            0 :                       print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1272            0 :                       fprintf (dump_file, "\n");
    1273              :                     }
    1274            0 :                   return NULL_TREE;
    1275              :                 }
    1276              :               else
    1277         1421 :                 offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
    1278              :             }
    1279              :         }
    1280         7297 :       else if (!operand_equal_p (tci->instance, base, 0)
    1281         7297 :                || tci->offset)
    1282              :         {
    1283         7297 :           if (dump_file)
    1284              :             {
    1285            0 :               fprintf (dump_file, "    base:");
    1286            0 :               print_generic_expr (dump_file, base, TDF_SLIM);
    1287            0 :               fprintf (dump_file, " does not match instance:");
    1288            0 :               print_generic_expr (dump_file, tci->instance, TDF_SLIM);
    1289            0 :               fprintf (dump_file, " with offset %i\n", (int)tci->offset);
    1290              :             }
    1291         7353 :           return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
    1292              :         }
    1293        14021 :       if (maybe_ne (offset, tci->offset)
    1294        14419 :           || maybe_ne (size, POINTER_SIZE)
    1295        28440 :           || maybe_ne (max_size, POINTER_SIZE))
    1296              :         {
    1297           35 :           if (dump_file)
    1298              :             {
    1299            0 :               fprintf (dump_file, "    wrong offset ");
    1300            0 :               print_dec (offset, dump_file);
    1301            0 :               fprintf (dump_file, "!=%i or size ", (int) tci->offset);
    1302            0 :               print_dec (size, dump_file);
    1303            0 :               fprintf (dump_file, "\n");
    1304              :             }
    1305           35 :           return (known_le (offset + POINTER_SIZE, tci->offset)
    1306            0 :                   || (known_size_p (max_size)
    1307            0 :                       && known_gt (tci->offset + POINTER_SIZE,
    1308              :                                    offset + max_size))
    1309           35 :                   ? error_mark_node : NULL);
    1310              :         }
    1311              :     }
    1312              : 
    1313        14060 :   tree vtable;
    1314        14060 :   unsigned HOST_WIDE_INT offset2;
    1315              : 
    1316        14060 :   if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
    1317              :     {
    1318           68 :       if (dump_file)
    1319            4 :         fprintf (dump_file, "    Failed to lookup binfo\n");
    1320           68 :       return NULL;
    1321              :     }
    1322              : 
    1323        13992 :   tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
    1324              :                                                offset2, vtable);
    1325        13992 :   if (!binfo)
    1326              :     {
    1327          161 :       if (dump_file)
    1328           13 :         fprintf (dump_file, "    Construction vtable used\n");
    1329              :       /* FIXME: We should support construction contexts.  */
    1330          161 :       return NULL;
    1331              :     }
    1332              : 
    1333        13831 :   *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
    1334        13831 :   return DECL_CONTEXT (vtable);
    1335              : }
    1336              : 
    1337              : /* Record dynamic type change of TCI to TYPE.  */
    1338              : 
    1339              : static void
    1340       138178 : record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
    1341              : {
    1342       138178 :   if (dump_file)
    1343              :     {
    1344           39 :       if (type)
    1345              :         {
    1346           39 :           fprintf (dump_file, "  Recording type: ");
    1347           39 :           print_generic_expr (dump_file, type, TDF_SLIM);
    1348           39 :           fprintf (dump_file, " at offset %i\n", (int)offset);
    1349              :         }
    1350              :      else
    1351            0 :        fprintf (dump_file, "  Recording unknown type\n");
    1352              :     }
    1353              : 
    1354              :   /* If we found a constructor of type that is not polymorphic or
    1355              :      that may contain the type in question as a field (not as base),
    1356              :      restrict to the inner class first to make type matching below
    1357              :      happier.  */
    1358       138178 :   if (type
    1359       138178 :       && (offset
    1360       132708 :           || (TREE_CODE (type) != RECORD_TYPE
    1361       132708 :               || !TYPE_BINFO (type)
    1362       132274 :               || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
    1363              :     {
    1364       121254 :       ipa_polymorphic_call_context context;
    1365              : 
    1366       121254 :       context.offset = offset;
    1367       121254 :       context.outer_type = type;
    1368       121254 :       context.maybe_in_construction = false;
    1369       121254 :       context.maybe_derived_type = false;
    1370       121254 :       context.dynamic = true;
    1371              :       /* If we failed to find the inner type, we know that the call
    1372              :          would be undefined for type produced here.  */
    1373       121254 :       if (!context.restrict_to_inner_class (tci->otr_type))
    1374              :         {
    1375          862 :           if (dump_file)
    1376            0 :             fprintf (dump_file, "  Ignoring; does not contain otr_type\n");
    1377          862 :           return;
    1378              :         }
    1379              :       /* Watch for case we reached an POD type and anticipate placement
    1380              :          new.  */
    1381       120392 :       if (!context.maybe_derived_type)
    1382              :         {
    1383          623 :           type = context.outer_type;
    1384          623 :           offset = context.offset;
    1385              :         }
    1386              :     }
    1387       137316 :   if (tci->type_maybe_changed
    1388       137316 :       && (!types_same_for_odr (type, tci->known_current_type)
    1389           21 :           || offset != tci->known_current_offset))
    1390            2 :     tci->multiple_types_encountered = true;
    1391       137316 :   tci->known_current_type = TYPE_MAIN_VARIANT (type);
    1392       137316 :   tci->known_current_offset = offset;
    1393       137316 :   tci->type_maybe_changed = true;
    1394              : }
    1395              : 
    1396              : 
    1397              : /* The maximum number of may-defs we visit when looking for a must-def
    1398              :    that changes the dynamic type in check_stmt_for_type_change.  Tuned
    1399              :    after the PR12392 testcase which unlimited spends 40% time within
    1400              :    these alias walks and 8% with the following limit.  */
    1401              : 
    1402              : static inline bool
    1403     15833916 : csftc_abort_walking_p (unsigned speculative)
    1404              : {
    1405     15833916 :   unsigned max = param_max_speculative_devirt_maydefs;
    1406     15833916 :   return speculative > max ? true : false;
    1407              : }
    1408              : 
    1409              : /* Callback of walk_aliased_vdefs and a helper function for
    1410              :    detect_type_change to check whether a particular statement may modify
    1411              :    the virtual table pointer, and if possible also determine the new type of
    1412              :    the (sub-)object.  It stores its result into DATA, which points to a
    1413              :    type_change_info structure.  */
    1414              : 
    1415              : static bool
    1416     23415031 : check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
    1417              : {
    1418     23415031 :   gimple *stmt = SSA_NAME_DEF_STMT (vdef);
    1419     23415031 :   struct type_change_info *tci = (struct type_change_info *) data;
    1420     23415031 :   tree fn;
    1421              : 
    1422              :   /* If we already gave up, just terminate the rest of walk.  */
    1423     23415031 :   if (tci->multiple_types_encountered)
    1424              :     return true;
    1425              : 
    1426     23415031 :   if (is_gimple_call (stmt))
    1427              :     {
    1428     16014906 :       if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
    1429              :         return false;
    1430              : 
    1431              :       /* Check for a constructor call.  */
    1432     15958263 :       if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
    1433     14454060 :           && DECL_CXX_CONSTRUCTOR_P (fn)
    1434       969800 :           && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
    1435     16928063 :           && gimple_call_num_args (stmt))
    1436              :       {
    1437       969800 :         tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
    1438       969800 :         tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
    1439       969800 :         HOST_WIDE_INT offset = 0;
    1440       969800 :         bool reverse;
    1441              : 
    1442       969800 :         if (dump_file)
    1443              :           {
    1444           31 :             fprintf (dump_file, "  Checking constructor call: ");
    1445           31 :             print_gimple_stmt (dump_file, stmt, 0);
    1446              :           }
    1447              : 
    1448              :         /* See if THIS parameter seems like instance pointer.  */
    1449       969800 :         if (TREE_CODE (op) == ADDR_EXPR)
    1450              :           {
    1451       933631 :             HOST_WIDE_INT size;
    1452       933631 :             op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
    1453              :                                               &offset, &size, &reverse);
    1454       933631 :             if (!op)
    1455              :               {
    1456            0 :                 tci->speculative++;
    1457            0 :                 return csftc_abort_walking_p (tci->speculative);
    1458              :               }
    1459       933631 :             if (TREE_CODE (op) == MEM_REF)
    1460              :               {
    1461        92370 :                 if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
    1462              :                   {
    1463            0 :                     tci->speculative++;
    1464            0 :                     return csftc_abort_walking_p (tci->speculative);
    1465              :                   }
    1466        92370 :                 offset += tree_to_shwi (TREE_OPERAND (op, 1))
    1467        92370 :                           * BITS_PER_UNIT;
    1468        92370 :                 op = TREE_OPERAND (op, 0);
    1469              :               }
    1470       841261 :             else if (DECL_P (op))
    1471              :               ;
    1472              :             else
    1473              :               {
    1474            0 :                 tci->speculative++;
    1475            0 :                 return csftc_abort_walking_p (tci->speculative);
    1476              :               }
    1477       933631 :             op = walk_ssa_copies (op);
    1478              :           }
    1479       969800 :         if (operand_equal_p (op, tci->instance, 0)
    1480       176018 :             && TYPE_SIZE (type)
    1481       176018 :             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
    1482       176018 :             && tree_fits_shwi_p (TYPE_SIZE (type))
    1483       176018 :             && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
    1484              :             /* Some inlined constructors may look as follows:
    1485              :                   _3 = operator new (16);
    1486              :                   MEM[(struct  &)_3] ={v} {CLOBBER};
    1487              :                   MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
    1488              :                     = &MEM[(void *)&_ZTV14CompositeClass + 16B];
    1489              :                   _7 = &MEM[(struct CompositeClass *)_3].object;
    1490              :                   EmptyClass::EmptyClass (_7);
    1491              : 
    1492              :                When determining dynamic type of _3 and because we stop at first
    1493              :                dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
    1494              :                In this case the emptyclass is not even polymorphic and we miss
    1495              :                it is contained in an outer type that is polymorphic.  */
    1496              : 
    1497      1114415 :             && (tci->offset == offset || contains_polymorphic_type_p (type)))
    1498              :           {
    1499       124347 :             record_known_type (tci, type, tci->offset - offset);
    1500       124347 :             return true;
    1501              :           }
    1502              :       }
    1503              :      /* Calls may possibly change dynamic type by placement new. Assume
    1504              :         it will not happen, but make result speculative only.  */
    1505     15833916 :      if (dump_file)
    1506              :         {
    1507          736 :           fprintf (dump_file, "  Function call may change dynamic type:");
    1508          736 :           print_gimple_stmt (dump_file, stmt, 0);
    1509              :         }
    1510     15833916 :      tci->speculative++;
    1511     15833916 :      return csftc_abort_walking_p (tci->speculative);
    1512              :    }
    1513              :   /* Check for inlined virtual table store.  */
    1514      7400125 :   else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
    1515              :     {
    1516        75426 :       tree type;
    1517        75426 :       HOST_WIDE_INT offset = 0;
    1518        75426 :       if (dump_file)
    1519              :         {
    1520           38 :           fprintf (dump_file, "  Checking vtbl store: ");
    1521           38 :           print_gimple_stmt (dump_file, stmt, 0);
    1522              :         }
    1523              : 
    1524        75426 :       type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
    1525        75426 :       if (type == error_mark_node)
    1526              :         return false;
    1527        75386 :       gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
    1528        75386 :       if (!type)
    1529              :         {
    1530        61555 :           if (dump_file)
    1531           17 :             fprintf (dump_file, "  Unanalyzed store may change type.\n");
    1532        61555 :           tci->seen_unanalyzed_store = true;
    1533        61555 :           tci->speculative++;
    1534              :         }
    1535              :       else
    1536        13831 :         record_known_type (tci, type, offset);
    1537        75386 :       return true;
    1538              :     }
    1539              :   else
    1540              :     return false;
    1541              : }
    1542              : 
    1543              : /* THIS is polymorphic call context obtained from get_polymorphic_context.
    1544              :    OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
    1545              :    INSTANCE is pointer to the outer instance as returned by
    1546              :    get_polymorphic_context.  To avoid creation of temporary expressions,
    1547              :    INSTANCE may also be an declaration of get_polymorphic_context found the
    1548              :    value to be in static storage.
    1549              : 
    1550              :    If the type of instance is not fully determined
    1551              :    (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
    1552              :    is set), try to walk memory writes and find the actual construction of the
    1553              :    instance.
    1554              : 
    1555              :    Return true if memory is unchanged from function entry.
    1556              : 
    1557              :    We do not include this analysis in the context analysis itself, because
    1558              :    it needs memory SSA to be fully built and the walk may be expensive.
    1559              :    So it is not suitable for use withing fold_stmt and similar uses.
    1560              : 
    1561              :    AA_WALK_BUDGET_P, if not NULL, is how statements we should allow
    1562              :    walk_aliased_vdefs to examine.  The value should be decremented by the
    1563              :    number of statements we examined or set to zero if exhausted.  */
    1564              : 
    1565              : bool
    1566      3417779 : ipa_polymorphic_call_context::get_dynamic_type (tree instance,
    1567              :                                                 tree otr_object,
    1568              :                                                 tree otr_type,
    1569              :                                                 gimple *call,
    1570              :                                                 unsigned *aa_walk_budget_p)
    1571              : {
    1572      3417779 :   struct type_change_info tci;
    1573      3417779 :   ao_ref ao;
    1574      3417779 :   bool function_entry_reached = false;
    1575      3417779 :   tree instance_ref = NULL;
    1576      3417779 :   gimple *stmt = call;
    1577              :   /* Remember OFFSET before it is modified by restrict_to_inner_class.
    1578              :      This is because we do not update INSTANCE when walking inwards.  */
    1579      3417779 :   HOST_WIDE_INT instance_offset = offset;
    1580      3417779 :   tree instance_outer_type = outer_type;
    1581              : 
    1582      3417779 :   if (!instance)
    1583              :     return false;
    1584              : 
    1585      3417774 :   if (otr_type)
    1586       218484 :     otr_type = TYPE_MAIN_VARIANT (otr_type);
    1587              : 
    1588              :   /* Walk into inner type. This may clear maybe_derived_type and save us
    1589              :      from useless work.  It also makes later comparisons with static type
    1590              :      easier.  */
    1591      3417774 :   if (outer_type && otr_type)
    1592              :     {
    1593       195036 :       if (!restrict_to_inner_class (otr_type))
    1594              :         return false;
    1595              :     }
    1596              : 
    1597      3417774 :   if (!maybe_in_construction && !maybe_derived_type)
    1598              :     return false;
    1599              : 
    1600              :   /* If we are in fact not looking at any object or the instance is
    1601              :      some placement new into a random load, give up straight away.  */
    1602      3389512 :   if (TREE_CODE (instance) == MEM_REF)
    1603              :     return false;
    1604              : 
    1605              :   /* We need to obtain reference to virtual table pointer.  It is better
    1606              :      to look it up in the code rather than build our own.  This require bit
    1607              :      of pattern matching, but we end up verifying that what we found is
    1608              :      correct.
    1609              : 
    1610              :      What we pattern match is:
    1611              : 
    1612              :        tmp = instance->_vptr.A;   // vtbl ptr load
    1613              :        tmp2 = tmp[otr_token];     // vtable lookup
    1614              :        OBJ_TYPE_REF(tmp2;instance->0) (instance);
    1615              : 
    1616              :      We want to start alias oracle walk from vtbl pointer load,
    1617              :      but we may not be able to identify it, for example, when PRE moved the
    1618              :      load around.  */
    1619              : 
    1620      3389512 :   if (gimple_code (call) == GIMPLE_CALL)
    1621              :     {
    1622      3389512 :       tree ref = gimple_call_fn (call);
    1623      3389512 :       bool reverse;
    1624              : 
    1625      3389512 :       if (TREE_CODE (ref) == OBJ_TYPE_REF)
    1626              :         {
    1627       255343 :           ref = OBJ_TYPE_REF_EXPR (ref);
    1628       255343 :           ref = walk_ssa_copies (ref);
    1629              : 
    1630              :           /* If call target is already known, no need to do the expensive
    1631              :              memory walk.  */
    1632       255343 :           if (is_gimple_min_invariant (ref))
    1633            0 :             return false;
    1634              : 
    1635              :           /* Check if definition looks like vtable lookup.  */
    1636       255343 :           if (TREE_CODE (ref) == SSA_NAME
    1637       255343 :               && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1638       255343 :               && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
    1639       510488 :               && TREE_CODE (gimple_assign_rhs1
    1640              :                              (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
    1641              :             {
    1642       255125 :               ref = get_base_address
    1643       255125 :                      (TREE_OPERAND (gimple_assign_rhs1
    1644              :                                      (SSA_NAME_DEF_STMT (ref)), 0));
    1645       255125 :               ref = walk_ssa_copies (ref);
    1646              :               /* Find base address of the lookup and see if it looks like
    1647              :                  vptr load.  */
    1648       255125 :               if (TREE_CODE (ref) == SSA_NAME
    1649       254985 :                   && !SSA_NAME_IS_DEFAULT_DEF (ref)
    1650       510110 :                   && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
    1651              :                 {
    1652       253039 :                   HOST_WIDE_INT offset2, size;
    1653       253039 :                   tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
    1654       253039 :                   tree base_ref
    1655       253039 :                     = get_ref_base_and_extent_hwi (ref_exp, &offset2,
    1656              :                                                    &size, &reverse);
    1657              : 
    1658              :                   /* Finally verify that what we found looks like read from
    1659              :                      OTR_OBJECT or from INSTANCE with offset OFFSET.  */
    1660       253039 :                   if (base_ref
    1661       253039 :                       && ((TREE_CODE (base_ref) == MEM_REF
    1662       249634 :                            && ((offset2 == instance_offset
    1663       246584 :                                 && TREE_OPERAND (base_ref, 0) == instance)
    1664        16711 :                                || (!offset2
    1665        16711 :                                    && TREE_OPERAND (base_ref, 0)
    1666              :                                       == otr_object)))
    1667        18399 :                           || (DECL_P (instance) && base_ref == instance
    1668         3248 :                               && offset2 == instance_offset)))
    1669              :                     {
    1670       237888 :                       stmt = SSA_NAME_DEF_STMT (ref);
    1671       237888 :                       instance_ref = ref_exp;
    1672              :                     }
    1673              :                 }
    1674              :             }
    1675              :         }
    1676              :     }
    1677              : 
    1678              :   /* If we failed to look up the reference in code, build our own.  */
    1679      3389512 :   if (!instance_ref)
    1680              :     {
    1681              :       /* If the statement in question does not use memory, we can't tell
    1682              :          anything.  */
    1683      9495110 :       if (!gimple_vuse (stmt))
    1684              :         return false;
    1685      3142866 :       ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
    1686              :     }
    1687              :   else
    1688              :   /* Otherwise use the real reference.  */
    1689       237888 :     ao_ref_init (&ao, instance_ref);
    1690              : 
    1691              :   /* We look for vtbl pointer read.  */
    1692      3615055 :   ao.size = POINTER_SIZE;
    1693      3380754 :   ao.max_size = ao.size;
    1694              :   /* We are looking for stores to vptr pointer within the instance of
    1695              :      outer type.
    1696              :      TODO: The vptr pointer type is globally known, we probably should
    1697              :      keep it and do that even when otr_type is unknown.  */
    1698      3380754 :   if (otr_type)
    1699              :     {
    1700       217820 :       ao.base_alias_set
    1701       412192 :         = get_alias_set (outer_type ? outer_type : otr_type);
    1702       217820 :       ao.ref_alias_set
    1703       217820 :         = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
    1704              :     }
    1705              : 
    1706      3380754 :   if (dump_file)
    1707              :     {
    1708          621 :       fprintf (dump_file, "Determining dynamic type for call: ");
    1709          621 :       print_gimple_stmt (dump_file, call, 0);
    1710          621 :       fprintf (dump_file, "  Starting walk at: ");
    1711          621 :       print_gimple_stmt (dump_file, stmt, 0);
    1712          621 :       fprintf (dump_file, "  instance pointer: ");
    1713          621 :       print_generic_expr (dump_file, otr_object, TDF_SLIM);
    1714          621 :       fprintf (dump_file, "  Outer instance pointer: ");
    1715          621 :       print_generic_expr (dump_file, instance, TDF_SLIM);
    1716          621 :       fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
    1717          621 :       fprintf (dump_file, " vtbl reference: ");
    1718          621 :       print_generic_expr (dump_file, instance_ref, TDF_SLIM);
    1719          621 :       fprintf (dump_file, "\n");
    1720              :     }
    1721              : 
    1722      3380754 :   tci.offset = instance_offset;
    1723      3380754 :   tci.instance = instance;
    1724      3380754 :   tci.vtbl_ptr_ref = instance_ref;
    1725      3380754 :   tci.known_current_type = NULL_TREE;
    1726      3380754 :   tci.known_current_offset = 0;
    1727      3380754 :   tci.otr_type = otr_type;
    1728      3380754 :   tci.type_maybe_changed = false;
    1729      3380754 :   tci.multiple_types_encountered = false;
    1730      3380754 :   tci.speculative = 0;
    1731      3380754 :   tci.seen_unanalyzed_store = false;
    1732              : 
    1733      3380754 :   unsigned aa_walk_budget = 0;
    1734      3380754 :   if (aa_walk_budget_p)
    1735      3188216 :     aa_walk_budget = *aa_walk_budget_p + 1;
    1736              : 
    1737      3380754 :   int walked
    1738      3380754 :    = walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
    1739              :                          &tci, NULL, &function_entry_reached, aa_walk_budget);
    1740              : 
    1741              :   /* If we did not find any type changing statements, we may still drop
    1742              :      maybe_in_construction flag if the context already have outer type.
    1743              : 
    1744              :      Here we make special assumptions about both constructors and
    1745              :      destructors which are all the functions that are allowed to alter the
    1746              :      VMT pointers.  It assumes that destructors begin with assignment into
    1747              :      all VMT pointers and that constructors essentially look in the
    1748              :      following way:
    1749              : 
    1750              :      1) The very first thing they do is that they call constructors of
    1751              :      ancestor sub-objects that have them.
    1752              : 
    1753              :      2) Then VMT pointers of this and all its ancestors is set to new
    1754              :      values corresponding to the type corresponding to the constructor.
    1755              : 
    1756              :      3) Only afterwards, other stuff such as constructor of member
    1757              :      sub-objects and the code written by the user is run.  Only this may
    1758              :      include calling virtual functions, directly or indirectly.
    1759              : 
    1760              :      4) placement new cannot be used to change type of non-POD statically
    1761              :      allocated variables.
    1762              : 
    1763              :      There is no way to call a constructor of an ancestor sub-object in any
    1764              :      other way.
    1765              : 
    1766              :      This means that we do not have to care whether constructors get the
    1767              :      correct type information because they will always change it (in fact,
    1768              :      if we define the type to be given by the VMT pointer, it is undefined).
    1769              : 
    1770              :      The most important fact to derive from the above is that if, for some
    1771              :      statement in the section 3, we try to detect whether the dynamic type
    1772              :      has changed, we can safely ignore all calls as we examine the function
    1773              :      body backwards until we reach statements in section 2 because these
    1774              :      calls cannot be ancestor constructors or destructors (if the input is
    1775              :      not bogus) and so do not change the dynamic type (this holds true only
    1776              :      for automatically allocated objects but at the moment we devirtualize
    1777              :      only these).  We then must detect that statements in section 2 change
    1778              :      the dynamic type and can try to derive the new type.  That is enough
    1779              :      and we can stop, we will never see the calls into constructors of
    1780              :      sub-objects in this code.
    1781              : 
    1782              :      Therefore if the static outer type was found (outer_type)
    1783              :      we can safely ignore tci.speculative that is set on calls and give up
    1784              :      only if there was dynamic type store that may affect given variable
    1785              :      (seen_unanalyzed_store)  */
    1786              : 
    1787      3380754 :   if (walked < 0)
    1788              :     {
    1789       105436 :       if (dump_file)
    1790            0 :         fprintf (dump_file, "  AA walk budget exhausted.\n");
    1791       105436 :       *aa_walk_budget_p = 0;
    1792       105436 :       return false;
    1793              :     }
    1794      3275318 :   else if (aa_walk_budget_p)
    1795      3082780 :     *aa_walk_budget_p -= walked;
    1796              : 
    1797      3275318 :   if (!tci.type_maybe_changed
    1798      3275318 :       || (outer_type
    1799        20942 :           && !dynamic
    1800         3182 :           && !tci.seen_unanalyzed_store
    1801         3182 :           && !tci.multiple_types_encountered
    1802         3182 :           && ((offset == tci.offset
    1803         2909 :                && types_same_for_odr (tci.known_current_type,
    1804              :                                       outer_type))
    1805          487 :                || (instance_offset == offset
    1806          214 :                    && types_same_for_odr (tci.known_current_type,
    1807              :                                           instance_outer_type)))))
    1808              :     {
    1809      3140724 :       if (!outer_type || tci.seen_unanalyzed_store)
    1810              :         return false;
    1811       217159 :       if (maybe_in_construction)
    1812       149536 :         maybe_in_construction = false;
    1813       217159 :       if (dump_file)
    1814          225 :         fprintf (dump_file, "  No dynamic type change found.\n");
    1815       217159 :       return true;
    1816              :     }
    1817              : 
    1818       134594 :   if (tci.known_current_type
    1819       134594 :       && !function_entry_reached
    1820       131118 :       && !tci.multiple_types_encountered)
    1821              :     {
    1822       131117 :       if (!tci.speculative)
    1823              :         {
    1824        42561 :           outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1825        42561 :           offset = tci.known_current_offset;
    1826        42561 :           dynamic = true;
    1827        42561 :           maybe_in_construction = false;
    1828        42561 :           maybe_derived_type = false;
    1829        42561 :           if (dump_file)
    1830           28 :             fprintf (dump_file, "  Determined dynamic type.\n");
    1831              :         }
    1832        88556 :       else if (!speculative_outer_type
    1833         4937 :                || speculative_maybe_derived_type)
    1834              :         {
    1835        88556 :           speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
    1836        88556 :           speculative_offset = tci.known_current_offset;
    1837        88556 :           speculative_maybe_derived_type = false;
    1838        88556 :           if (dump_file)
    1839            8 :             fprintf (dump_file, "  Determined speculative dynamic type.\n");
    1840              :         }
    1841              :     }
    1842         3477 :   else if (dump_file)
    1843              :     {
    1844            0 :       fprintf (dump_file, "  Found multiple types%s%s\n",
    1845              :                function_entry_reached ? " (function entry reached)" : "",
    1846              :                function_entry_reached ? " (multiple types encountered)" : "");
    1847              :     }
    1848              : 
    1849              :   return false;
    1850              : }
    1851              : 
    1852              : /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
    1853              :    seems consistent (and useful) with what we already have in the non-speculative context.  */
    1854              : 
    1855              : bool
    1856      4769467 : ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type,
    1857              :                                                         HOST_WIDE_INT spec_offset,
    1858              :                                                         bool spec_maybe_derived_type,
    1859              :                                                         tree otr_type) const
    1860              : {
    1861      4769467 :   if (!flag_devirtualize_speculatively)
    1862              :     return false;
    1863              : 
    1864              :   /* Non-polymorphic types are useless for deriving likely polymorphic
    1865              :      call targets.  */
    1866      4761235 :   if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
    1867      3416940 :     return false;
    1868              : 
    1869              :   /* If we know nothing, speculation is always good.  */
    1870      1344295 :   if (!outer_type)
    1871              :     return true;
    1872              : 
    1873              :   /* Speculation is only useful to avoid derived types.
    1874              :      This is not 100% true for placement new, where the outer context may
    1875              :      turn out to be useless, but ignore these for now.  */
    1876       949062 :   if (!maybe_derived_type)
    1877              :     return false;
    1878              : 
    1879              :   /* If types agrees, speculation is consistent, but it makes sense only
    1880              :      when it says something new.  */
    1881       928430 :   if (types_must_be_same_for_odr (spec_outer_type, outer_type))
    1882      1415489 :     return maybe_derived_type && !spec_maybe_derived_type;
    1883              : 
    1884              :   /* If speculation does not contain the type in question, ignore it.  */
    1885       220604 :   if (otr_type
    1886       220604 :       && !contains_type_p (spec_outer_type, spec_offset, otr_type, false, true))
    1887              :     return false;
    1888              : 
    1889              :   /* If outer type already contains speculation as a filed,
    1890              :      it is useless.  We already know from OUTER_TYPE
    1891              :      SPEC_TYPE and that it is not in the construction.  */
    1892       218249 :   if (contains_type_p (outer_type, offset - spec_offset,
    1893              :                        spec_outer_type, false, false))
    1894              :     return false;
    1895              : 
    1896              :   /* If speculative outer type is not more specified than outer
    1897              :      type, just give up.
    1898              :      We can only decide this safely if we can compare types with OUTER_TYPE.
    1899              :    */
    1900           84 :   if ((!in_lto_p || odr_type_p (outer_type))
    1901       436216 :       && !contains_type_p (spec_outer_type,
    1902       218108 :                            spec_offset - offset,
    1903       218108 :                            outer_type, false))
    1904              :     return false;
    1905              :   return true;
    1906              : }
    1907              : 
    1908              : /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
    1909              :    NEW_MAYBE_DERIVED_TYPE
    1910              :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    1911              : 
    1912              : bool
    1913      4528368 : ipa_polymorphic_call_context::combine_speculation_with
    1914              :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    1915              :     tree otr_type)
    1916              : {
    1917      4528368 :   if (!new_outer_type)
    1918              :     return false;
    1919              : 
    1920              :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    1921              :      easier.  */
    1922      4450309 :   if (otr_type)
    1923         3941 :     restrict_to_inner_class (otr_type);
    1924              : 
    1925      4450309 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    1926              :                                  new_maybe_derived_type, otr_type))
    1927              :     return false;
    1928              : 
    1929              :   /* New speculation is a win in case we have no speculation or new
    1930              :      speculation does not consider derivations.  */
    1931       331585 :   if (!speculative_outer_type
    1932        84136 :       || (speculative_maybe_derived_type
    1933        83937 :           && !new_maybe_derived_type))
    1934              :     {
    1935       247617 :       speculative_outer_type = new_outer_type;
    1936       247617 :       speculative_offset = new_offset;
    1937       247617 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1938       247617 :       return true;
    1939              :     }
    1940        83968 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    1941              :                                        new_outer_type))
    1942              :     {
    1943        62457 :       if (speculative_offset != new_offset)
    1944              :         {
    1945              :           /* OK we have two contexts that seems valid but they disagree,
    1946              :              just give up.
    1947              : 
    1948              :              This is not a lattice operation, so we may want to drop it later.  */
    1949            4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    1950            0 :             fprintf (dump_file,
    1951              :                      "Speculative outer types match, "
    1952              :                      "offset mismatch -> invalid speculation\n");
    1953            4 :           clear_speculation ();
    1954            4 :           return true;
    1955              :         }
    1956              :       else
    1957              :         {
    1958        62453 :           if (speculative_maybe_derived_type && !new_maybe_derived_type)
    1959              :             {
    1960            0 :               speculative_maybe_derived_type = false;
    1961            0 :               return true;
    1962              :             }
    1963              :           else
    1964              :             return false;
    1965              :         }
    1966              :     }
    1967              :   /* Choose type that contains the other.  This one either contains the outer
    1968              :      as a field (thus giving exactly one target) or is deeper in the type
    1969              :      hierarchy.  */
    1970        21511 :   else if (speculative_outer_type
    1971        21511 :            && speculative_maybe_derived_type
    1972        42855 :            && (new_offset > speculative_offset
    1973        20777 :                || (new_offset == speculative_offset
    1974        20729 :                    && contains_type_p (new_outer_type,
    1975              :                                        0, speculative_outer_type, false))))
    1976              :     {
    1977          968 :       tree old_outer_type = speculative_outer_type;
    1978          968 :       HOST_WIDE_INT old_offset = speculative_offset;
    1979          968 :       bool old_maybe_derived_type = speculative_maybe_derived_type;
    1980              : 
    1981          968 :       speculative_outer_type = new_outer_type;
    1982          968 :       speculative_offset = new_offset;
    1983          968 :       speculative_maybe_derived_type = new_maybe_derived_type;
    1984              : 
    1985          968 :       if (otr_type)
    1986            0 :         restrict_to_inner_class (otr_type);
    1987              : 
    1988              :       /* If the speculation turned out to make no sense, revert to sensible
    1989              :          one.  */
    1990          968 :       if (!speculative_outer_type)
    1991              :         {
    1992            0 :           speculative_outer_type = old_outer_type;
    1993            0 :           speculative_offset = old_offset;
    1994            0 :           speculative_maybe_derived_type = old_maybe_derived_type;
    1995            0 :           return false;
    1996              :         }
    1997          968 :       return (old_offset != speculative_offset
    1998          401 :               || old_maybe_derived_type != speculative_maybe_derived_type
    1999         1369 :               || types_must_be_same_for_odr (speculative_outer_type,
    2000              :                                              new_outer_type));
    2001              :     }
    2002              :   return false;
    2003              : }
    2004              : 
    2005              : /* Make speculation less specific so
    2006              :    NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
    2007              :    If OTR_TYPE is set, assume the context is used with OTR_TYPE.  */
    2008              : 
    2009              : bool
    2010           59 : ipa_polymorphic_call_context::meet_speculation_with
    2011              :    (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
    2012              :     tree otr_type)
    2013              : {
    2014           59 :   if (!new_outer_type && speculative_outer_type)
    2015              :     {
    2016            2 :       clear_speculation ();
    2017            2 :       return true;
    2018              :     }
    2019              : 
    2020              :   /* restrict_to_inner_class may eliminate wrong speculation making our job
    2021              :      easier.  */
    2022           57 :   if (otr_type)
    2023            0 :     restrict_to_inner_class (otr_type);
    2024              : 
    2025           57 :   if (!speculative_outer_type
    2026           84 :       || !speculation_consistent_p (speculative_outer_type,
    2027              :                                     speculative_offset,
    2028           27 :                                     speculative_maybe_derived_type,
    2029              :                                     otr_type))
    2030           31 :     return false;
    2031              : 
    2032           26 :   if (!speculation_consistent_p (new_outer_type, new_offset,
    2033              :                                  new_maybe_derived_type, otr_type))
    2034              :     {
    2035            0 :       clear_speculation ();
    2036            0 :       return true;
    2037              :     }
    2038              : 
    2039           26 :   else if (types_must_be_same_for_odr (speculative_outer_type,
    2040              :                                        new_outer_type))
    2041              :     {
    2042            4 :       if (speculative_offset != new_offset)
    2043              :         {
    2044            0 :           clear_speculation ();
    2045            0 :           return true;
    2046              :         }
    2047              :       else
    2048              :         {
    2049            4 :           if (!speculative_maybe_derived_type && new_maybe_derived_type)
    2050              :             {
    2051            0 :               speculative_maybe_derived_type = true;
    2052            0 :               return true;
    2053              :             }
    2054              :           else
    2055              :             return false;
    2056              :         }
    2057              :     }
    2058              :   /* See if one type contains the other as a field (not base).  */
    2059           22 :   else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
    2060              :                             speculative_outer_type, false, false))
    2061              :     return false;
    2062           22 :   else if (contains_type_p (speculative_outer_type,
    2063           22 :                             speculative_offset - new_offset,
    2064              :                             new_outer_type, false, false))
    2065              :     {
    2066            0 :       speculative_outer_type = new_outer_type;
    2067            0 :       speculative_offset = new_offset;
    2068            0 :       speculative_maybe_derived_type = new_maybe_derived_type;
    2069            0 :       return true;
    2070              :     }
    2071              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2072           22 :   else if (contains_type_p (new_outer_type,
    2073           22 :                             new_offset - speculative_offset,
    2074              :                             speculative_outer_type, false, true))
    2075              :     {
    2076           19 :       if (!speculative_maybe_derived_type)
    2077              :         {
    2078            0 :           speculative_maybe_derived_type = true;
    2079            0 :           return true;
    2080              :         }
    2081              :       return false;
    2082              :     }
    2083              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2084            3 :   else if (contains_type_p (speculative_outer_type,
    2085            3 :                             speculative_offset - new_offset, new_outer_type, false, true))
    2086              :     {
    2087            0 :       speculative_outer_type = new_outer_type;
    2088            0 :       speculative_offset = new_offset;
    2089            0 :       speculative_maybe_derived_type = true;
    2090            0 :       return true;
    2091              :     }
    2092              :   else
    2093              :     {
    2094            3 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2095            0 :         fprintf (dump_file, "Giving up on speculative meet\n");
    2096            3 :       clear_speculation ();
    2097            3 :       return true;
    2098              :     }
    2099              : }
    2100              : 
    2101              : /* Assume that both THIS and a given context is valid and strengthen THIS
    2102              :    if possible.  Return true if any strengthening was made.
    2103              :    If actual type the context is being used in is known, OTR_TYPE should be
    2104              :    set accordingly. This improves quality of combined result.  */
    2105              : 
    2106              : bool
    2107       132284 : ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
    2108              :                                             tree otr_type)
    2109              : {
    2110       132284 :   bool updated = false;
    2111              : 
    2112       180957 :   if (ctx.useless_p () || invalid)
    2113              :     return false;
    2114              : 
    2115              :   /* Restricting context to inner type makes merging easier, however do not
    2116              :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2117       131224 :   if (otr_type && !invalid && !ctx.invalid)
    2118              :     {
    2119        32212 :       restrict_to_inner_class (otr_type);
    2120        32212 :       ctx.restrict_to_inner_class (otr_type);
    2121        32212 :       if(invalid)
    2122              :         return false;
    2123              :     }
    2124              : 
    2125       131173 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2126              :     {
    2127          101 :       fprintf (dump_file, "Polymorphic call context combine:");
    2128          101 :       dump (dump_file);
    2129          101 :       fprintf (dump_file, "With context:                    ");
    2130          101 :       ctx.dump (dump_file);
    2131          101 :       if (otr_type)
    2132              :         {
    2133           59 :           fprintf (dump_file, "To be used with type:            ");
    2134           59 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2135           59 :           fprintf (dump_file, "\n");
    2136              :         }
    2137              :     }
    2138              : 
    2139              :   /* If call is known to be invalid, we are done.  */
    2140       131173 :   if (ctx.invalid)
    2141              :     {
    2142            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2143            0 :         fprintf (dump_file, "-> Invalid context\n");
    2144            0 :       goto invalidate;
    2145              :     }
    2146              : 
    2147       131173 :   if (!ctx.outer_type)
    2148              :     ;
    2149        83745 :   else if (!outer_type)
    2150              :     {
    2151        15948 :       outer_type = ctx.outer_type;
    2152        15948 :       offset = ctx.offset;
    2153        15948 :       dynamic = ctx.dynamic;
    2154        15948 :       maybe_in_construction = ctx.maybe_in_construction;
    2155        15948 :       maybe_derived_type = ctx.maybe_derived_type;
    2156        15948 :       updated = true;
    2157              :     }
    2158              :   /* If types are known to be same, merging is quite easy.  */
    2159        67797 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2160              :     {
    2161        42032 :       if (offset != ctx.offset
    2162            4 :           && TYPE_SIZE (outer_type)
    2163        42036 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2164              :         {
    2165            4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2166            0 :             fprintf (dump_file, "Outer types match, offset mismatch -> invalid\n");
    2167            4 :           clear_speculation ();
    2168            4 :           clear_outer_type ();
    2169            4 :           invalid = true;
    2170            4 :           return true;
    2171              :         }
    2172        42028 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2173           21 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2174        42028 :       if (maybe_in_construction && !ctx.maybe_in_construction)
    2175              :         {
    2176        12545 :           updated = true;
    2177        12545 :           maybe_in_construction = false;
    2178              :         }
    2179        42028 :       if (maybe_derived_type && !ctx.maybe_derived_type)
    2180              :         {
    2181         2815 :           updated = true;
    2182         2815 :           maybe_derived_type = false;
    2183              :         }
    2184        42028 :       if (dynamic && !ctx.dynamic)
    2185              :         {
    2186        11676 :           updated = true;
    2187        11676 :           dynamic = false;
    2188              :         }
    2189              :     }
    2190              :   /* If we know the type precisely, there is not much to improve.  */
    2191        25765 :   else if (!maybe_derived_type && !maybe_in_construction
    2192        16372 :            && !ctx.maybe_derived_type && !ctx.maybe_in_construction)
    2193              :     {
    2194              :       /* It may be easy to check if second context permits the first
    2195              :          and set INVALID otherwise.  This is not easy to do in general;
    2196              :          contains_type_p may return false negatives for non-comparable
    2197              :          types.
    2198              : 
    2199              :          If OTR_TYPE is known, we however can expect that
    2200              :          restrict_to_inner_class should have discovered the same base
    2201              :          type.  */
    2202         1021 :       if (otr_type && !ctx.maybe_in_construction && !ctx.maybe_derived_type)
    2203              :         {
    2204            0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2205            0 :             fprintf (dump_file, "Contextes disagree -> invalid\n");
    2206            0 :           goto invalidate;
    2207              :         }
    2208              :     }
    2209              :   /* See if one type contains the other as a field (not base).
    2210              :      In this case we want to choose the wider type, because it contains
    2211              :      more information.  */
    2212        24744 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2213              :                             outer_type, false, false))
    2214              :     {
    2215         3959 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2216            0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2217              : 
    2218         3959 :       if (maybe_derived_type)
    2219              :         {
    2220         3548 :           outer_type = ctx.outer_type;
    2221         3548 :           maybe_derived_type = ctx.maybe_derived_type;
    2222         3548 :           offset = ctx.offset;
    2223         3548 :           dynamic = ctx.dynamic;
    2224         3548 :           updated = true;
    2225              :         }
    2226              : 
    2227              :       /* If we do not know how the context is being used, we cannot
    2228              :          clear MAYBE_IN_CONSTRUCTION because it may be offseted
    2229              :          to other component of OUTER_TYPE later and we know nothing
    2230              :          about it.  */
    2231         3959 :       if (otr_type && maybe_in_construction
    2232            0 :           && !ctx.maybe_in_construction)
    2233              :         {
    2234            0 :           maybe_in_construction = false;
    2235            0 :           updated = true;
    2236              :         }
    2237              :     }
    2238        20785 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2239              :                             ctx.outer_type, false, false))
    2240              :     {
    2241           68 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2242            0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2243              : 
    2244           68 :       if (otr_type && maybe_in_construction
    2245            0 :           && !ctx.maybe_in_construction)
    2246              :         {
    2247            0 :           maybe_in_construction = false;
    2248            0 :           updated = true;
    2249              :         }
    2250              :     }
    2251              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2252        20717 :   else if (contains_type_p (ctx.outer_type,
    2253        20717 :                             ctx.offset - offset, outer_type, false, true))
    2254              :     {
    2255         8997 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2256           12 :         fprintf (dump_file, "First type is base of second\n");
    2257         8997 :       if (!maybe_derived_type)
    2258              :         {
    2259         4292 :           if (!ctx.maybe_in_construction
    2260         4292 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2261              :             {
    2262            0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2263            0 :                 fprintf (dump_file, "Second context does not permit base -> invalid\n");
    2264            0 :               goto invalidate;
    2265              :             }
    2266              :         }
    2267              :       /* Pick variant deeper in the hierarchy.  */
    2268              :       else
    2269              :         {
    2270         4705 :           outer_type = ctx.outer_type;
    2271         4705 :           maybe_in_construction = ctx.maybe_in_construction;
    2272         4705 :           maybe_derived_type = ctx.maybe_derived_type;
    2273         4705 :           offset = ctx.offset;
    2274         4705 :           dynamic = ctx.dynamic;
    2275         4705 :           updated = true;
    2276              :         }
    2277              :     }
    2278              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2279        11720 :   else if (contains_type_p (outer_type,
    2280        11720 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2281              :     {
    2282        11605 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2283           50 :         fprintf (dump_file, "Second type is base of first\n");
    2284        11605 :       if (!ctx.maybe_derived_type)
    2285              :         {
    2286          139 :           if (!maybe_in_construction
    2287          139 :               && types_odr_comparable (outer_type, ctx.outer_type))
    2288              :             {
    2289            0 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2290            0 :                 fprintf (dump_file, "First context does not permit base -> invalid\n");
    2291            0 :               goto invalidate;
    2292              :             }
    2293              :           /* Pick the base type.  */
    2294          139 :           else if (maybe_in_construction)
    2295              :             {
    2296          139 :               outer_type = ctx.outer_type;
    2297          139 :               maybe_in_construction = ctx.maybe_in_construction;
    2298          139 :               maybe_derived_type = ctx.maybe_derived_type;
    2299          139 :               offset = ctx.offset;
    2300          139 :               dynamic = ctx.dynamic;
    2301          139 :               updated = true;
    2302              :             }
    2303              :         }
    2304              :     }
    2305              :   /* TODO handle merging using hierarchy. */
    2306          115 :   else if (dump_file && (dump_flags & TDF_DETAILS))
    2307            3 :     fprintf (dump_file, "Giving up on merge\n");
    2308              : 
    2309       262338 :   updated |= combine_speculation_with (ctx.speculative_outer_type,
    2310              :                                        ctx.speculative_offset,
    2311       131169 :                                        ctx.speculative_maybe_derived_type,
    2312              :                                        otr_type);
    2313              : 
    2314       131169 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2315              :     {
    2316           33 :       fprintf (dump_file, "Updated as:                      ");
    2317           33 :       dump (dump_file);
    2318           33 :       fprintf (dump_file, "\n");
    2319              :     }
    2320              :   return updated;
    2321              : 
    2322            0 : invalidate:
    2323            0 :   invalid = true;
    2324            0 :   clear_speculation ();
    2325            0 :   clear_outer_type ();
    2326            0 :   return true;
    2327              : }
    2328              : 
    2329              : /* Take non-speculative info, merge it with speculative and clear speculation.
    2330              :    Used when we no longer manage to keep track of actual outer type, but we
    2331              :    think it is still there.
    2332              : 
    2333              :    If OTR_TYPE is set, the transformation can be done more effectively assuming
    2334              :    that context is going to be used only that way.  */
    2335              : 
    2336              : void
    2337        92794 : ipa_polymorphic_call_context::make_speculative (tree otr_type)
    2338              : {
    2339        92794 :   tree spec_outer_type = outer_type;
    2340        92794 :   HOST_WIDE_INT spec_offset = offset;
    2341        92794 :   bool spec_maybe_derived_type = maybe_derived_type;
    2342              : 
    2343        92794 :   if (invalid)
    2344              :     {
    2345            0 :       invalid = false;
    2346            0 :       clear_outer_type ();
    2347            0 :       clear_speculation ();
    2348            0 :       return;
    2349              :     }
    2350        92794 :   if (!outer_type)
    2351              :     return;
    2352        28586 :   clear_outer_type ();
    2353        28586 :   combine_speculation_with (spec_outer_type, spec_offset,
    2354              :                             spec_maybe_derived_type,
    2355              :                             otr_type);
    2356              : }
    2357              : 
    2358              : /* Use when we cannot track dynamic type change.  This speculatively assume
    2359              :    type change is not happening.  */
    2360              : 
    2361              : void
    2362       113924 : ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
    2363              :                                                             tree otr_type)
    2364              : {
    2365       113924 :   if (dynamic)
    2366              :     {
    2367              :       /* See if existing speculation was inconsistent before type change.
    2368              :          If so drop it first, so we do not lose track about it being
    2369              :          impossible.  */
    2370        92758 :       if (speculative_outer_type
    2371        92758 :           && !speculation_consistent_p (speculative_outer_type,
    2372              :                                         speculative_offset,
    2373              :                                         speculative_maybe_derived_type,
    2374              :                                         otr_type))
    2375         7492 :         clear_speculation ();
    2376        92758 :       make_speculative (otr_type);
    2377              :     }
    2378        21166 :   else if (in_poly_cdtor)
    2379        11416 :     maybe_in_construction = true;
    2380       113924 : }
    2381              : 
    2382              : /* Return TRUE if this context conveys the same information as OTHER.  */
    2383              : 
    2384              : bool
    2385       123611 : ipa_polymorphic_call_context::equal_to
    2386              :     (const ipa_polymorphic_call_context &x) const
    2387              : {
    2388       123611 :   if (useless_p ())
    2389          100 :     return x.useless_p ();
    2390       123511 :   if (invalid)
    2391            0 :     return x.invalid;
    2392       231623 :   if (x.useless_p () || x.invalid)
    2393              :     return false;
    2394              : 
    2395       123500 :   if (outer_type)
    2396              :     {
    2397        17482 :       if (!x.outer_type
    2398        17094 :           || !types_odr_comparable (outer_type, x.outer_type)
    2399        17094 :           || !types_same_for_odr (outer_type, x.outer_type)
    2400        16783 :           || offset != x.offset
    2401        16762 :           || maybe_in_construction != x.maybe_in_construction
    2402        16757 :           || maybe_derived_type != x.maybe_derived_type
    2403        34180 :           || dynamic != x.dynamic)
    2404          890 :         return false;
    2405              :     }
    2406       106018 :   else if (x.outer_type)
    2407              :     return false;
    2408              : 
    2409              : 
    2410       122007 :   if (speculative_outer_type
    2411       229273 :       && speculation_consistent_p (speculative_outer_type, speculative_offset,
    2412       107266 :                                    speculative_maybe_derived_type, NULL_TREE))
    2413              :     {
    2414       104267 :       if (!x.speculative_outer_type)
    2415              :         return false;
    2416              : 
    2417       104267 :       if (!types_odr_comparable (speculative_outer_type,
    2418              :                                  x.speculative_outer_type)
    2419       104267 :           || !types_same_for_odr  (speculative_outer_type,
    2420       104267 :                                    x.speculative_outer_type)
    2421       103646 :           || speculative_offset != x.speculative_offset
    2422       207849 :           || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
    2423          688 :         return false;
    2424              :     }
    2425        17740 :   else if (x.speculative_outer_type
    2426        20751 :            && x.speculation_consistent_p (x.speculative_outer_type,
    2427         3011 :                                           x.speculative_offset,
    2428         3011 :                                           x.speculative_maybe_derived_type,
    2429              :                                           NULL))
    2430              :     return false;
    2431              : 
    2432              :   return true;
    2433              : }
    2434              : 
    2435              : /* Modify context to be strictly less restrictive than CTX.  */
    2436              : 
    2437              : bool
    2438         1327 : ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
    2439              :                                          tree otr_type)
    2440              : {
    2441         1327 :   bool updated = false;
    2442              : 
    2443         3576 :   if (useless_p () || ctx.invalid)
    2444              :     return false;
    2445              : 
    2446              :   /* Restricting context to inner type makes merging easier, however do not
    2447              :      do that unless we know how the context is used (OTR_TYPE is non-NULL)  */
    2448         1327 :   if (otr_type && !useless_p () && !ctx.useless_p ())
    2449              :     {
    2450            0 :       restrict_to_inner_class (otr_type);
    2451            0 :       ctx.restrict_to_inner_class (otr_type);
    2452            0 :       if(invalid)
    2453              :         return false;
    2454              :     }
    2455              : 
    2456         1327 :   if (equal_to (ctx))
    2457              :     return false;
    2458              : 
    2459           78 :   if (ctx.useless_p () || invalid)
    2460              :     {
    2461           11 :       *this = ctx;
    2462           11 :       return true;
    2463              :     }
    2464              : 
    2465           59 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2466              :     {
    2467            0 :       fprintf (dump_file, "Polymorphic call context meet:");
    2468            0 :       dump (dump_file);
    2469            0 :       fprintf (dump_file, "With context:                    ");
    2470            0 :       ctx.dump (dump_file);
    2471            0 :       if (otr_type)
    2472              :         {
    2473            0 :           fprintf (dump_file, "To be used with type:            ");
    2474            0 :           print_generic_expr (dump_file, otr_type, TDF_SLIM);
    2475            0 :           fprintf (dump_file, "\n");
    2476              :         }
    2477              :     }
    2478              : 
    2479           59 :   if (!dynamic && ctx.dynamic)
    2480              :     {
    2481            4 :       dynamic = true;
    2482            4 :       updated = true;
    2483              :     }
    2484              : 
    2485              :   /* If a certain context is known to be invalid, we can move to comparing
    2486              :      speculation.  Because the second context might be a certain one which can
    2487              :      be met with the speculation of the first, make it speculative.  */
    2488           59 :   if (!outer_type)
    2489           28 :     ctx.make_speculative ();
    2490           31 :   else if (!ctx.outer_type)
    2491              :     {
    2492            8 :       make_speculative ();
    2493            8 :       updated = true;
    2494              :     }
    2495              :   /* If types are known to be same, merging is quite easy.  */
    2496           23 :   else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
    2497              :     {
    2498           23 :       if (offset != ctx.offset
    2499            0 :           && TYPE_SIZE (outer_type)
    2500           23 :           && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
    2501              :         {
    2502            0 :           if (dump_file && (dump_flags & TDF_DETAILS))
    2503            0 :             fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
    2504            0 :           clear_outer_type ();
    2505            0 :           return true;
    2506              :         }
    2507           23 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2508            0 :         fprintf (dump_file, "Outer types match, merging flags\n");
    2509           23 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2510              :         {
    2511            0 :           updated = true;
    2512            0 :           maybe_in_construction = true;
    2513              :         }
    2514           23 :       if (!maybe_derived_type && ctx.maybe_derived_type)
    2515              :         {
    2516            4 :           updated = true;
    2517            4 :           maybe_derived_type = true;
    2518              :         }
    2519           23 :       if (!dynamic && ctx.dynamic)
    2520              :         {
    2521            0 :           updated = true;
    2522            0 :           dynamic = true;
    2523              :         }
    2524              :     }
    2525              :   /* See if one type contains the other as a field (not base).  */
    2526            0 :   else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
    2527              :                             outer_type, false, false))
    2528              :     {
    2529            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2530            0 :         fprintf (dump_file, "Second type contain the first as a field\n");
    2531              : 
    2532              :       /* The second type is more specified, so we keep the first.
    2533              :          We need to set DYNAMIC flag to avoid declaring context INVALID
    2534              :          of OFFSET ends up being out of range.  */
    2535            0 :       if (!dynamic
    2536            0 :           && (ctx.dynamic
    2537            0 :               || (!otr_type
    2538            0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2539            0 :                       || !TYPE_SIZE (outer_type)
    2540            0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2541            0 :                                            TYPE_SIZE (outer_type), 0)))))
    2542              :         {
    2543            0 :           dynamic = true;
    2544            0 :           updated = true;
    2545              :         }
    2546              :     }
    2547            0 :   else if (contains_type_p (outer_type, offset - ctx.offset,
    2548              :                             ctx.outer_type, false, false))
    2549              :     {
    2550            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2551            0 :         fprintf (dump_file, "First type contain the second as a field\n");
    2552              : 
    2553            0 :       if (!dynamic
    2554            0 :           && (ctx.dynamic
    2555            0 :               || (!otr_type
    2556            0 :                   && (!TYPE_SIZE (ctx.outer_type)
    2557            0 :                       || !TYPE_SIZE (outer_type)
    2558            0 :                       || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
    2559            0 :                                            TYPE_SIZE (outer_type), 0)))))
    2560              :         dynamic = true;
    2561            0 :       outer_type = ctx.outer_type;
    2562            0 :       offset = ctx.offset;
    2563            0 :       dynamic = ctx.dynamic;
    2564            0 :       maybe_in_construction = ctx.maybe_in_construction;
    2565            0 :       maybe_derived_type = ctx.maybe_derived_type;
    2566            0 :       updated = true;
    2567              :     }
    2568              :   /* See if OUTER_TYPE is base of CTX.OUTER_TYPE.  */
    2569            0 :   else if (contains_type_p (ctx.outer_type,
    2570            0 :                             ctx.offset - offset, outer_type, false, true))
    2571              :     {
    2572            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2573            0 :         fprintf (dump_file, "First type is base of second\n");
    2574            0 :       if (!maybe_derived_type)
    2575              :         {
    2576            0 :           maybe_derived_type = true;
    2577            0 :           updated = true;
    2578              :         }
    2579            0 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2580              :         {
    2581            0 :           maybe_in_construction = true;
    2582            0 :           updated = true;
    2583              :         }
    2584            0 :       if (!dynamic && ctx.dynamic)
    2585              :         {
    2586            0 :           dynamic = true;
    2587            0 :           updated = true;
    2588              :         }
    2589              :     }
    2590              :   /* See if CTX.OUTER_TYPE is base of OUTER_TYPE.  */
    2591            0 :   else if (contains_type_p (outer_type,
    2592            0 :                             offset - ctx.offset, ctx.outer_type, false, true))
    2593              :     {
    2594            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2595            0 :         fprintf (dump_file, "Second type is base of first\n");
    2596            0 :       outer_type = ctx.outer_type;
    2597            0 :       offset = ctx.offset;
    2598            0 :       updated = true;
    2599            0 :       if (!maybe_derived_type)
    2600            0 :         maybe_derived_type = true;
    2601            0 :       if (!maybe_in_construction && ctx.maybe_in_construction)
    2602            0 :         maybe_in_construction = true;
    2603            0 :       if (!dynamic && ctx.dynamic)
    2604            0 :         dynamic = true;
    2605              :     }
    2606              :   /* TODO handle merging using hierarchy. */
    2607              :   else
    2608              :     {
    2609            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2610            0 :         fprintf (dump_file, "Giving up on meet\n");
    2611            0 :       clear_outer_type ();
    2612            0 :       updated = true;
    2613              :     }
    2614              : 
    2615          118 :   updated |= meet_speculation_with (ctx.speculative_outer_type,
    2616              :                                     ctx.speculative_offset,
    2617           59 :                                     ctx.speculative_maybe_derived_type,
    2618              :                                     otr_type);
    2619              : 
    2620           59 :   if (updated && dump_file && (dump_flags & TDF_DETAILS))
    2621              :     {
    2622            0 :       fprintf (dump_file, "Updated as:                      ");
    2623            0 :       dump (dump_file);
    2624            0 :       fprintf (dump_file, "\n");
    2625              :     }
    2626              :   return updated;
    2627              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.