LCOV - code coverage report
Current view: top level - gcc - ubsan.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.3 % 1393 1342
Test Date: 2026-02-28 14:20:25 Functions: 97.1 % 35 34
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* UndefinedBehaviorSanitizer, undefined behavior detector.
       2              :    Copyright (C) 2013-2026 Free Software Foundation, Inc.
       3              :    Contributed by Marek Polacek <polacek@redhat.com>
       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 "c-family/c-common.h"
      27              : #include "gimple.h"
      28              : #include "cfghooks.h"
      29              : #include "tree-pass.h"
      30              : #include "memmodel.h"
      31              : #include "tm_p.h"
      32              : #include "ssa.h"
      33              : #include "cgraph.h"
      34              : #include "tree-pretty-print.h"
      35              : #include "stor-layout.h"
      36              : #include "cfganal.h"
      37              : #include "gimple-iterator.h"
      38              : #include "output.h"
      39              : #include "cfgloop.h"
      40              : #include "ubsan.h"
      41              : #include "expr.h"
      42              : #include "stringpool.h"
      43              : #include "attribs.h"
      44              : #include "asan.h"
      45              : #include "gimplify-me.h"
      46              : #include "dfp.h"
      47              : #include "builtins.h"
      48              : #include "tree-object-size.h"
      49              : #include "tree-cfg.h"
      50              : #include "gimple-fold.h"
      51              : #include "varasm.h"
      52              : #include "realmpfr.h"
      53              : #include "target.h"
      54              : #include "langhooks.h"
      55              : 
      56              : /* Map from a tree to a VAR_DECL tree.  */
      57              : 
      58              : struct GTY((for_user)) tree_type_map {
      59              :   struct tree_map_base type;
      60              :   tree decl;
      61              : };
      62              : 
      63              : struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
      64              : {
      65              :   static inline hashval_t
      66       104283 :   hash (tree_type_map *t)
      67              :   {
      68       104283 :     return TYPE_UID (t->type.from);
      69              :   }
      70              : 
      71              :   static inline bool
      72       119071 :   equal (tree_type_map *a, tree_type_map *b)
      73              :   {
      74       119071 :     return a->type.from == b->type.from;
      75              :   }
      76              : 
      77              :   static int
      78         2105 :   keep_cache_entry (tree_type_map *&m)
      79              :   {
      80         2105 :     return ggc_marked_p (m->type.from);
      81              :   }
      82              : };
      83              : 
      84              : static GTY ((cache))
      85              :      hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
      86              : 
      87              : /* Lookup a VAR_DECL for TYPE, and return it if we find one.  */
      88              : 
      89              : static tree
      90        38958 : decl_for_type_lookup (tree type)
      91              : {
      92              :   /* If the hash table is not initialized yet, create it now.  */
      93        38958 :   if (decl_tree_for_type == NULL)
      94              :     {
      95         2410 :       decl_tree_for_type
      96         2410 :         = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
      97              :       /* That also means we don't have to bother with the lookup.  */
      98         2410 :       return NULL_TREE;
      99              :     }
     100              : 
     101        36548 :   struct tree_type_map *h, in;
     102        36548 :   in.type.from = type;
     103              : 
     104        36548 :   h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
     105        36548 :   return h ? h->decl : NULL_TREE;
     106              : }
     107              : 
     108              : /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable.  */
     109              : 
     110              : static void
     111         5271 : decl_for_type_insert (tree type, tree decl)
     112              : {
     113         5271 :   struct tree_type_map *h;
     114              : 
     115         5271 :   h = ggc_alloc<tree_type_map> ();
     116         5271 :   h->type.from = type;
     117         5271 :   h->decl = decl;
     118         5271 :   *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
     119         5271 : }
     120              : 
     121              : /* Helper routine, which encodes a value in the pointer_sized_int_node.
     122              :    Arguments with precision <= POINTER_SIZE are passed directly,
     123              :    the rest is passed by reference.  T is a value we are to encode.
     124              :    PHASE determines when this function is called.  */
     125              : 
     126              : tree
     127        27560 : ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
     128              : {
     129        27560 :   tree type = TREE_TYPE (t);
     130        27560 :   if (TREE_CODE (type) == BITINT_TYPE)
     131              :     {
     132          290 :       if (TYPE_PRECISION (type) <= POINTER_SIZE)
     133              :         {
     134          102 :           type = pointer_sized_int_node;
     135          102 :           t = fold_build1 (NOP_EXPR, type, t);
     136              :         }
     137              :       else
     138              :         {
     139          376 :           if (TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE)
     140           86 :             return build_zero_cst (pointer_sized_int_node);
     141          102 :           type = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
     142          102 :                                                  TYPE_UNSIGNED (type));
     143          102 :           t = fold_build1 (NOP_EXPR, type, t);
     144              :         }
     145              :     }
     146        27474 :   scalar_mode mode = SCALAR_TYPE_MODE (type);
     147        27474 :   const unsigned int bitsize = GET_MODE_BITSIZE (mode);
     148        27474 :   if (bitsize <= POINTER_SIZE)
     149        23742 :     switch (TREE_CODE (type))
     150              :       {
     151        14796 :       case BOOLEAN_TYPE:
     152        14796 :       case ENUMERAL_TYPE:
     153        14796 :       case INTEGER_TYPE:
     154        14796 :         return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
     155         8946 :       case REAL_TYPE:
     156         8946 :         {
     157         8946 :           tree itype = build_nonstandard_integer_type (bitsize, true);
     158         8946 :           t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
     159         8946 :           return fold_convert (pointer_sized_int_node, t);
     160              :         }
     161            0 :       default:
     162            0 :         gcc_unreachable ();
     163              :       }
     164              :   else
     165              :     {
     166         3732 :       if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
     167              :         {
     168              :           /* The reason for this is that we don't want to pessimize
     169              :              code by making vars unnecessarily addressable.  */
     170         3732 :           tree var;
     171         3732 :           if (phase != UBSAN_ENCODE_VALUE_GENERIC)
     172              :             {
     173          263 :               var = create_tmp_var (type);
     174          263 :               mark_addressable (var);
     175              :             }
     176              :           else
     177              :             {
     178         3469 :               var = create_tmp_var_raw (type);
     179         3469 :               TREE_ADDRESSABLE (var) = 1;
     180         3469 :               DECL_CONTEXT (var) = current_function_decl;
     181              :             }
     182         3732 :           if (phase == UBSAN_ENCODE_VALUE_RTL)
     183              :             {
     184          526 :               rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
     185              :                                                     type);
     186          263 :               SET_DECL_RTL (var, mem);
     187          263 :               expand_assignment (var, t, false);
     188          263 :               return build_fold_addr_expr (var);
     189              :             }
     190         3469 :           if (phase != UBSAN_ENCODE_VALUE_GENERIC)
     191              :             {
     192            0 :               tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
     193            0 :               t = build_fold_addr_expr (var);
     194            0 :               return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
     195              :             }
     196              :           else
     197              :             {
     198         3469 :               var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
     199         3469 :               return build_fold_addr_expr (var);
     200              :             }
     201              :         }
     202              :       else
     203            0 :         return build_fold_addr_expr (t);
     204              :     }
     205              : }
     206              : 
     207              : /* Cached ubsan_get_type_descriptor_type () return value.  */
     208              : static GTY(()) tree ubsan_type_descriptor_type;
     209              : 
     210              : /* Build
     211              :    struct __ubsan_type_descriptor
     212              :    {
     213              :      unsigned short __typekind;
     214              :      unsigned short __typeinfo;
     215              :      char __typename[];
     216              :    }
     217              :    type.  */
     218              : 
     219              : static tree
     220        34161 : ubsan_get_type_descriptor_type (void)
     221              : {
     222        34161 :   static const char *field_names[3]
     223              :     = { "__typekind", "__typeinfo", "__typename" };
     224        34161 :   tree fields[3], ret;
     225              : 
     226        34161 :   if (ubsan_type_descriptor_type)
     227              :     return ubsan_type_descriptor_type;
     228              : 
     229         2630 :   tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
     230         2630 :   tree flex_arr_type = build_array_type (char_type_node, itype);
     231              : 
     232         2630 :   ret = make_node (RECORD_TYPE);
     233        10520 :   for (int i = 0; i < 3; i++)
     234              :     {
     235         7890 :       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
     236              :                               get_identifier (field_names[i]),
     237              :                               (i == 2) ? flex_arr_type
     238              :                               : short_unsigned_type_node);
     239         7890 :       DECL_CONTEXT (fields[i]) = ret;
     240         7890 :       if (i)
     241         5260 :         DECL_CHAIN (fields[i - 1]) = fields[i];
     242              :     }
     243         2630 :   tree type_decl = build_decl (input_location, TYPE_DECL,
     244              :                                get_identifier ("__ubsan_type_descriptor"),
     245              :                                ret);
     246         2630 :   DECL_IGNORED_P (type_decl) = 1;
     247         2630 :   DECL_ARTIFICIAL (type_decl) = 1;
     248         2630 :   TYPE_FIELDS (ret) = fields[0];
     249         2630 :   TYPE_NAME (ret) = type_decl;
     250         2630 :   TYPE_STUB_DECL (ret) = type_decl;
     251         2630 :   TYPE_ARTIFICIAL (ret) = 1;
     252         2630 :   layout_type (ret);
     253         2630 :   ubsan_type_descriptor_type = ret;
     254         2630 :   return ret;
     255              : }
     256              : 
     257              : /* Cached ubsan_get_source_location_type () return value.  */
     258              : static GTY(()) tree ubsan_source_location_type;
     259              : 
     260              : /* Build
     261              :    struct __ubsan_source_location
     262              :    {
     263              :      const char *__filename;
     264              :      unsigned int __line;
     265              :      unsigned int __column;
     266              :    }
     267              :    type.  */
     268              : 
     269              : tree
     270        69618 : ubsan_get_source_location_type (void)
     271              : {
     272        69618 :   static const char *field_names[3]
     273              :     = { "__filename", "__line", "__column" };
     274        69618 :   tree fields[3], ret;
     275        69618 :   if (ubsan_source_location_type)
     276              :     return ubsan_source_location_type;
     277              : 
     278         3483 :   tree const_char_type = build_qualified_type (char_type_node,
     279              :                                                TYPE_QUAL_CONST);
     280              : 
     281         3483 :   ret = make_node (RECORD_TYPE);
     282        13932 :   for (int i = 0; i < 3; i++)
     283              :     {
     284        13932 :       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
     285              :                               get_identifier (field_names[i]),
     286         3483 :                               (i == 0) ? build_pointer_type (const_char_type)
     287              :                               : unsigned_type_node);
     288        10449 :       DECL_CONTEXT (fields[i]) = ret;
     289        10449 :       if (i)
     290         6966 :         DECL_CHAIN (fields[i - 1]) = fields[i];
     291              :     }
     292         3483 :   tree type_decl = build_decl (input_location, TYPE_DECL,
     293              :                                get_identifier ("__ubsan_source_location"),
     294              :                                ret);
     295         3483 :   DECL_IGNORED_P (type_decl) = 1;
     296         3483 :   DECL_ARTIFICIAL (type_decl) = 1;
     297         3483 :   TYPE_FIELDS (ret) = fields[0];
     298         3483 :   TYPE_NAME (ret) = type_decl;
     299         3483 :   TYPE_STUB_DECL (ret) = type_decl;
     300         3483 :   TYPE_ARTIFICIAL (ret) = 1;
     301         3483 :   layout_type (ret);
     302         3483 :   ubsan_source_location_type = ret;
     303         3483 :   return ret;
     304              : }
     305              : 
     306              : /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
     307              :    type with its fields filled from a location_t LOC.  */
     308              : 
     309              : static tree
     310        29718 : ubsan_source_location (location_t loc)
     311              : {
     312        29718 :   expanded_location xloc;
     313        29718 :   tree type = ubsan_get_source_location_type ();
     314              : 
     315        29718 :   xloc = expand_location (loc);
     316        29718 :   tree str;
     317        29718 :   if (xloc.file == NULL)
     318              :     {
     319          934 :       str = build_int_cst (ptr_type_node, 0);
     320          934 :       xloc.line = 0;
     321          934 :       xloc.column = 0;
     322              :     }
     323              :   else
     324              :     {
     325              :       /* Fill in the values from LOC.  */
     326        28784 :       size_t len = strlen (xloc.file) + 1;
     327        28784 :       str = build_string (len, xloc.file);
     328        28784 :       TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
     329        28784 :       TREE_READONLY (str) = 1;
     330        28784 :       TREE_STATIC (str) = 1;
     331        28784 :       str = build_fold_addr_expr (str);
     332              :     }
     333        29718 :   tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
     334              :                                     build_int_cst (unsigned_type_node,
     335        29718 :                                                    xloc.line), NULL_TREE,
     336              :                                     build_int_cst (unsigned_type_node,
     337        29718 :                                                    xloc.column));
     338        29718 :   TREE_CONSTANT (ctor) = 1;
     339        29718 :   TREE_STATIC (ctor) = 1;
     340              : 
     341        29718 :   return ctor;
     342              : }
     343              : 
     344              : /* This routine returns a magic number for TYPE.  */
     345              : 
     346              : static unsigned short
     347         3813 : get_ubsan_type_info_for_type (tree type)
     348              : {
     349         3813 :   if (SCALAR_FLOAT_TYPE_P (type))
     350          204 :     return tree_to_uhwi (TYPE_SIZE (type));
     351         3609 :   else if (INTEGRAL_TYPE_P (type))
     352              :     {
     353         3609 :       int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
     354            0 :       gcc_assert (prec != -1);
     355         3609 :       return (prec << 1) | !TYPE_UNSIGNED (type);
     356              :     }
     357              :   else
     358              :     return 0;
     359              : }
     360              : 
     361              : /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
     362              :    descriptor.  It first looks into the hash table; if not found,
     363              :    create the VAR_DECL, put it into the hash table and return the
     364              :    ADDR_EXPR of it.  TYPE describes a particular type.  PSTYLE is
     365              :    an enum controlling how we want to print the type.  */
     366              : 
     367              : tree
     368        38958 : ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
     369              : {
     370              :   /* See through any typedefs.  */
     371        38958 :   type = TYPE_MAIN_VARIANT (type);
     372        38958 :   tree type3 = type;
     373        38958 :   if (pstyle == UBSAN_PRINT_FORCE_INT)
     374              :     {
     375              :       /* Temporary hack for -fsanitize=shift with _BitInt(129) and more.
     376              :          libubsan crashes if it is not TK_Integer type.  */
     377         1024 :       if (TREE_CODE (type) == BITINT_TYPE
     378         1104 :           && TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE)
     379           16 :         type3 = build_qualified_type (type, TYPE_QUAL_CONST);
     380         1024 :       if (type3 == type)
     381         1008 :         pstyle = UBSAN_PRINT_NORMAL;
     382              :     }
     383              : 
     384        38958 :   tree decl = decl_for_type_lookup (type3);
     385              :   /* It is possible that some of the earlier created DECLs were found
     386              :      unused, in that case they weren't emitted and varpool_node::get
     387              :      returns NULL node on them.  But now we really need them.  Thus,
     388              :      renew them here.  */
     389        38958 :   if (decl != NULL_TREE && varpool_node::get (decl))
     390              :     {
     391        33687 :       return build_fold_addr_expr (decl);
     392              :     }
     393              : 
     394         5271 :   tree dtype = ubsan_get_type_descriptor_type ();
     395         5271 :   tree type2 = type;
     396         5271 :   const char *tname = NULL;
     397         5271 :   pretty_printer pretty_name;
     398         5271 :   unsigned char deref_depth = 0;
     399         5271 :   unsigned short tkind, tinfo;
     400         5271 :   char tname_bitint[sizeof ("unsigned _BitInt(2147483647)")];
     401              : 
     402              :   /* Get the name of the type, or the name of the pointer type.  */
     403         5271 :   if (pstyle == UBSAN_PRINT_POINTER)
     404              :     {
     405         1172 :       gcc_assert (POINTER_TYPE_P (type));
     406         1172 :       type2 = TREE_TYPE (type);
     407              : 
     408              :       /* Remove any '*' operators from TYPE.  */
     409         1296 :       while (POINTER_TYPE_P (type2))
     410          124 :         deref_depth++, type2 = TREE_TYPE (type2);
     411              : 
     412         1172 :       if (TREE_CODE (type2) == METHOD_TYPE)
     413            0 :         type2 = TYPE_METHOD_BASETYPE (type2);
     414              :     }
     415              : 
     416              :   /* If an array, get its type.  */
     417         5271 :   type2 = strip_array_types (type2);
     418              : 
     419         5271 :   if (pstyle == UBSAN_PRINT_ARRAY)
     420              :     {
     421         1002 :       while (POINTER_TYPE_P (type2))
     422           54 :         deref_depth++, type2 = TREE_TYPE (type2);
     423              :     }
     424              : 
     425         5271 :   if (TYPE_NAME (type2) != NULL)
     426              :     {
     427         5166 :       if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
     428          612 :         tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
     429         4554 :       else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
     430         4551 :         tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
     431              :     }
     432              : 
     433         5163 :   if (tname == NULL)
     434              :     {
     435          108 :       if (TREE_CODE (type2) == BITINT_TYPE)
     436              :         {
     437          152 :           snprintf (tname_bitint, sizeof (tname_bitint),
     438           38 :                     "%s_BitInt(%d)", TYPE_UNSIGNED (type2) ? "unsigned " : "",
     439           38 :                     TYPE_PRECISION (type2));
     440           38 :           tname = tname_bitint;
     441              :         }
     442              :       else
     443              :         /* We weren't able to determine the type name.  */
     444              :         tname = "<unknown>";
     445              :     }
     446              : 
     447         5271 :   pp_quote (&pretty_name);
     448              : 
     449         5271 :   tree eltype = type;
     450         5271 :   if (pstyle == UBSAN_PRINT_POINTER)
     451              :     {
     452         1172 :       pp_printf (&pretty_name, "%s%s%s%s%s%s%s",
     453         1172 :                  TYPE_VOLATILE (type2) ? "volatile " : "",
     454         1172 :                  TYPE_READONLY (type2) ? "const " : "",
     455         1172 :                  TYPE_RESTRICT (type2) ? "restrict " : "",
     456         1172 :                  TYPE_ATOMIC (type2) ? "_Atomic " : "",
     457         1172 :                  TREE_CODE (type2) == RECORD_TYPE
     458              :                  ? "struct "
     459              :                  : TREE_CODE (type2) == UNION_TYPE
     460          707 :                    ? "union " : "", tname,
     461              :                  deref_depth == 0 ? "" : " ");
     462         2468 :       while (deref_depth-- > 0)
     463          124 :         pp_star (&pretty_name);
     464              :     }
     465         4099 :   else if (pstyle == UBSAN_PRINT_ARRAY)
     466              :     {
     467              :       /* Pretty print the array dimensions.  */
     468          948 :       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
     469          948 :       tree t = type;
     470          948 :       pp_string (&pretty_name, tname);
     471          948 :       pp_space (&pretty_name);
     472         1950 :       while (deref_depth-- > 0)
     473           54 :         pp_star (&pretty_name);
     474         2080 :       while (TREE_CODE (t) == ARRAY_TYPE)
     475              :         {
     476         1132 :           pp_left_bracket (&pretty_name);
     477         1132 :           tree dom = TYPE_DOMAIN (t);
     478         1132 :           if (dom != NULL_TREE
     479         1132 :               && TYPE_MAX_VALUE (dom) != NULL_TREE
     480         2043 :               && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
     481              :             {
     482          559 :               unsigned HOST_WIDE_INT m;
     483          559 :               if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
     484          559 :                   && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
     485          547 :                 pp_unsigned_wide_integer (&pretty_name, m + 1);
     486              :               else
     487           12 :                 pp_wide_int (&pretty_name,
     488           24 :                              wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
     489           12 :                              TYPE_SIGN (TREE_TYPE (dom)));
     490              :             }
     491              :           else
     492              :             /* ??? We can't determine the variable name; print VLA unspec.  */
     493          573 :             pp_star (&pretty_name);
     494         1132 :           pp_right_bracket (&pretty_name);
     495         1132 :           t = TREE_TYPE (t);
     496              :         }
     497              : 
     498              :       /* Save the tree with stripped types.  */
     499              :       eltype = t;
     500              :     }
     501              :   else
     502         3151 :     pp_string (&pretty_name, tname);
     503              : 
     504         5271 :   pp_quote (&pretty_name);
     505              : 
     506         5271 :   switch (TREE_CODE (eltype))
     507              :     {
     508              :     case BOOLEAN_TYPE:
     509              :     case ENUMERAL_TYPE:
     510              :     case INTEGER_TYPE:
     511              :       tkind = 0x0000;
     512              :       break;
     513           38 :     case BITINT_TYPE:
     514           76 :       if (TYPE_PRECISION (eltype) <= MAX_FIXED_MODE_SIZE)
     515              :         tkind = 0x0000;
     516              :       else
     517              :         tkind = 0xffff;
     518              :       break;
     519          238 :     case REAL_TYPE:
     520              :       /* FIXME: libubsan right now only supports float, double and
     521              :          long double type formats.  */
     522          238 :       if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
     523          190 :           || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
     524          315 :           || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
     525              :         tkind = 0x0001;
     526              :       else
     527              :         tkind = 0xffff;
     528              :       break;
     529              :     default:
     530              :       tkind = 0xffff;
     531              :       break;
     532              :     }
     533         3805 :   tinfo = tkind == 0xffff ? 0 : get_ubsan_type_info_for_type (eltype);
     534              : 
     535         5271 :   if (pstyle == UBSAN_PRINT_FORCE_INT)
     536              :     {
     537            8 :       tkind = 0x0000;
     538            8 :       tree t = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
     539            8 :                                                TYPE_UNSIGNED (eltype));
     540            8 :       tinfo = get_ubsan_type_info_for_type (t);
     541              :     }
     542              : 
     543              :   /* Create a new VAR_DECL of type descriptor.  */
     544         5271 :   const char *tmp = pp_formatted_text (&pretty_name);
     545         5271 :   size_t len = strlen (tmp) + 1;
     546         5271 :   tree str = build_string (len, tmp);
     547         5271 :   TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
     548         5271 :   TREE_READONLY (str) = 1;
     549         5271 :   TREE_STATIC (str) = 1;
     550              : 
     551         5271 :   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
     552              :                      generate_internal_label ("Lubsan_type"), dtype);
     553         5271 :   TREE_STATIC (decl) = 1;
     554         5271 :   TREE_PUBLIC (decl) = 0;
     555         5271 :   DECL_ARTIFICIAL (decl) = 1;
     556         5271 :   DECL_IGNORED_P (decl) = 1;
     557         5271 :   DECL_EXTERNAL (decl) = 0;
     558         5271 :   DECL_SIZE (decl)
     559         5271 :     = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
     560         5271 :   DECL_SIZE_UNIT (decl)
     561         5271 :     = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
     562              :                   TYPE_SIZE_UNIT (TREE_TYPE (str)));
     563              : 
     564         5271 :   tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
     565              :                                     build_int_cst (short_unsigned_type_node,
     566         5271 :                                                    tkind), NULL_TREE,
     567              :                                     build_int_cst (short_unsigned_type_node,
     568         5271 :                                                    tinfo), NULL_TREE, str);
     569         5271 :   TREE_CONSTANT (ctor) = 1;
     570         5271 :   TREE_STATIC (ctor) = 1;
     571         5271 :   DECL_INITIAL (decl) = ctor;
     572         5271 :   varpool_node::finalize_decl (decl);
     573              : 
     574              :   /* Save the VAR_DECL into the hash table.  */
     575         5271 :   decl_for_type_insert (type3, decl);
     576              : 
     577         5271 :   return build_fold_addr_expr (decl);
     578         5271 : }
     579              : 
     580              : /* Create a structure for the ubsan library.  NAME is a name of the new
     581              :    structure.  LOCCNT is number of locations, PLOC points to array of
     582              :    locations.  The arguments in ... are of __ubsan_type_descriptor type
     583              :    and there are at most two of them, followed by NULL_TREE, followed
     584              :    by optional extra arguments and another NULL_TREE.  */
     585              : 
     586              : tree
     587        28890 : ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
     588              : {
     589        28890 :   va_list args;
     590        28890 :   tree ret, t;
     591        28890 :   tree fields[6];
     592        28890 :   vec<tree, va_gc> *saved_args = NULL;
     593        28890 :   size_t i = 0;
     594        28890 :   int j;
     595              : 
     596              :   /* It is possible that PCH zapped table with definitions of sanitizer
     597              :      builtins.  Reinitialize them if needed.  */
     598        28890 :   initialize_sanitizer_builtins ();
     599              : 
     600              :   /* Firstly, create a pointer to type descriptor type.  */
     601        28890 :   tree td_type = ubsan_get_type_descriptor_type ();
     602        28890 :   td_type = build_pointer_type (td_type);
     603              : 
     604              :   /* Create the structure type.  */
     605        28890 :   ret = make_node (RECORD_TYPE);
     606        87498 :   for (j = 0; j < loccnt; j++)
     607              :     {
     608        29718 :       gcc_checking_assert (i < 2);
     609        29718 :       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
     610              :                               ubsan_get_source_location_type ());
     611        29718 :       DECL_CONTEXT (fields[i]) = ret;
     612        29718 :       if (i)
     613          828 :         DECL_CHAIN (fields[i - 1]) = fields[i];
     614        29718 :       i++;
     615              :     }
     616              : 
     617        28890 :   va_start (args, ploc);
     618        67848 :   for (t = va_arg (args, tree); t != NULL_TREE;
     619        38958 :        i++, t = va_arg (args, tree))
     620              :     {
     621        38958 :       gcc_checking_assert (i < 4);
     622              :       /* Save the tree arguments for later use.  */
     623        38958 :       vec_safe_push (saved_args, t);
     624        38958 :       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
     625              :                               td_type);
     626        38958 :       DECL_CONTEXT (fields[i]) = ret;
     627        38958 :       if (i)
     628        38958 :         DECL_CHAIN (fields[i - 1]) = fields[i];
     629              :     }
     630              : 
     631        37368 :   for (t = va_arg (args, tree); t != NULL_TREE;
     632         8478 :        i++, t = va_arg (args, tree))
     633              :     {
     634         8478 :       gcc_checking_assert (i < 6);
     635              :       /* Save the tree arguments for later use.  */
     636         8478 :       vec_safe_push (saved_args, t);
     637         8478 :       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
     638         8478 :                               TREE_TYPE (t));
     639         8478 :       DECL_CONTEXT (fields[i]) = ret;
     640         8478 :       if (i)
     641         8478 :         DECL_CHAIN (fields[i - 1]) = fields[i];
     642              :     }
     643        28890 :   va_end (args);
     644              : 
     645        28890 :   tree type_decl = build_decl (input_location, TYPE_DECL,
     646              :                                get_identifier (name), ret);
     647        28890 :   DECL_IGNORED_P (type_decl) = 1;
     648        28890 :   DECL_ARTIFICIAL (type_decl) = 1;
     649        28890 :   TYPE_FIELDS (ret) = fields[0];
     650        28890 :   TYPE_NAME (ret) = type_decl;
     651        28890 :   TYPE_STUB_DECL (ret) = type_decl;
     652        28890 :   TYPE_ARTIFICIAL (ret) = 1;
     653        28890 :   layout_type (ret);
     654              : 
     655              :   /* Now, fill in the type.  */
     656        28890 :   tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
     657              :                          generate_internal_label ("Lubsan_data"), ret);
     658        28890 :   TREE_STATIC (var) = 1;
     659        28890 :   TREE_PUBLIC (var) = 0;
     660        28890 :   DECL_ARTIFICIAL (var) = 1;
     661        28890 :   DECL_IGNORED_P (var) = 1;
     662        28890 :   DECL_EXTERNAL (var) = 0;
     663              : 
     664        28890 :   vec<constructor_elt, va_gc> *v;
     665        28890 :   vec_alloc (v, i);
     666        28890 :   tree ctor = build_constructor (ret, v);
     667              : 
     668              :   /* If desirable, set the __ubsan_source_location element.  */
     669        58608 :   for (j = 0; j < loccnt; j++)
     670              :     {
     671        29718 :       location_t loc = LOCATION_LOCUS (ploc[j]);
     672        29718 :       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
     673              :     }
     674              : 
     675        28890 :   size_t nelts = vec_safe_length (saved_args);
     676        76326 :   for (i = 0; i < nelts; i++)
     677              :     {
     678        47436 :       t = (*saved_args)[i];
     679        47436 :       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
     680              :     }
     681              : 
     682        28890 :   TREE_CONSTANT (ctor) = 1;
     683        28890 :   TREE_STATIC (ctor) = 1;
     684        28890 :   DECL_INITIAL (var) = ctor;
     685        28890 :   varpool_node::finalize_decl (var);
     686              : 
     687        28890 :   return var;
     688              : }
     689              : 
     690              : /* Shared between *build_builtin_unreachable.  */
     691              : 
     692              : tree
     693     21113835 : sanitize_unreachable_fn (tree *data, location_t loc)
     694              : {
     695     21113835 :   tree fn = NULL_TREE;
     696     21113835 :   bool san = sanitize_flags_p (SANITIZE_UNREACHABLE);
     697     21113835 :   if (san
     698     21113835 :       ? (flag_sanitize_trap & SANITIZE_UNREACHABLE)
     699     21113636 :       : flag_unreachable_traps)
     700              :     {
     701       764792 :       fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE_TRAP);
     702       764792 :       *data = NULL_TREE;
     703              :     }
     704     20349043 :   else if (san)
     705              :     {
     706              :       /* Call ubsan_create_data first as it initializes SANITIZER built-ins.  */
     707          199 :       *data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
     708              :                                  NULL_TREE, NULL_TREE);
     709          199 :       fn = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
     710          199 :       *data = build_fold_addr_expr_loc (loc, *data);
     711              :     }
     712              :   else
     713              :     {
     714     20348844 :       fn = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
     715     20348844 :       *data = NULL_TREE;
     716              :     }
     717     21113835 :   return fn;
     718              : }
     719              : 
     720              : /* Rewrite a gcall to __builtin_unreachable for -fsanitize=unreachable.  Called
     721              :    by the sanopt pass.  */
     722              : 
     723              : bool
     724            0 : ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
     725              : {
     726            0 :   location_t loc = gimple_location (gsi_stmt (*gsi));
     727            0 :   gimple *g = gimple_build_builtin_unreachable (loc);
     728            0 :   gsi_replace (gsi, g, false);
     729            0 :   return false;
     730              : }
     731              : 
     732              : /* Return true if T is a call to a libubsan routine.  */
     733              : 
     734              : bool
     735    198587493 : is_ubsan_builtin_p (tree t)
     736              : {
     737    198587493 :   return TREE_CODE (t) == FUNCTION_DECL
     738    198587492 :          && fndecl_built_in_p (t, BUILT_IN_NORMAL)
     739    208877211 :          && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
     740    198587493 :                      "__builtin___ubsan_", 18) == 0;
     741              : }
     742              : 
     743              : /* Create a callgraph edge for statement STMT.  */
     744              : 
     745              : static void
     746         3394 : ubsan_create_edge (gimple *stmt)
     747              : {
     748         3394 :   gcall *call_stmt = dyn_cast <gcall *> (stmt);
     749         3394 :   basic_block bb = gimple_bb (stmt);
     750         3394 :   cgraph_node *node = cgraph_node::get (current_function_decl);
     751         3394 :   tree decl = gimple_call_fndecl (call_stmt);
     752         3394 :   if (decl)
     753         3394 :     node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
     754         3394 : }
     755              : 
     756              : /* Expand the UBSAN_BOUNDS special builtin function.  */
     757              : 
     758              : bool
     759         1561 : ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
     760              : {
     761         1561 :   gimple *stmt = gsi_stmt (*gsi);
     762         1561 :   location_t loc = gimple_location (stmt);
     763         1561 :   gcc_assert (gimple_call_num_args (stmt) == 3);
     764              : 
     765              :   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
     766         1561 :   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
     767         1561 :   tree index = gimple_call_arg (stmt, 1);
     768         1561 :   tree orig_index = index;
     769         1561 :   tree bound = gimple_call_arg (stmt, 2);
     770              : 
     771         1561 :   gimple_stmt_iterator gsi_orig = *gsi;
     772              : 
     773              :   /* Create condition "if (index >= bound)".  */
     774         1561 :   basic_block then_bb, fallthru_bb;
     775         1561 :   gimple_stmt_iterator cond_insert_point
     776         1561 :     = create_cond_insert_point (gsi, false, false, true,
     777              :                                 &then_bb, &fallthru_bb);
     778         1561 :   index = fold_convert (TREE_TYPE (bound), index);
     779         1561 :   index = force_gimple_operand_gsi (&cond_insert_point, index,
     780              :                                     true, NULL_TREE,
     781              :                                     false, GSI_NEW_STMT);
     782         1561 :   gimple *g = gimple_build_cond (GE_EXPR, index, bound, NULL_TREE, NULL_TREE);
     783         1561 :   gimple_set_location (g, loc);
     784         1561 :   gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
     785              : 
     786              :   /* Generate __ubsan_handle_out_of_bounds call.  */
     787         1561 :   *gsi = gsi_after_labels (then_bb);
     788         1561 :   if (flag_sanitize_trap & SANITIZE_BOUNDS)
     789            0 :     g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
     790              :   else
     791              :     {
     792         1561 :       tree data
     793         1561 :         = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
     794              :                              ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
     795         1561 :                              ubsan_type_descriptor (TREE_TYPE (orig_index)),
     796              :                              NULL_TREE, NULL_TREE);
     797         1561 :       data = build_fold_addr_expr_loc (loc, data);
     798          116 :       enum built_in_function bcode
     799         1561 :         = (flag_sanitize_recover & SANITIZE_BOUNDS)
     800         1561 :           ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
     801              :           : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
     802         1561 :       tree fn = builtin_decl_explicit (bcode);
     803         1561 :       tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
     804         1561 :       val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
     805              :                                       GSI_SAME_STMT);
     806         1561 :       g = gimple_build_call (fn, 2, data, val);
     807              :     }
     808         1561 :   gimple_set_location (g, loc);
     809         1561 :   gsi_insert_before (gsi, g, GSI_SAME_STMT);
     810              : 
     811              :   /* Get rid of the UBSAN_BOUNDS call from the IR.  */
     812         1561 :   unlink_stmt_vdef (stmt);
     813         1561 :   gsi_remove (&gsi_orig, true);
     814              : 
     815              :   /* Point GSI to next logical statement.  */
     816         1561 :   *gsi = gsi_start_bb (fallthru_bb);
     817         1561 :   return true;
     818              : }
     819              : 
     820              : /* Expand UBSAN_NULL internal call.  The type is kept on the ckind
     821              :    argument which is a constant, because the middle-end treats pointer
     822              :    conversions as useless and therefore the type of the first argument
     823              :    could be changed to any other pointer type.  */
     824              : 
     825              : bool
     826         2942 : ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
     827              : {
     828         2942 :   gimple_stmt_iterator gsi = *gsip;
     829         2942 :   gimple *stmt = gsi_stmt (gsi);
     830         2942 :   location_t loc = gimple_location (stmt);
     831         2942 :   gcc_assert (gimple_call_num_args (stmt) == 3);
     832         2942 :   tree ptr = gimple_call_arg (stmt, 0);
     833         2942 :   tree ckind = gimple_call_arg (stmt, 1);
     834         2942 :   tree align = gimple_call_arg (stmt, 2);
     835         2942 :   tree check_align = NULL_TREE;
     836         2942 :   bool check_null;
     837              : 
     838         2942 :   basic_block cur_bb = gsi_bb (gsi);
     839              : 
     840         2942 :   gimple *g;
     841         2942 :   if (!integer_zerop (align))
     842              :     {
     843         2041 :       unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
     844         2041 :       if (compare_tree_int (align, ptralign) == 1)
     845              :         {
     846         1574 :           check_align = make_ssa_name (pointer_sized_int_node);
     847         1574 :           g = gimple_build_assign (check_align, NOP_EXPR, ptr);
     848         1574 :           gimple_set_location (g, loc);
     849         1574 :           gsi_insert_before (&gsi, g, GSI_SAME_STMT);
     850              :         }
     851              :     }
     852         2942 :   check_null = sanitize_flags_p (SANITIZE_NULL);
     853         2942 :   if (check_null && POINTER_TYPE_P (TREE_TYPE (ptr)))
     854              :     {
     855         2644 :       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (ptr)));
     856         2644 :       if (!ADDR_SPACE_GENERIC_P (as)
     857         2644 :           && targetm.addr_space.zero_address_valid (as))
     858              :         check_null = false;
     859              :     }
     860              : 
     861         2942 :   if (check_align == NULL_TREE && !check_null)
     862              :     {
     863           20 :       gsi_remove (gsip, true);
     864              :       /* Unlink the UBSAN_NULLs vops before replacing it.  */
     865           20 :       unlink_stmt_vdef (stmt);
     866           20 :       return true;
     867              :     }
     868              : 
     869              :   /* Split the original block holding the pointer dereference.  */
     870         2922 :   edge e = split_block (cur_bb, stmt);
     871              : 
     872              :   /* Get a hold on the 'condition block', the 'then block' and the
     873              :      'else block'.  */
     874         2922 :   basic_block cond_bb = e->src;
     875         2922 :   basic_block fallthru_bb = e->dest;
     876         2922 :   basic_block then_bb = create_empty_bb (cond_bb);
     877         2922 :   add_bb_to_loop (then_bb, cond_bb->loop_father);
     878         2922 :   loops_state_set (LOOPS_NEED_FIXUP);
     879              : 
     880              :   /* Make an edge coming from the 'cond block' into the 'then block';
     881              :      this edge is unlikely taken, so set up the probability accordingly.  */
     882         2922 :   e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
     883         2922 :   e->probability = profile_probability::very_unlikely ();
     884         2922 :   then_bb->count = e->count ();
     885              : 
     886              :   /* Connect 'then block' with the 'else block'.  This is needed
     887              :      as the ubsan routines we call in the 'then block' are not noreturn.
     888              :      The 'then block' only has one outcoming edge.  */
     889         2922 :   make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
     890              : 
     891              :   /* Set up the fallthrough basic block.  */
     892         2922 :   e = find_edge (cond_bb, fallthru_bb);
     893         2922 :   e->flags = EDGE_FALSE_VALUE;
     894         2922 :   e->probability = profile_probability::very_likely ();
     895              : 
     896              :   /* Update dominance info for the newly created then_bb; note that
     897              :      fallthru_bb's dominance info has already been updated by
     898              :      split_block.  */
     899         2922 :   if (dom_info_available_p (CDI_DOMINATORS))
     900         2922 :     set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
     901              : 
     902              :   /* Put the ubsan builtin call into the newly created BB.  */
     903         2922 :   if (flag_sanitize_trap & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
     904         3204 :                             | (check_null ? SANITIZE_NULL + 0 : 0)))
     905          106 :     g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
     906              :   else
     907              :     {
     908          542 :       enum built_in_function bcode
     909         2869 :         = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT + 0 : 0)
     910              :                                     | (check_null ? SANITIZE_NULL + 0 : 0)))
     911         2869 :           ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
     912              :           : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
     913         2869 :       tree fn = builtin_decl_implicit (bcode);
     914         2869 :       int align_log = tree_log2 (align);
     915         2869 :       tree data
     916         5738 :         = ubsan_create_data ("__ubsan_null_data", 1, &loc,
     917         2869 :                              ubsan_type_descriptor (TREE_TYPE (ckind),
     918              :                                                     UBSAN_PRINT_POINTER),
     919              :                              NULL_TREE,
     920              :                              build_int_cst (unsigned_char_type_node,
     921         2869 :                                             MAX (align_log, 0)),
     922              :                              fold_convert (unsigned_char_type_node, ckind),
     923              :                              NULL_TREE);
     924         2869 :       data = build_fold_addr_expr_loc (loc, data);
     925         4214 :       g = gimple_build_call (fn, 2, data,
     926              :                              check_align ? check_align
     927         1345 :                              : build_zero_cst (pointer_sized_int_node));
     928              :     }
     929         2922 :   gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
     930         2922 :   gimple_set_location (g, loc);
     931         2922 :   gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
     932              : 
     933              :   /* Unlink the UBSAN_NULLs vops before replacing it.  */
     934         2922 :   unlink_stmt_vdef (stmt);
     935              : 
     936         2922 :   if (check_null)
     937              :     {
     938         2640 :       g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
     939              :                              NULL_TREE, NULL_TREE);
     940         2640 :       gimple_set_location (g, loc);
     941              : 
     942              :       /* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
     943         2640 :       gsi_replace (&gsi, g, false);
     944         2640 :       stmt = g;
     945              :     }
     946              : 
     947         2922 :   if (check_align)
     948              :     {
     949         1574 :       if (check_null)
     950              :         {
     951              :           /* Split the block with the condition again.  */
     952         1292 :           e = split_block (cond_bb, stmt);
     953         1292 :           basic_block cond1_bb = e->src;
     954         1292 :           basic_block cond2_bb = e->dest;
     955              : 
     956              :           /* Make an edge coming from the 'cond1 block' into the 'then block';
     957              :              this edge is unlikely taken, so set up the probability
     958              :              accordingly.  */
     959         1292 :           e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
     960         1292 :           e->probability = profile_probability::very_unlikely ();
     961              : 
     962              :           /* Set up the fallthrough basic block.  */
     963         1292 :           e = find_edge (cond1_bb, cond2_bb);
     964         1292 :           e->flags = EDGE_FALSE_VALUE;
     965         1292 :           e->probability = profile_probability::very_likely ();
     966              : 
     967              :           /* Update dominance info.  */
     968         1292 :           if (dom_info_available_p (CDI_DOMINATORS))
     969              :             {
     970         1292 :               set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
     971         1292 :               set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
     972              :             }
     973              : 
     974         2584 :           gsi2 = gsi_start_bb (cond2_bb);
     975              :         }
     976              : 
     977         3148 :       tree mask = build_int_cst (pointer_sized_int_node,
     978         1574 :                                  tree_to_uhwi (align) - 1);
     979         1574 :       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
     980              :                                BIT_AND_EXPR, check_align, mask);
     981         1574 :       gimple_set_location (g, loc);
     982         1574 :       if (check_null)
     983         1292 :         gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
     984              :       else
     985          282 :         gsi_insert_before (&gsi, g, GSI_SAME_STMT);
     986              : 
     987         1574 :       g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
     988              :                              build_int_cst (pointer_sized_int_node, 0),
     989              :                              NULL_TREE, NULL_TREE);
     990         1574 :       gimple_set_location (g, loc);
     991         1574 :       if (check_null)
     992         1292 :         gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
     993              :       else
     994              :         /* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
     995          282 :         gsi_replace (&gsi, g, false);
     996              :     }
     997              :   return false;
     998              : }
     999              : 
    1000              : #define OBJSZ_MAX_OFFSET (1024 * 16)
    1001              : 
    1002              : /* Expand UBSAN_OBJECT_SIZE internal call.  */
    1003              : 
    1004              : bool
    1005          368 : ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
    1006              : {
    1007          368 :   gimple *stmt = gsi_stmt (*gsi);
    1008          368 :   location_t loc = gimple_location (stmt);
    1009          368 :   gcc_assert (gimple_call_num_args (stmt) == 4);
    1010              : 
    1011          368 :   tree ptr = gimple_call_arg (stmt, 0);
    1012          368 :   tree offset = gimple_call_arg (stmt, 1);
    1013          368 :   tree size = gimple_call_arg (stmt, 2);
    1014          368 :   tree ckind = gimple_call_arg (stmt, 3);
    1015          368 :   gimple_stmt_iterator gsi_orig = *gsi;
    1016          368 :   gimple *g;
    1017              : 
    1018              :   /* See if we can discard the check.  */
    1019          368 :   if (TREE_CODE (size) == INTEGER_CST
    1020          368 :       && integer_all_onesp (size))
    1021              :     /* Yes, __builtin_object_size couldn't determine the
    1022              :        object size.  */;
    1023          368 :   else if (TREE_CODE (offset) == INTEGER_CST
    1024          113 :            && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
    1025          481 :            && wi::to_widest (offset) <= -1)
    1026              :     /* The offset is in range [-16K, -1].  */;
    1027              :   else
    1028              :     {
    1029              :       /* if (offset > objsize) */
    1030          368 :       basic_block then_bb, fallthru_bb;
    1031          368 :       gimple_stmt_iterator cond_insert_point
    1032          368 :         = create_cond_insert_point (gsi, false, false, true,
    1033              :                                     &then_bb, &fallthru_bb);
    1034          368 :       g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
    1035          368 :       gimple_set_location (g, loc);
    1036          368 :       gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
    1037              : 
    1038              :       /* If the offset is small enough, we don't need the second
    1039              :          run-time check.  */
    1040          368 :       if (TREE_CODE (offset) == INTEGER_CST
    1041          113 :           && wi::to_widest (offset) >= 0
    1042          481 :           && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
    1043          101 :         *gsi = gsi_after_labels (then_bb);
    1044              :       else
    1045              :         {
    1046              :           /* Don't issue run-time error if (ptr > ptr + offset).  That
    1047              :              may happen when computing a POINTER_PLUS_EXPR.  */
    1048          267 :           basic_block then2_bb, fallthru2_bb;
    1049              : 
    1050          267 :           gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
    1051          267 :           cond_insert_point = create_cond_insert_point (&gsi2, false, false,
    1052              :                                                         true, &then2_bb,
    1053              :                                                         &fallthru2_bb);
    1054              :           /* Convert the pointer to an integer type.  */
    1055          267 :           tree p = make_ssa_name (pointer_sized_int_node);
    1056          267 :           g = gimple_build_assign (p, NOP_EXPR, ptr);
    1057          267 :           gimple_set_location (g, loc);
    1058          267 :           gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
    1059          267 :           p = gimple_assign_lhs (g);
    1060              :           /* Compute ptr + offset.  */
    1061          267 :           g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    1062              :                                    PLUS_EXPR, p, offset);
    1063          267 :           gimple_set_location (g, loc);
    1064          267 :           gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
    1065              :           /* Now build the conditional and put it into the IR.  */
    1066          267 :           g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
    1067              :                                  NULL_TREE, NULL_TREE);
    1068          267 :           gimple_set_location (g, loc);
    1069          267 :           gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
    1070          267 :           *gsi = gsi_after_labels (then2_bb);
    1071              :         }
    1072              : 
    1073              :       /* Generate __ubsan_handle_type_mismatch call.  */
    1074          368 :       if (flag_sanitize_trap & SANITIZE_OBJECT_SIZE)
    1075            0 :         g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
    1076              :       else
    1077              :         {
    1078          368 :           tree data
    1079          736 :             = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
    1080          368 :                                  ubsan_type_descriptor (TREE_TYPE (ptr),
    1081              :                                                         UBSAN_PRINT_POINTER),
    1082              :                                  NULL_TREE,
    1083              :                                  build_zero_cst (unsigned_char_type_node),
    1084              :                                  ckind,
    1085              :                                  NULL_TREE);
    1086          368 :           data = build_fold_addr_expr_loc (loc, data);
    1087           66 :           enum built_in_function bcode
    1088          368 :             = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
    1089          368 :               ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
    1090              :               : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
    1091          368 :           tree p = make_ssa_name (pointer_sized_int_node);
    1092          368 :           g = gimple_build_assign (p, NOP_EXPR, ptr);
    1093          368 :           gimple_set_location (g, loc);
    1094          368 :           gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1095          368 :           g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
    1096              :         }
    1097          368 :       gimple_set_location (g, loc);
    1098          368 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1099              : 
    1100              :       /* Point GSI to next logical statement.  */
    1101          368 :       *gsi = gsi_start_bb (fallthru_bb);
    1102              : 
    1103              :       /* Get rid of the UBSAN_OBJECT_SIZE call from the IR.  */
    1104          368 :       unlink_stmt_vdef (stmt);
    1105          368 :       gsi_remove (&gsi_orig, true);
    1106          368 :       return true;
    1107              :     }
    1108              : 
    1109              :   /* Get rid of the UBSAN_OBJECT_SIZE call from the IR.  */
    1110            0 :   unlink_stmt_vdef (stmt);
    1111            0 :   gsi_remove (gsi, true);
    1112            0 :   return true;
    1113              : }
    1114              : 
    1115              : /* Expand UBSAN_PTR internal call.  */
    1116              : 
    1117              : bool
    1118         1558 : ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
    1119              : {
    1120         1558 :   gimple_stmt_iterator gsi = *gsip;
    1121         1558 :   gimple *stmt = gsi_stmt (gsi);
    1122         1558 :   location_t loc = gimple_location (stmt);
    1123         1558 :   gcc_assert (gimple_call_num_args (stmt) == 2);
    1124         1558 :   tree ptr = gimple_call_arg (stmt, 0);
    1125         1558 :   tree off = gimple_call_arg (stmt, 1);
    1126              : 
    1127         1558 :   if (integer_zerop (off))
    1128              :     {
    1129            0 :       gsi_remove (gsip, true);
    1130            0 :       unlink_stmt_vdef (stmt);
    1131            0 :       return true;
    1132              :     }
    1133              : 
    1134         1558 :   basic_block cur_bb = gsi_bb (gsi);
    1135         1558 :   tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
    1136         1558 :   tree ptri = make_ssa_name (pointer_sized_int_node);
    1137         1558 :   int pos_neg = get_range_pos_neg (off);
    1138              : 
    1139              :   /* Split the original block holding the pointer dereference.  */
    1140         1558 :   edge e = split_block (cur_bb, stmt);
    1141              : 
    1142              :   /* Get a hold on the 'condition block', the 'then block' and the
    1143              :      'else block'.  */
    1144         1558 :   basic_block cond_bb = e->src;
    1145         1558 :   basic_block fallthru_bb = e->dest;
    1146         1558 :   basic_block then_bb = create_empty_bb (cond_bb);
    1147         1558 :   basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
    1148         1558 :   add_bb_to_loop (then_bb, cond_bb->loop_father);
    1149         1558 :   loops_state_set (LOOPS_NEED_FIXUP);
    1150              : 
    1151              :   /* Set up the fallthrough basic block.  */
    1152         1558 :   e->flags = EDGE_FALSE_VALUE;
    1153         1558 :   if (pos_neg != 3)
    1154              :     {
    1155         1079 :       e->probability = profile_probability::very_likely ();
    1156              : 
    1157              :       /* Connect 'then block' with the 'else block'.  This is needed
    1158              :          as the ubsan routines we call in the 'then block' are not noreturn.
    1159              :          The 'then block' only has one outcoming edge.  */
    1160         1079 :       make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
    1161              : 
    1162              :       /* Make an edge coming from the 'cond block' into the 'then block';
    1163              :          this edge is unlikely taken, so set up the probability
    1164              :          accordingly.  */
    1165         1079 :       e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
    1166         1079 :       e->probability = profile_probability::very_unlikely ();
    1167         1079 :       then_bb->count = e->count ();
    1168              :     }
    1169              :   else
    1170              :     {
    1171          479 :       e->probability = profile_probability::even ();
    1172              : 
    1173          479 :       e = split_block (fallthru_bb, (gimple *) NULL);
    1174          479 :       cond_neg_bb = e->src;
    1175          479 :       fallthru_bb = e->dest;
    1176          479 :       e->probability = profile_probability::very_likely ();
    1177          479 :       e->flags = EDGE_FALSE_VALUE;
    1178              : 
    1179          479 :       e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
    1180          479 :       e->probability = profile_probability::very_unlikely ();
    1181          479 :       then_bb->count = e->count ();
    1182              : 
    1183          479 :       cond_pos_bb = create_empty_bb (cond_bb);
    1184          479 :       add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
    1185              : 
    1186          479 :       e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
    1187          479 :       e->probability = profile_probability::even ();
    1188          479 :       cond_pos_bb->count = e->count ();
    1189              : 
    1190          479 :       e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
    1191          479 :       e->probability = profile_probability::very_unlikely ();
    1192              : 
    1193          479 :       e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
    1194          479 :       e->probability = profile_probability::very_likely ();
    1195              : 
    1196          479 :       make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
    1197              :     }
    1198              : 
    1199         1558 :   gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
    1200         1558 :   gimple_set_location (g, loc);
    1201         1558 :   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
    1202         1558 :   g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
    1203         1558 :   gimple_set_location (g, loc);
    1204         1558 :   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
    1205              : 
    1206              :   /* Update dominance info for the newly created then_bb; note that
    1207              :      fallthru_bb's dominance info has already been updated by
    1208              :      split_block.  */
    1209         1558 :   if (dom_info_available_p (CDI_DOMINATORS))
    1210              :     {
    1211         1558 :       set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
    1212         1558 :       if (pos_neg == 3)
    1213              :         {
    1214          479 :           set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
    1215          479 :           set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
    1216              :         }
    1217              :     }
    1218              : 
    1219              :   /* Put the ubsan builtin call into the newly created BB.  */
    1220         1558 :   if (flag_sanitize_trap & SANITIZE_POINTER_OVERFLOW)
    1221            0 :     g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
    1222              :   else
    1223              :     {
    1224          345 :       enum built_in_function bcode
    1225         1558 :         = (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
    1226         1558 :           ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
    1227              :           : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
    1228         1558 :       tree fn = builtin_decl_implicit (bcode);
    1229         1558 :       tree data
    1230         1558 :         = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
    1231              :                              NULL_TREE, NULL_TREE);
    1232         1558 :       data = build_fold_addr_expr_loc (loc, data);
    1233         1558 :       g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
    1234              :     }
    1235         1558 :   gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
    1236         1558 :   gimple_set_location (g, loc);
    1237         1558 :   gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
    1238              : 
    1239              :   /* Unlink the UBSAN_PTRs vops before replacing it.  */
    1240         1558 :   unlink_stmt_vdef (stmt);
    1241              : 
    1242         1558 :   if (TREE_CODE (off) == INTEGER_CST)
    1243         1956 :     g = gimple_build_cond (wi::neg_p (wi::to_wide (off)) ? LT_EXPR : GE_EXPR,
    1244              :                            ptri, fold_build1 (NEGATE_EXPR, sizetype, off),
    1245              :                            NULL_TREE, NULL_TREE);
    1246          529 :   else if (pos_neg != 3)
    1247           50 :     g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
    1248              :                            ptrplusoff, ptri, NULL_TREE, NULL_TREE);
    1249              :   else
    1250              :     {
    1251          479 :       gsi2 = gsi_start_bb (cond_pos_bb);
    1252          479 :       g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
    1253          479 :       gimple_set_location (g, loc);
    1254          479 :       gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
    1255              : 
    1256          479 :       gsi2 = gsi_start_bb (cond_neg_bb);
    1257          479 :       g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
    1258          479 :       gimple_set_location (g, loc);
    1259          479 :       gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
    1260              : 
    1261          479 :       tree t = gimple_build (&gsi, true, GSI_SAME_STMT,
    1262              :                              loc, NOP_EXPR, ssizetype, off);
    1263          479 :       g = gimple_build_cond (GE_EXPR, t, ssize_int (0),
    1264              :                              NULL_TREE, NULL_TREE);
    1265              :     }
    1266         1558 :   gimple_set_location (g, loc);
    1267              :   /* Replace the UBSAN_PTR with a GIMPLE_COND stmt.  */
    1268         1558 :   gsi_replace (&gsi, g, false);
    1269         1558 :   return false;
    1270              : }
    1271              : 
    1272              : 
    1273              : /* Cached __ubsan_vptr_type_cache decl.  */
    1274              : static GTY(()) tree ubsan_vptr_type_cache_decl;
    1275              : 
    1276              : /* Expand UBSAN_VPTR internal call.  The type is kept on the ckind
    1277              :    argument which is a constant, because the middle-end treats pointer
    1278              :    conversions as useless and therefore the type of the first argument
    1279              :    could be changed to any other pointer type.  */
    1280              : 
    1281              : bool
    1282          498 : ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
    1283              : {
    1284          498 :   gimple_stmt_iterator gsi = *gsip;
    1285          498 :   gimple *stmt = gsi_stmt (gsi);
    1286          498 :   location_t loc = gimple_location (stmt);
    1287          498 :   gcc_assert (gimple_call_num_args (stmt) == 5);
    1288          498 :   tree op = gimple_call_arg (stmt, 0);
    1289          498 :   tree vptr = gimple_call_arg (stmt, 1);
    1290          498 :   tree str_hash = gimple_call_arg (stmt, 2);
    1291          498 :   tree ti_decl_addr = gimple_call_arg (stmt, 3);
    1292          498 :   tree ckind_tree = gimple_call_arg (stmt, 4);
    1293          498 :   ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
    1294          498 :   tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
    1295          498 :   gimple *g;
    1296          498 :   basic_block fallthru_bb = NULL;
    1297              : 
    1298          498 :   if (ckind == UBSAN_DOWNCAST_POINTER)
    1299              :     {
    1300              :       /* Guard everything with if (op != NULL) { ... }.  */
    1301           36 :       basic_block then_bb;
    1302           36 :       gimple_stmt_iterator cond_insert_point
    1303           36 :         = create_cond_insert_point (gsip, false, false, true,
    1304              :                                     &then_bb, &fallthru_bb);
    1305           36 :       g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
    1306              :                              NULL_TREE, NULL_TREE);
    1307           36 :       gimple_set_location (g, loc);
    1308           36 :       gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
    1309           36 :       *gsip = gsi_after_labels (then_bb);
    1310           36 :       gsi_remove (&gsi, false);
    1311           36 :       gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
    1312           36 :       gsi = *gsip;
    1313              :     }
    1314              : 
    1315          498 :   tree htype = TREE_TYPE (str_hash);
    1316          498 :   tree cst = wide_int_to_tree (htype,
    1317          498 :                                wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
    1318              :                                | 0xeb382d69, 64));
    1319          498 :   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
    1320              :                            vptr, str_hash);
    1321          498 :   gimple_set_location (g, loc);
    1322          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1323          498 :   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
    1324              :                            gimple_assign_lhs (g), cst);
    1325          498 :   gimple_set_location (g, loc);
    1326          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1327          498 :   tree t1 = gimple_assign_lhs (g);
    1328          498 :   g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
    1329              :                            t1, build_int_cst (integer_type_node, 47));
    1330          498 :   gimple_set_location (g, loc);
    1331          498 :   tree t2 = gimple_assign_lhs (g);
    1332          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1333          498 :   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
    1334              :                            vptr, t1);
    1335          498 :   gimple_set_location (g, loc);
    1336          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1337          498 :   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
    1338              :                            t2, gimple_assign_lhs (g));
    1339          498 :   gimple_set_location (g, loc);
    1340          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1341          498 :   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
    1342              :                            gimple_assign_lhs (g), cst);
    1343          498 :   gimple_set_location (g, loc);
    1344          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1345          498 :   tree t3 = gimple_assign_lhs (g);
    1346          498 :   g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
    1347              :                            t3, build_int_cst (integer_type_node, 47));
    1348          498 :   gimple_set_location (g, loc);
    1349          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1350          498 :   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
    1351              :                            t3, gimple_assign_lhs (g));
    1352          498 :   gimple_set_location (g, loc);
    1353          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1354          498 :   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
    1355              :                            gimple_assign_lhs (g), cst);
    1356          498 :   gimple_set_location (g, loc);
    1357          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1358          498 :   if (!useless_type_conversion_p (pointer_sized_int_node, htype))
    1359              :     {
    1360            0 :       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    1361              :                                NOP_EXPR, gimple_assign_lhs (g));
    1362            0 :       gimple_set_location (g, loc);
    1363            0 :       gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1364              :     }
    1365          498 :   tree hash = gimple_assign_lhs (g);
    1366              : 
    1367          498 :   if (ubsan_vptr_type_cache_decl == NULL_TREE)
    1368              :     {
    1369          100 :       tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
    1370          100 :       tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
    1371              :                                get_identifier ("__ubsan_vptr_type_cache"),
    1372              :                                atype);
    1373          100 :       DECL_ARTIFICIAL (array) = 1;
    1374          100 :       DECL_IGNORED_P (array) = 1;
    1375          100 :       TREE_PUBLIC (array) = 1;
    1376          100 :       TREE_STATIC (array) = 1;
    1377          100 :       DECL_EXTERNAL (array) = 1;
    1378          100 :       DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
    1379          100 :       DECL_VISIBILITY_SPECIFIED (array) = 1;
    1380          100 :       varpool_node::finalize_decl (array);
    1381          100 :       ubsan_vptr_type_cache_decl = array;
    1382              :    }
    1383              : 
    1384          498 :   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    1385              :                            BIT_AND_EXPR, hash,
    1386              :                            build_int_cst (pointer_sized_int_node, 127));
    1387          498 :   gimple_set_location (g, loc);
    1388          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1389              : 
    1390          498 :   tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
    1391              :                        ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
    1392              :                        NULL_TREE, NULL_TREE);
    1393          498 :   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    1394              :                            ARRAY_REF, c);
    1395          498 :   gimple_set_location (g, loc);
    1396          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1397              : 
    1398          498 :   basic_block then_bb, fallthru2_bb;
    1399          498 :   gimple_stmt_iterator cond_insert_point
    1400          498 :     = create_cond_insert_point (gsip, false, false, true,
    1401              :                                 &then_bb, &fallthru2_bb);
    1402          498 :   g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
    1403              :                          NULL_TREE, NULL_TREE);
    1404          498 :   gimple_set_location (g, loc);
    1405          498 :   gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
    1406          498 :   *gsip = gsi_after_labels (then_bb);
    1407          498 :   if (fallthru_bb == NULL)
    1408          462 :     fallthru_bb = fallthru2_bb;
    1409              : 
    1410          498 :   tree data
    1411          498 :     = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
    1412              :                          ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
    1413          498 :                          build_int_cst (unsigned_char_type_node, ckind),
    1414              :                          NULL_TREE);
    1415          498 :   data = build_fold_addr_expr_loc (loc, data);
    1416          134 :   enum built_in_function bcode
    1417          498 :     = (flag_sanitize_recover & SANITIZE_VPTR)
    1418          498 :       ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
    1419              :       : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
    1420              : 
    1421          498 :   g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
    1422          498 :   gimple_set_location (g, loc);
    1423          498 :   gsi_insert_before (gsip, g, GSI_SAME_STMT);
    1424              : 
    1425              :   /* Point GSI to next logical statement.  */
    1426          498 :   *gsip = gsi_start_bb (fallthru_bb);
    1427              : 
    1428              :   /* Get rid of the UBSAN_VPTR call from the IR.  */
    1429          498 :   unlink_stmt_vdef (stmt);
    1430          498 :   gsi_remove (&gsi, true);
    1431          498 :   return true;
    1432              : }
    1433              : 
    1434              : /* Instrument a memory reference.  BASE is the base of MEM, IS_LHS says
    1435              :    whether the pointer is on the left hand side of the assignment.  */
    1436              : 
    1437              : static void
    1438         3700 : instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
    1439              :                     bool is_lhs)
    1440              : {
    1441         3700 :   enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
    1442         3700 :   unsigned int align = 0;
    1443         3700 :   if (sanitize_flags_p (SANITIZE_ALIGNMENT))
    1444              :     {
    1445         3408 :       align = min_align_of_type (TREE_TYPE (base));
    1446         3408 :       if (align <= 1)
    1447              :         align = 0;
    1448              :     }
    1449              :   if (align == 0)
    1450              :     {
    1451          753 :       if (!sanitize_flags_p (SANITIZE_NULL))
    1452         3700 :         return;
    1453          742 :       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
    1454          742 :       if (!ADDR_SPACE_GENERIC_P (as)
    1455          742 :           && targetm.addr_space.zero_address_valid (as))
    1456              :         return;
    1457              :     }
    1458         3682 :   tree t = TREE_OPERAND (base, 0);
    1459         3682 :   if (!POINTER_TYPE_P (TREE_TYPE (t)))
    1460              :     return;
    1461         3682 :   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
    1462              :     ikind = UBSAN_MEMBER_ACCESS;
    1463         3682 :   tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
    1464         3682 :   tree alignt = build_int_cst (pointer_sized_int_node, align);
    1465         3682 :   gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
    1466         3682 :   gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
    1467         3682 :   gsi_safe_insert_before (iter, g);
    1468              : }
    1469              : 
    1470              : /* Perform the pointer instrumentation.  */
    1471              : 
    1472              : static void
    1473        20040 : instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
    1474              : {
    1475              :   /* Handle also e.g. &s->i.  */
    1476        20040 :   if (TREE_CODE (t) == ADDR_EXPR)
    1477          831 :     t = TREE_OPERAND (t, 0);
    1478        20040 :   tree base = get_base_address (t);
    1479        20040 :   if (base != NULL_TREE
    1480        20040 :       && TREE_CODE (base) == MEM_REF
    1481        23740 :       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
    1482         3700 :     instrument_mem_ref (t, base, &gsi, is_lhs);
    1483        20040 : }
    1484              : 
    1485              : /* Instrument pointer arithmetics PTR p+ OFF.  */
    1486              : 
    1487              : static void
    1488         2772 : instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
    1489              : {
    1490         2772 :   if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
    1491              :     return;
    1492         2772 :   gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
    1493         2772 :   gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
    1494         2772 :   gsi_safe_insert_before (gsi, g);
    1495              : }
    1496              : 
    1497              : /* Instrument pointer arithmetics if any.  */
    1498              : 
    1499              : static void
    1500        26755 : maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
    1501              : {
    1502        26755 :   if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
    1503        24781 :     return;
    1504              : 
    1505              :   /* Handle also e.g. &s->i.  */
    1506        26755 :   if (TREE_CODE (t) == ADDR_EXPR)
    1507         3099 :     t = TREE_OPERAND (t, 0);
    1508              : 
    1509        26755 :   if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
    1510              :     return;
    1511              : 
    1512         6303 :   poly_int64 bitsize, bitpos, bytepos;
    1513         6303 :   tree offset;
    1514         6303 :   machine_mode mode;
    1515         6303 :   int volatilep = 0, reversep, unsignedp = 0;
    1516         6303 :   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
    1517              :                                     &unsignedp, &reversep, &volatilep);
    1518         6303 :   tree moff = NULL_TREE;
    1519              : 
    1520         6303 :   bool decl_p = DECL_P (inner);
    1521         6303 :   tree base;
    1522         6303 :   if (decl_p)
    1523              :     {
    1524         2736 :       if ((VAR_P (inner)
    1525              :            || TREE_CODE (inner) == PARM_DECL
    1526              :            || TREE_CODE (inner) == RESULT_DECL)
    1527         2736 :           && DECL_REGISTER (inner))
    1528         1790 :         return;
    1529         2736 :       base = inner;
    1530              :       /* If BASE is a fixed size automatic variable or
    1531              :          global variable defined in the current TU and bitpos
    1532              :          fits, don't instrument anything.  */
    1533         2736 :       poly_int64 base_size;
    1534         2736 :       if (offset == NULL_TREE
    1535         2413 :           && maybe_ne (bitpos, 0)
    1536              :           && (VAR_P (base)
    1537              :               || TREE_CODE (base) == PARM_DECL
    1538              :               || TREE_CODE (base) == RESULT_DECL)
    1539         1808 :           && poly_int_tree_p (DECL_SIZE (base), &base_size)
    1540         1808 :           && known_ge (base_size, bitpos)
    1541         4544 :           && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
    1542         1790 :         return;
    1543              :     }
    1544         3567 :   else if (TREE_CODE (inner) == MEM_REF)
    1545              :     {
    1546         3163 :       base = TREE_OPERAND (inner, 0);
    1547         3163 :       if (TREE_CODE (base) == ADDR_EXPR
    1548            0 :           && DECL_P (TREE_OPERAND (base, 0))
    1549            0 :           && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
    1550         3163 :           && !is_global_var (TREE_OPERAND (base, 0)))
    1551              :         return;
    1552         3163 :       moff = TREE_OPERAND (inner, 1);
    1553         3163 :       if (integer_zerop (moff))
    1554         3155 :         moff = NULL_TREE;
    1555              :     }
    1556              :   else
    1557              :     return;
    1558              : 
    1559         4109 :   if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
    1560              :     return;
    1561         4109 :   bytepos = bits_to_bytes_round_down (bitpos);
    1562         4109 :   if (offset == NULL_TREE && known_eq (bytepos, 0) && moff == NULL_TREE)
    1563              :     return;
    1564              : 
    1565         1974 :   tree base_addr = base;
    1566         1974 :   if (decl_p)
    1567          341 :     base_addr = build1 (ADDR_EXPR,
    1568          341 :                         build_pointer_type (TREE_TYPE (base)), base);
    1569         1974 :   t = offset;
    1570         1974 :   if (maybe_ne (bytepos, 0))
    1571              :     {
    1572         1822 :       if (t)
    1573          621 :         t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
    1574              :                          build_int_cst (TREE_TYPE (t), bytepos));
    1575              :       else
    1576         1201 :         t = size_int (bytepos);
    1577              :     }
    1578         1974 :   if (moff)
    1579              :     {
    1580            8 :       if (t)
    1581            0 :         t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
    1582              :                          fold_convert (TREE_TYPE (t), moff));
    1583              :       else
    1584            8 :         t = fold_convert (sizetype, moff);
    1585              :     }
    1586         1974 :   gimple_seq seq, this_seq;
    1587         1974 :   t = force_gimple_operand (t, &seq, true, NULL_TREE);
    1588         1974 :   base_addr = force_gimple_operand (base_addr, &this_seq, true, NULL_TREE);
    1589         1974 :   gimple_seq_add_seq_without_update (&seq, this_seq);
    1590         1974 :   gsi_safe_insert_seq_before (gsi, seq);
    1591         1974 :   instrument_pointer_overflow (gsi, base_addr, t);
    1592              : }
    1593              : 
    1594              : /* Build an ubsan builtin call for the signed-integer-overflow
    1595              :    sanitization.  CODE says what kind of builtin are we building,
    1596              :    LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
    1597              :    are operands of the binary operation.  */
    1598              : 
    1599              : tree
    1600         5490 : ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
    1601              :                               tree op0, tree op1, tree *datap)
    1602              : {
    1603         5490 :   if (flag_sanitize_trap & SANITIZE_SI_OVERFLOW)
    1604          322 :     return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
    1605              : 
    1606         5168 :   tree data;
    1607         5168 :   if (datap && *datap)
    1608              :     data = *datap;
    1609              :   else
    1610         4772 :     data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
    1611              :                               ubsan_type_descriptor (lhstype), NULL_TREE,
    1612              :                               NULL_TREE);
    1613         4772 :   if (datap)
    1614          945 :     *datap = data;
    1615         5168 :   enum built_in_function fn_code;
    1616              : 
    1617         5168 :   switch (code)
    1618              :     {
    1619         1871 :     case PLUS_EXPR:
    1620          596 :       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
    1621         1871 :                 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
    1622              :                 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
    1623              :       break;
    1624         1416 :     case MINUS_EXPR:
    1625          438 :       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
    1626         1416 :                 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
    1627              :                 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
    1628              :       break;
    1629         1320 :     case MULT_EXPR:
    1630          282 :       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
    1631         1320 :                 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
    1632              :                 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
    1633              :       break;
    1634          561 :     case NEGATE_EXPR:
    1635          165 :       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
    1636          561 :                 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
    1637              :                 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
    1638              :       break;
    1639            0 :     default:
    1640            0 :       gcc_unreachable ();
    1641              :     }
    1642         5168 :   tree fn = builtin_decl_explicit (fn_code);
    1643        10336 :   return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
    1644              :                               build_fold_addr_expr_loc (loc, data),
    1645              :                               ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
    1646              :                               op1
    1647         4607 :                               ? ubsan_encode_value (op1,
    1648              :                                                     UBSAN_ENCODE_VALUE_RTL)
    1649         5168 :                               : NULL_TREE);
    1650              : }
    1651              : 
    1652              : /* Perform the signed integer instrumentation.  GSI is the iterator
    1653              :    pointing at statement we are trying to instrument.  */
    1654              : 
    1655              : static void
    1656        53535 : instrument_si_overflow (gimple_stmt_iterator gsi)
    1657              : {
    1658        53535 :   gimple *stmt = gsi_stmt (gsi);
    1659        53535 :   tree_code code = gimple_assign_rhs_code (stmt);
    1660        53535 :   tree lhs = gimple_assign_lhs (stmt);
    1661        53535 :   tree lhstype = TREE_TYPE (lhs);
    1662        53535 :   tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
    1663        53535 :   tree a, b;
    1664        53535 :   gimple *g;
    1665              : 
    1666              :   /* If this is not a signed operation, don't instrument anything here.
    1667              :      Also punt on bit-fields.  */
    1668        53535 :   if (!INTEGRAL_TYPE_P (lhsinner)
    1669        49104 :       || TYPE_OVERFLOW_WRAPS (lhsinner)
    1670        85676 :       || (TREE_CODE (lhsinner) != BITINT_TYPE
    1671        63034 :           && maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)),
    1672        31517 :                        TYPE_PRECISION (lhsinner))))
    1673        21470 :     return;
    1674              : 
    1675        32065 :   switch (code)
    1676              :     {
    1677         6015 :     case MINUS_EXPR:
    1678         6015 :     case PLUS_EXPR:
    1679         6015 :     case MULT_EXPR:
    1680              :       /* Transform
    1681              :          i = u {+,-,*} 5;
    1682              :          into
    1683              :          i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5);  */
    1684         6015 :       a = gimple_assign_rhs1 (stmt);
    1685         6015 :       b = gimple_assign_rhs2 (stmt);
    1686         9649 :       g = gimple_build_call_internal (code == PLUS_EXPR
    1687              :                                       ? IFN_UBSAN_CHECK_ADD
    1688              :                                       : code == MINUS_EXPR
    1689         3634 :                                       ? IFN_UBSAN_CHECK_SUB
    1690              :                                       : IFN_UBSAN_CHECK_MUL, 2, a, b);
    1691         6015 :       gimple_call_set_lhs (g, lhs);
    1692         6015 :       gsi_replace (&gsi, g, true);
    1693         6015 :       break;
    1694          524 :     case NEGATE_EXPR:
    1695              :       /* Represent i = -u;
    1696              :          as
    1697              :          i = UBSAN_CHECK_SUB (0, u);  */
    1698          524 :       a = build_zero_cst (lhstype);
    1699          524 :       b = gimple_assign_rhs1 (stmt);
    1700          524 :       g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
    1701          524 :       gimple_call_set_lhs (g, lhs);
    1702          524 :       gsi_replace (&gsi, g, true);
    1703          524 :       break;
    1704           10 :     case ABS_EXPR:
    1705              :       /* Transform i = ABS_EXPR<u>;
    1706              :          into
    1707              :          _N = UBSAN_CHECK_SUB (0, u);
    1708              :          i = ABS_EXPR<_N>;  */
    1709           10 :       a = build_zero_cst (lhstype);
    1710           10 :       b = gimple_assign_rhs1 (stmt);
    1711           10 :       g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
    1712           10 :       a = make_ssa_name (lhstype);
    1713           10 :       gimple_call_set_lhs (g, a);
    1714           10 :       gimple_set_location (g, gimple_location (stmt));
    1715           10 :       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
    1716           10 :       gimple_assign_set_rhs1 (stmt, a);
    1717           10 :       update_stmt (stmt);
    1718           10 :       break;
    1719              :     default:
    1720              :       break;
    1721              :     }
    1722              : }
    1723              : 
    1724              : /* Instrument loads from (non-bitfield) bool and C++ enum values
    1725              :    to check if the memory value is outside of the range of the valid
    1726              :    type values.  */
    1727              : 
    1728              : static void
    1729         4605 : instrument_bool_enum_load (gimple_stmt_iterator *gsi)
    1730              : {
    1731         4605 :   gimple *stmt = gsi_stmt (*gsi);
    1732         4605 :   tree rhs = gimple_assign_rhs1 (stmt);
    1733         4605 :   tree type = TREE_TYPE (rhs);
    1734         4605 :   tree minv = NULL_TREE, maxv = NULL_TREE;
    1735              : 
    1736         4605 :   if (TREE_CODE (type) == BOOLEAN_TYPE
    1737         4605 :       && sanitize_flags_p (SANITIZE_BOOL))
    1738              :     {
    1739           69 :       minv = boolean_false_node;
    1740           69 :       maxv = boolean_true_node;
    1741              :     }
    1742         4536 :   else if (TREE_CODE (type) == ENUMERAL_TYPE
    1743           40 :            && sanitize_flags_p (SANITIZE_ENUM)
    1744           40 :            && TREE_TYPE (type) != NULL_TREE
    1745           40 :            && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
    1746         4616 :            && (TYPE_PRECISION (TREE_TYPE (type))
    1747           40 :                < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
    1748              :     {
    1749           12 :       minv = TYPE_MIN_VALUE (TREE_TYPE (type));
    1750           12 :       maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
    1751              :     }
    1752              :   else
    1753         4524 :     return;
    1754              : 
    1755           81 :   int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
    1756           81 :   poly_int64 bitsize, bitpos;
    1757           81 :   tree offset;
    1758           81 :   machine_mode mode;
    1759           81 :   int volatilep = 0, reversep, unsignedp = 0;
    1760           81 :   tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
    1761              :                                    &unsignedp, &reversep, &volatilep);
    1762           81 :   tree utype = build_nonstandard_integer_type (modebitsize, 1);
    1763              : 
    1764           58 :   if ((VAR_P (base) && DECL_HARD_REGISTER (base))
    1765          162 :       || !multiple_p (bitpos, modebitsize)
    1766           81 :       || maybe_ne (bitsize, modebitsize)
    1767          162 :       || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
    1768          162 :       || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
    1769            0 :     return;
    1770              : 
    1771           81 :   addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (rhs));
    1772           81 :   if (as != TYPE_ADDR_SPACE (utype))
    1773            7 :     utype = build_qualified_type (utype, TYPE_QUALS (utype)
    1774            7 :                                          | ENCODE_QUAL_ADDR_SPACE (as));
    1775           81 :   bool ends_bb = stmt_ends_bb_p (stmt);
    1776           81 :   location_t loc = gimple_location (stmt);
    1777           81 :   tree lhs = gimple_assign_lhs (stmt);
    1778           81 :   tree ptype = build_pointer_type (TREE_TYPE (rhs));
    1779           81 :   tree atype = reference_alias_ptr_type (rhs);
    1780           81 :   gimple *g = gimple_build_assign (make_ssa_name (ptype),
    1781              :                                    build_fold_addr_expr (rhs));
    1782           81 :   gimple_set_location (g, loc);
    1783           81 :   gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1784           81 :   tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
    1785              :                      build_int_cst (atype, 0));
    1786           81 :   tree urhs = make_ssa_name (utype);
    1787           81 :   if (ends_bb)
    1788              :     {
    1789            3 :       gimple_assign_set_lhs (stmt, urhs);
    1790            3 :       g = gimple_build_assign (lhs, NOP_EXPR, urhs);
    1791            3 :       gimple_set_location (g, loc);
    1792            3 :       edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
    1793            3 :       gsi_insert_on_edge_immediate (e, g);
    1794            3 :       gimple_assign_set_rhs_from_tree (gsi, mem);
    1795            3 :       update_stmt (stmt);
    1796            3 :       *gsi = gsi_for_stmt (g);
    1797            3 :       g = stmt;
    1798              :     }
    1799              :   else
    1800              :     {
    1801           78 :       g = gimple_build_assign (urhs, mem);
    1802           78 :       gimple_set_location (g, loc);
    1803           78 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1804              :     }
    1805           81 :   minv = fold_convert (utype, minv);
    1806           81 :   maxv = fold_convert (utype, maxv);
    1807           81 :   if (!integer_zerop (minv))
    1808              :     {
    1809            3 :       g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
    1810            3 :       gimple_set_location (g, loc);
    1811            3 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    1812              :     }
    1813              : 
    1814           81 :   gimple_stmt_iterator gsi2 = *gsi;
    1815           81 :   basic_block then_bb, fallthru_bb;
    1816           81 :   *gsi = create_cond_insert_point (gsi, true, false, true,
    1817              :                                    &then_bb, &fallthru_bb);
    1818           81 :   g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
    1819              :                          int_const_binop (MINUS_EXPR, maxv, minv),
    1820              :                          NULL_TREE, NULL_TREE);
    1821           81 :   gimple_set_location (g, loc);
    1822           81 :   gsi_insert_after (gsi, g, GSI_NEW_STMT);
    1823              : 
    1824           81 :   if (!ends_bb)
    1825              :     {
    1826           78 :       gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
    1827           78 :       update_stmt (stmt);
    1828              :     }
    1829              : 
    1830           81 :   gsi2 = gsi_after_labels (then_bb);
    1831           81 :   if (flag_sanitize_trap & (TREE_CODE (type) == BOOLEAN_TYPE
    1832           81 :                             ? SANITIZE_BOOL : SANITIZE_ENUM))
    1833            3 :     g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
    1834              :   else
    1835              :     {
    1836           78 :       tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
    1837              :                                      ubsan_type_descriptor (type), NULL_TREE,
    1838              :                                      NULL_TREE);
    1839           78 :       data = build_fold_addr_expr_loc (loc, data);
    1840           16 :       enum built_in_function bcode
    1841          156 :         = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
    1842           78 :                                     ? SANITIZE_BOOL : SANITIZE_ENUM))
    1843           78 :           ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
    1844              :           : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
    1845           78 :       tree fn = builtin_decl_explicit (bcode);
    1846              : 
    1847           78 :       tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
    1848           78 :       val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
    1849              :                                       GSI_SAME_STMT);
    1850           78 :       g = gimple_build_call (fn, 2, data, val);
    1851              :     }
    1852           81 :   gimple_set_location (g, loc);
    1853           81 :   gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
    1854           81 :   ubsan_create_edge (g);
    1855           81 :   *gsi = gsi_for_stmt (stmt);
    1856              : }
    1857              : 
    1858              : /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
    1859              :    new style handlers.  Libubsan uses heuristics to destinguish between old and
    1860              :    new styles and relies on these properties for filename:
    1861              : 
    1862              :    a) Location's filename must not be NULL.
    1863              :    b) Location's filename must not be equal to "".
    1864              :    c) Location's filename must not be equal to "\1".
    1865              :    d) First two bytes of filename must not contain '\xff' symbol.  */
    1866              : 
    1867              : static bool
    1868        12097 : ubsan_use_new_style_p (location_t loc)
    1869              : {
    1870        12097 :   if (loc == UNKNOWN_LOCATION)
    1871              :     return false;
    1872              : 
    1873        12097 :   expanded_location xloc = expand_location (loc);
    1874        12097 :   if (xloc.file == NULL || startswith (xloc.file, "\1")
    1875        12097 :       || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
    1876        24194 :       || xloc.file[1] == '\xff')
    1877              :     return false;
    1878              : 
    1879              :   return true;
    1880              : }
    1881              : 
    1882              : /* Instrument float point-to-integer conversion.  TYPE is an integer type of
    1883              :    destination, EXPR is floating-point expression.  */
    1884              : 
    1885              : tree
    1886        16702 : ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
    1887              : {
    1888        16702 :   tree expr_type = TREE_TYPE (expr);
    1889        16702 :   tree t, tt, fn, min, max;
    1890        16702 :   machine_mode mode = TYPE_MODE (expr_type);
    1891        16702 :   int prec = TYPE_PRECISION (type);
    1892        16702 :   bool uns_p = TYPE_UNSIGNED (type);
    1893        16702 :   if (loc == UNKNOWN_LOCATION)
    1894         5222 :     loc = input_location;
    1895              : 
    1896              :   /* Float to integer conversion first truncates toward zero, so
    1897              :      even signed char c = 127.875f; is not problematic.
    1898              :      Therefore, we should complain only if EXPR is unordered or smaller
    1899              :      or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
    1900              :      TYPE_MAX_VALUE + 1.0.  */
    1901        16702 :   if (REAL_MODE_FORMAT (mode)->b == 2)
    1902              :     {
    1903              :       /* For maximum, TYPE_MAX_VALUE might not be representable
    1904              :          in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
    1905              :          EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
    1906              :          either representable or infinity.  */
    1907        16504 :       REAL_VALUE_TYPE maxval = dconst1;
    1908        16504 :       SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
    1909        16504 :       real_convert (&maxval, mode, &maxval);
    1910        16504 :       max = build_real (expr_type, maxval);
    1911              : 
    1912              :       /* For unsigned, assume -1.0 is always representable.  */
    1913        16504 :       if (uns_p)
    1914         7050 :         min = build_minus_one_cst (expr_type);
    1915              :       else
    1916              :         {
    1917              :           /* TYPE_MIN_VALUE is generally representable (or -inf),
    1918              :              but TYPE_MIN_VALUE - 1.0 might not be.  */
    1919         9454 :           REAL_VALUE_TYPE minval = dconstm1, minval2;
    1920         9454 :           SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
    1921         9454 :           real_convert (&minval, mode, &minval);
    1922         9454 :           real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
    1923         9454 :           real_convert (&minval2, mode, &minval2);
    1924         9454 :           if (real_compare (EQ_EXPR, &minval, &minval2)
    1925         9454 :               && !real_isinf (&minval))
    1926              :             {
    1927              :               /* If TYPE_MIN_VALUE - 1.0 is not representable and
    1928              :                  rounds to TYPE_MIN_VALUE, we need to subtract
    1929              :                  more.  As REAL_MODE_FORMAT (mode)->p is the number
    1930              :                  of base digits, we want to subtract a number that
    1931              :                  will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
    1932              :                  times smaller than minval.  */
    1933         2553 :               minval2 = dconst1;
    1934         2553 :               gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
    1935         2553 :               SET_REAL_EXP (&minval2,
    1936              :                             REAL_EXP (&minval2) + prec - 1
    1937              :                             - REAL_MODE_FORMAT (mode)->p + 1);
    1938         2553 :               real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
    1939         2553 :               real_convert (&minval2, mode, &minval2);
    1940              :             }
    1941         9454 :           min = build_real (expr_type, minval2);
    1942              :         }
    1943              :     }
    1944          198 :   else if (REAL_MODE_FORMAT (mode)->b == 10)
    1945              :     {
    1946              :       /* For _Decimal128 up to 34 decimal digits, - sign,
    1947              :          dot, e, exponent.  */
    1948          198 :       char buf[64];
    1949          198 :       int p = REAL_MODE_FORMAT (mode)->p;
    1950          198 :       REAL_VALUE_TYPE maxval, minval;
    1951              : 
    1952              :       /* Use mpfr_snprintf rounding to compute the smallest
    1953              :          representable decimal number greater or equal than
    1954              :          1 << (prec - !uns_p).  */
    1955          198 :       auto_mpfr m (prec + 2);
    1956          198 :       mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
    1957          198 :       mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, (mpfr_srcptr) m);
    1958          198 :       decimal_real_from_string (&maxval, buf);
    1959          198 :       max = build_real (expr_type, maxval);
    1960              : 
    1961              :       /* For unsigned, assume -1.0 is always representable.  */
    1962          198 :       if (uns_p)
    1963           90 :         min = build_minus_one_cst (expr_type);
    1964              :       else
    1965              :         {
    1966              :           /* Use mpfr_snprintf rounding to compute the largest
    1967              :              representable decimal number less or equal than
    1968              :              (-1 << (prec - 1)) - 1.  */
    1969          108 :           mpfr_set_si_2exp (m, -1, prec - 1, MPFR_RNDN);
    1970          108 :           mpfr_sub_ui (m, m, 1, MPFR_RNDN);
    1971          108 :           mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, (mpfr_srcptr) m);
    1972          108 :           decimal_real_from_string (&minval, buf);
    1973          108 :           min = build_real (expr_type, minval);
    1974              :         }
    1975          198 :     }
    1976              :   else
    1977              :     return NULL_TREE;
    1978              : 
    1979        16702 :   if (HONOR_NANS (mode))
    1980              :     {
    1981        16688 :       t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
    1982        16688 :       tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
    1983              :     }
    1984              :   else
    1985              :     {
    1986           14 :       t = fold_build2 (LE_EXPR, boolean_type_node, expr, min);
    1987           14 :       tt = fold_build2 (GE_EXPR, boolean_type_node, expr, max);
    1988              :     }
    1989        16702 :   t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
    1990        16702 :   if (integer_zerop (t))
    1991              :     return NULL_TREE;
    1992              : 
    1993        12097 :   if (flag_sanitize_trap & SANITIZE_FLOAT_CAST)
    1994            0 :     fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
    1995              :   else
    1996              :     {
    1997        12097 :       location_t *loc_ptr = NULL;
    1998        12097 :       unsigned num_locations = 0;
    1999              :       /* Figure out if we can propagate location to ubsan_data and use new
    2000              :          style handlers in libubsan.  */
    2001        12097 :       if (ubsan_use_new_style_p (loc))
    2002              :         {
    2003        12097 :           loc_ptr = &loc;
    2004        12097 :           num_locations = 1;
    2005              :         }
    2006              :       /* Create the __ubsan_handle_float_cast_overflow fn call.  */
    2007        12097 :       tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
    2008              :                                      num_locations, loc_ptr,
    2009              :                                      ubsan_type_descriptor (expr_type),
    2010              :                                      ubsan_type_descriptor (type), NULL_TREE,
    2011              :                                      NULL_TREE);
    2012          294 :       enum built_in_function bcode
    2013        12097 :         = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
    2014        12097 :           ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
    2015              :           : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
    2016        12097 :       fn = builtin_decl_explicit (bcode);
    2017        12097 :       fn = build_call_expr_loc (loc, fn, 2,
    2018              :                                 build_fold_addr_expr_loc (loc, data),
    2019              :                                 ubsan_encode_value (expr));
    2020              :     }
    2021              : 
    2022        12097 :   return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
    2023              : }
    2024              : 
    2025              : /* Instrument values passed to function arguments with nonnull attribute.  */
    2026              : 
    2027              : static void
    2028         4670 : instrument_nonnull_arg (gimple_stmt_iterator *gsi)
    2029              : {
    2030         4670 :   gimple *stmt = gsi_stmt (*gsi);
    2031         4670 :   location_t loc[2];
    2032              :   /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
    2033              :      while for nonnull sanitization it is clear.  */
    2034         4670 :   int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
    2035         4670 :   flag_delete_null_pointer_checks = 1;
    2036         4670 :   loc[0] = gimple_location (stmt);
    2037         4670 :   loc[1] = UNKNOWN_LOCATION;
    2038        13720 :   for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
    2039              :     {
    2040         9050 :       tree arg = gimple_call_arg (stmt, i);
    2041         9050 :       tree arg2, arg3;
    2042        14336 :       if (POINTER_TYPE_P (TREE_TYPE (arg))
    2043         9224 :           && infer_nonnull_range_by_attribute (stmt, arg, &arg2, &arg3))
    2044              :         {
    2045          968 :           gimple *g;
    2046          968 :           if (!is_gimple_val (arg))
    2047              :             {
    2048            0 :               g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
    2049            0 :               gimple_set_location (g, loc[0]);
    2050            0 :               gsi_safe_insert_before (gsi, g);
    2051            0 :               arg = gimple_assign_lhs (g);
    2052              :             }
    2053          968 :           if (arg2 == arg3)
    2054          928 :             arg3 = NULL_TREE;
    2055          968 :           if (arg2 && !is_gimple_val (arg2))
    2056              :             {
    2057            0 :               g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg2)), arg2);
    2058            0 :               gimple_set_location (g, loc[0]);
    2059            0 :               gsi_safe_insert_before (gsi, g);
    2060            0 :               arg2 = gimple_assign_lhs (g);
    2061              :             }
    2062          968 :           if (arg3 && !is_gimple_val (arg3))
    2063              :             {
    2064            0 :               g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg3)), arg3);
    2065            0 :               gimple_set_location (g, loc[0]);
    2066            0 :               gsi_safe_insert_before (gsi, g);
    2067            0 :               arg3 = gimple_assign_lhs (g);
    2068              :             }
    2069              : 
    2070          968 :           basic_block then_bb, fallthru_bb;
    2071          968 :           *gsi = create_cond_insert_point (gsi, true, false, true,
    2072              :                                            &then_bb, &fallthru_bb);
    2073          968 :           g = gimple_build_cond (EQ_EXPR, arg,
    2074          968 :                                  build_zero_cst (TREE_TYPE (arg)),
    2075              :                                  NULL_TREE, NULL_TREE);
    2076          968 :           gimple_set_location (g, loc[0]);
    2077          968 :           gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2078              : 
    2079          968 :           *gsi = gsi_after_labels (then_bb);
    2080          968 :           if (arg2)
    2081              :             {
    2082          132 :               *gsi = create_cond_insert_point (gsi, true, false, true,
    2083              :                                                &then_bb, &fallthru_bb);
    2084          132 :               g = gimple_build_cond (NE_EXPR, arg2,
    2085          132 :                                      build_zero_cst (TREE_TYPE (arg2)),
    2086              :                                      NULL_TREE, NULL_TREE);
    2087          132 :               gimple_set_location (g, loc[0]);
    2088          132 :               gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2089              : 
    2090          132 :               *gsi = gsi_after_labels (then_bb);
    2091              :             }
    2092          968 :           if (arg3)
    2093              :             {
    2094           40 :               *gsi = create_cond_insert_point (gsi, true, false, true,
    2095              :                                                &then_bb, &fallthru_bb);
    2096           40 :               g = gimple_build_cond (NE_EXPR, arg3,
    2097           40 :                                      build_zero_cst (TREE_TYPE (arg3)),
    2098              :                                      NULL_TREE, NULL_TREE);
    2099           40 :               gimple_set_location (g, loc[0]);
    2100           40 :               gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2101              : 
    2102           40 :               *gsi = gsi_after_labels (then_bb);
    2103              :             }
    2104          968 :           if (flag_sanitize_trap & SANITIZE_NONNULL_ATTRIBUTE)
    2105          140 :             g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
    2106              :           else
    2107              :             {
    2108          828 :               tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
    2109              :                                              2, loc, NULL_TREE,
    2110              :                                              build_int_cst (integer_type_node,
    2111          828 :                                                             i + 1),
    2112              :                                              NULL_TREE);
    2113          828 :               data = build_fold_addr_expr_loc (loc[0], data);
    2114          210 :               enum built_in_function bcode
    2115          828 :                 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
    2116          828 :                   ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
    2117              :                   : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
    2118          828 :               tree fn = builtin_decl_explicit (bcode);
    2119              : 
    2120          828 :               g = gimple_build_call (fn, 1, data);
    2121              :             }
    2122          968 :           gimple_set_location (g, loc[0]);
    2123          968 :           gsi_safe_insert_before (gsi, g);
    2124          968 :           ubsan_create_edge (g);
    2125              :         }
    2126         9050 :       *gsi = gsi_for_stmt (stmt);
    2127              :     }
    2128         4670 :   flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
    2129         4670 : }
    2130              : 
    2131              : /* Instrument returns in functions with returns_nonnull attribute.  */
    2132              : 
    2133              : static void
    2134         2671 : instrument_nonnull_return (gimple_stmt_iterator *gsi)
    2135              : {
    2136         2671 :   greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
    2137         2671 :   location_t loc[2];
    2138         2671 :   tree arg = gimple_return_retval (stmt);
    2139              :   /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
    2140              :      while for nonnull return sanitization it is clear.  */
    2141         2671 :   int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
    2142         2671 :   flag_delete_null_pointer_checks = 1;
    2143         2671 :   loc[0] = gimple_location (stmt);
    2144         2671 :   loc[1] = UNKNOWN_LOCATION;
    2145         2671 :   if (arg
    2146         1851 :       && POINTER_TYPE_P (TREE_TYPE (arg))
    2147          101 :       && is_gimple_val (arg)
    2148         2772 :       && infer_nonnull_range_by_attribute (stmt, arg))
    2149              :     {
    2150           50 :       basic_block then_bb, fallthru_bb;
    2151           50 :       *gsi = create_cond_insert_point (gsi, true, false, true,
    2152              :                                        &then_bb, &fallthru_bb);
    2153           50 :       gimple *g = gimple_build_cond (EQ_EXPR, arg,
    2154           50 :                                     build_zero_cst (TREE_TYPE (arg)),
    2155              :                                     NULL_TREE, NULL_TREE);
    2156           50 :       gimple_set_location (g, loc[0]);
    2157           50 :       gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2158              : 
    2159           50 :       *gsi = gsi_after_labels (then_bb);
    2160           50 :       if (flag_sanitize_trap & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
    2161           20 :         g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
    2162              :       else
    2163              :         {
    2164           30 :           tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
    2165              :                                          1, &loc[1], NULL_TREE, NULL_TREE);
    2166           30 :           data = build_fold_addr_expr_loc (loc[0], data);
    2167           30 :           tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
    2168              :                                           1, &loc[0], NULL_TREE, NULL_TREE);
    2169           30 :           data2 = build_fold_addr_expr_loc (loc[0], data2);
    2170           20 :           enum built_in_function bcode
    2171           30 :             = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
    2172           30 :               ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
    2173              :               : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
    2174           30 :           tree fn = builtin_decl_explicit (bcode);
    2175              : 
    2176           30 :           g = gimple_build_call (fn, 2, data, data2);
    2177              :         }
    2178           50 :       gimple_set_location (g, loc[0]);
    2179           50 :       gsi_safe_insert_before (gsi, g);
    2180           50 :       ubsan_create_edge (g);
    2181           50 :       *gsi = gsi_for_stmt (stmt);
    2182              :     }
    2183         2671 :   flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
    2184         2671 : }
    2185              : 
    2186              : /* Instrument memory references.  Here we check whether the pointer
    2187              :    points to an out-of-bounds location.  */
    2188              : 
    2189              : static void
    2190         9102 : instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
    2191              : {
    2192         9102 :   gimple *stmt = gsi_stmt (*gsi);
    2193         9102 :   location_t loc = gimple_location (stmt);
    2194         9102 :   tree type;
    2195         9102 :   tree index = NULL_TREE;
    2196         9102 :   HOST_WIDE_INT size_in_bytes;
    2197              : 
    2198         9102 :   type = TREE_TYPE (t);
    2199         9102 :   if (VOID_TYPE_P (type))
    2200         6682 :     return;
    2201              : 
    2202         9102 :   switch (TREE_CODE (t))
    2203              :     {
    2204         4204 :     case COMPONENT_REF:
    2205         4204 :       if (TREE_CODE (t) == COMPONENT_REF
    2206         4204 :           && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
    2207              :         {
    2208           73 :           tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
    2209           73 :           t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
    2210           73 :                       repr, TREE_OPERAND (t, 2));
    2211              :         }
    2212              :       break;
    2213          336 :     case ARRAY_REF:
    2214          336 :       index = TREE_OPERAND (t, 1);
    2215          336 :       break;
    2216              :     case INDIRECT_REF:
    2217              :     case MEM_REF:
    2218              :     case VAR_DECL:
    2219              :     case PARM_DECL:
    2220              :     case RESULT_DECL:
    2221              :       break;
    2222              :     default:
    2223              :       return;
    2224              :     }
    2225              : 
    2226         9084 :   size_in_bytes = int_size_in_bytes (type);
    2227         9084 :   if (size_in_bytes <= 0)
    2228              :     return;
    2229              : 
    2230         9078 :   poly_int64 bitsize, bitpos;
    2231         9078 :   tree offset;
    2232         9078 :   machine_mode mode;
    2233         9078 :   int volatilep = 0, reversep, unsignedp = 0;
    2234         9078 :   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
    2235              :                                     &unsignedp, &reversep, &volatilep);
    2236              : 
    2237         9078 :   if (!multiple_p (bitpos, BITS_PER_UNIT)
    2238         9078 :       || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
    2239              :     return;
    2240              : 
    2241         9054 :   bool decl_p = DECL_P (inner);
    2242         9054 :   tree base;
    2243         9054 :   if (decl_p)
    2244              :     {
    2245         6180 :       if ((VAR_P (inner)
    2246              :            || TREE_CODE (inner) == PARM_DECL
    2247              :            || TREE_CODE (inner) == RESULT_DECL)
    2248         6180 :           && DECL_REGISTER (inner))
    2249              :         return;
    2250         6173 :       if (t == inner && !is_global_var (t))
    2251              :         return;
    2252              :       base = inner;
    2253              :     }
    2254         2874 :   else if (TREE_CODE (inner) == MEM_REF)
    2255         2867 :     base = TREE_OPERAND (inner, 0);
    2256              :   else
    2257              :     return;
    2258         8129 :   tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
    2259              : 
    2260        16765 :   while (TREE_CODE (base) == SSA_NAME)
    2261              :     {
    2262         3368 :       gimple *def_stmt = SSA_NAME_DEF_STMT (base);
    2263         3368 :       if (gimple_assign_ssa_name_copy_p (def_stmt)
    2264         3134 :           || (gimple_assign_cast_p (def_stmt)
    2265            3 :               && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
    2266         6502 :           || (is_gimple_assign (def_stmt)
    2267          737 :               && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
    2268              :         {
    2269          517 :           tree rhs1 = gimple_assign_rhs1 (def_stmt);
    2270          517 :           if (TREE_CODE (rhs1) == SSA_NAME
    2271          517 :               && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
    2272              :             break;
    2273              :           else
    2274              :             base = rhs1;
    2275              :         }
    2276              :       else
    2277              :         break;
    2278              :     }
    2279              : 
    2280         8129 :   if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
    2281              :     return;
    2282              : 
    2283         8129 :   tree sizet;
    2284         8129 :   tree base_addr = base;
    2285         8129 :   gimple *bos_stmt = NULL;
    2286         8129 :   gimple_seq seq = NULL;
    2287         8129 :   if (decl_p)
    2288         5262 :     base_addr = build1 (ADDR_EXPR,
    2289         5262 :                         build_pointer_type (TREE_TYPE (base)), base);
    2290         8129 :   if (compute_builtin_object_size (base_addr, OST_DYNAMIC, &sizet))
    2291              :     ;
    2292         2861 :   else if (optimize)
    2293              :     {
    2294         2115 :       if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
    2295            0 :         loc = input_location;
    2296              :       /* Generate __builtin_dynamic_object_size call.  */
    2297         2115 :       sizet = builtin_decl_explicit (BUILT_IN_DYNAMIC_OBJECT_SIZE);
    2298         2115 :       sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
    2299              :                                    integer_zero_node);
    2300         2115 :       sizet = force_gimple_operand (sizet, &seq, false, NULL_TREE);
    2301              :       /* If the call above didn't end up being an integer constant, go one
    2302              :          statement back and get the __builtin_object_size stmt.  Save it,
    2303              :          we might need it later.  */
    2304         2115 :       if (SSA_VAR_P (sizet))
    2305         4230 :         bos_stmt = gsi_stmt (gsi_last (seq));
    2306              :     }
    2307              :   else
    2308              :     return;
    2309              : 
    2310              :   /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
    2311              :      call.  */
    2312              :   /* ptr + sizeof (*ptr) - base */
    2313         7383 :   t = fold_build2 (MINUS_EXPR, sizetype,
    2314              :                    fold_convert (pointer_sized_int_node, ptr),
    2315              :                    fold_convert (pointer_sized_int_node, base_addr));
    2316         7383 :   t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
    2317              : 
    2318              :   /* Perhaps we can omit the check.  */
    2319         7383 :   if (TREE_CODE (t) == INTEGER_CST
    2320         6323 :       && TREE_CODE (sizet) == INTEGER_CST
    2321        12333 :       && tree_int_cst_le (t, sizet))
    2322              :     return;
    2323              : 
    2324         2440 :   if (index != NULL_TREE
    2325          134 :       && TREE_CODE (index) == SSA_NAME
    2326           94 :       && TREE_CODE (sizet) == INTEGER_CST)
    2327              :     {
    2328           80 :       gimple *def = SSA_NAME_DEF_STMT (index);
    2329           80 :       if (is_gimple_assign (def)
    2330           73 :           && gimple_assign_rhs_code (def) == BIT_AND_EXPR
    2331          109 :           && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
    2332              :         {
    2333           26 :           tree cst = gimple_assign_rhs2 (def);
    2334           26 :           tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
    2335              :                                  TYPE_SIZE_UNIT (type));
    2336           26 :           if (tree_int_cst_sgn (cst) >= 0
    2337           26 :               && tree_int_cst_lt (cst, sz))
    2338              :             return;
    2339              :         }
    2340              :     }
    2341              : 
    2342         2420 :   if (DECL_P (base)
    2343          299 :       && decl_function_context (base) == current_function_decl
    2344         2677 :       && !TREE_ADDRESSABLE (base))
    2345           61 :     mark_addressable (base);
    2346              : 
    2347              :   /* We have to emit the check.  */
    2348         2420 :   gimple_seq this_seq;
    2349         2420 :   t = force_gimple_operand (t, &this_seq, true, NULL_TREE);
    2350         2420 :   gimple_seq_add_seq_without_update (&seq, this_seq);
    2351         2420 :   ptr = force_gimple_operand (ptr, &this_seq, true, NULL_TREE);
    2352         2420 :   gimple_seq_add_seq_without_update (&seq, this_seq);
    2353         2420 :   gsi_safe_insert_seq_before (gsi, seq);
    2354              : 
    2355         2420 :   if (bos_stmt
    2356         2420 :       && gimple_call_builtin_p (bos_stmt, BUILT_IN_DYNAMIC_OBJECT_SIZE))
    2357         2115 :     ubsan_create_edge (bos_stmt);
    2358              : 
    2359         2420 :   tree ckind = build_int_cst (unsigned_char_type_node,
    2360         3952 :                               is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
    2361         2420 :   gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
    2362              :                                          ptr, t, sizet, ckind);
    2363         2420 :   gimple_set_location (g, loc);
    2364         2420 :   gsi_safe_insert_before (gsi, g);
    2365              : }
    2366              : 
    2367              : /* Instrument values passed to builtin functions.  */
    2368              : 
    2369              : static void
    2370         1342 : instrument_builtin (gimple_stmt_iterator *gsi)
    2371              : {
    2372         1342 :   gimple *stmt = gsi_stmt (*gsi);
    2373         1342 :   location_t loc = gimple_location (stmt);
    2374         1342 :   tree arg;
    2375         1342 :   enum built_in_function fcode
    2376         1342 :     = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
    2377         1342 :   int kind = 0;
    2378         1342 :   switch (fcode)
    2379              :     {
    2380           80 :     CASE_INT_FN (BUILT_IN_CLZ):
    2381           80 :       kind = 1;
    2382          180 :       gcc_fallthrough ();
    2383          180 :     CASE_INT_FN (BUILT_IN_CTZ):
    2384          180 :       arg = gimple_call_arg (stmt, 0);
    2385          180 :       if (!integer_nonzerop (arg))
    2386              :         {
    2387          180 :           gimple *g;
    2388          180 :           if (!is_gimple_val (arg))
    2389              :             {
    2390            0 :               g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
    2391            0 :               gimple_set_location (g, loc);
    2392            0 :               gsi_insert_before (gsi, g, GSI_SAME_STMT);
    2393            0 :               arg = gimple_assign_lhs (g);
    2394              :             }
    2395              : 
    2396          180 :           basic_block then_bb, fallthru_bb;
    2397          180 :           *gsi = create_cond_insert_point (gsi, true, false, true,
    2398              :                                            &then_bb, &fallthru_bb);
    2399          180 :           g = gimple_build_cond (EQ_EXPR, arg,
    2400          180 :                                  build_zero_cst (TREE_TYPE (arg)),
    2401              :                                  NULL_TREE, NULL_TREE);
    2402          180 :           gimple_set_location (g, loc);
    2403          180 :           gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2404              : 
    2405          180 :           *gsi = gsi_after_labels (then_bb);
    2406          180 :           if (flag_sanitize_trap & SANITIZE_BUILTIN)
    2407            0 :             g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
    2408              :           else
    2409              :             {
    2410          180 :               tree t = build_int_cst (unsigned_char_type_node, kind);
    2411          180 :               tree data = ubsan_create_data ("__ubsan_builtin_data",
    2412              :                                              1, &loc, NULL_TREE, t, NULL_TREE);
    2413          180 :               data = build_fold_addr_expr_loc (loc, data);
    2414            0 :               enum built_in_function bcode
    2415          180 :                 = (flag_sanitize_recover & SANITIZE_BUILTIN)
    2416          180 :                   ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
    2417              :                   : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
    2418          180 :               tree fn = builtin_decl_explicit (bcode);
    2419              : 
    2420          180 :               g = gimple_build_call (fn, 1, data);
    2421              :             }
    2422          180 :           gimple_set_location (g, loc);
    2423          180 :           gsi_insert_before (gsi, g, GSI_SAME_STMT);
    2424          180 :           ubsan_create_edge (g);
    2425              :         }
    2426          180 :       *gsi = gsi_for_stmt (stmt);
    2427          180 :       break;
    2428              :     default:
    2429              :       break;
    2430              :     }
    2431         1342 : }
    2432              : 
    2433              : namespace {
    2434              : 
    2435              : const pass_data pass_data_ubsan =
    2436              : {
    2437              :   GIMPLE_PASS, /* type */
    2438              :   "ubsan", /* name */
    2439              :   OPTGROUP_NONE, /* optinfo_flags */
    2440              :   TV_TREE_UBSAN, /* tv_id */
    2441              :   ( PROP_cfg | PROP_ssa ), /* properties_required */
    2442              :   0, /* properties_provided */
    2443              :   0, /* properties_destroyed */
    2444              :   0, /* todo_flags_start */
    2445              :   TODO_update_ssa, /* todo_flags_finish */
    2446              : };
    2447              : 
    2448              : class pass_ubsan : public gimple_opt_pass
    2449              : {
    2450              : public:
    2451       285722 :   pass_ubsan (gcc::context *ctxt)
    2452       571444 :     : gimple_opt_pass (pass_data_ubsan, ctxt)
    2453              :   {}
    2454              : 
    2455              :   /* opt_pass methods: */
    2456      2848664 :   bool gate (function *) final override
    2457              :     {
    2458      2848664 :       return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
    2459              :                                 | SANITIZE_BOOL | SANITIZE_ENUM
    2460              :                                 | SANITIZE_ALIGNMENT
    2461              :                                 | SANITIZE_NONNULL_ATTRIBUTE
    2462              :                                 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
    2463              :                                 | SANITIZE_OBJECT_SIZE
    2464              :                                 | SANITIZE_POINTER_OVERFLOW
    2465      2848664 :                                 | SANITIZE_BUILTIN));
    2466              :     }
    2467              : 
    2468              :   unsigned int execute (function *) final override;
    2469              : 
    2470              : }; // class pass_ubsan
    2471              : 
    2472              : unsigned int
    2473         4703 : pass_ubsan::execute (function *fun)
    2474              : {
    2475         4703 :   basic_block bb;
    2476         4703 :   gimple_stmt_iterator gsi;
    2477         4703 :   unsigned int ret = 0;
    2478              : 
    2479         4703 :   initialize_sanitizer_builtins ();
    2480              : 
    2481        27423 :   FOR_EACH_BB_FN (bb, fun)
    2482              :     {
    2483       143139 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
    2484              :         {
    2485        97699 :           gimple *stmt = gsi_stmt (gsi);
    2486        97699 :           if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
    2487              :             {
    2488         7407 :               gsi_next (&gsi);
    2489         7407 :               continue;
    2490              :             }
    2491              : 
    2492        90292 :           if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
    2493        90292 :               && is_gimple_assign (stmt))
    2494        53535 :             instrument_si_overflow (gsi);
    2495              : 
    2496        90292 :           if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
    2497              :             {
    2498        40047 :               if (gimple_store_p (stmt))
    2499         4669 :                 instrument_null (gsi, gimple_get_lhs (stmt), true);
    2500        40047 :               if (gimple_assign_single_p (stmt))
    2501        14973 :                 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
    2502        40047 :               if (is_gimple_call (stmt))
    2503              :                 {
    2504         6238 :                   unsigned args_num = gimple_call_num_args (stmt);
    2505        18571 :                   for (unsigned i = 0; i < args_num; ++i)
    2506              :                     {
    2507        12333 :                       tree arg = gimple_call_arg (stmt, i);
    2508        12333 :                       if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
    2509        11935 :                         continue;
    2510          398 :                       instrument_null (gsi, arg, false);
    2511              :                     }
    2512              :                 }
    2513              :             }
    2514              : 
    2515        90292 :           if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
    2516        90292 :               && gimple_assign_load_p (stmt))
    2517              :             {
    2518         4605 :               instrument_bool_enum_load (&gsi);
    2519         4605 :               bb = gimple_bb (stmt);
    2520              :             }
    2521              : 
    2522        90292 :           if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
    2523        35709 :               && is_gimple_call (stmt)
    2524        95782 :               && !gimple_call_internal_p (stmt))
    2525              :             {
    2526         4670 :               instrument_nonnull_arg (&gsi);
    2527         4670 :               bb = gimple_bb (stmt);
    2528              :             }
    2529              : 
    2530        90292 :           if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
    2531        90292 :               && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    2532              :             {
    2533         1342 :               instrument_builtin (&gsi);
    2534         1342 :               bb = gimple_bb (stmt);
    2535              :             }
    2536              : 
    2537        90292 :           if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
    2538        90292 :               && gimple_code (stmt) == GIMPLE_RETURN)
    2539              :             {
    2540         2671 :               instrument_nonnull_return (&gsi);
    2541         2671 :               bb = gimple_bb (stmt);
    2542              :             }
    2543              : 
    2544        90292 :           if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
    2545              :             {
    2546        35843 :               if (gimple_store_p (stmt))
    2547         4436 :                 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
    2548        35843 :               if (gimple_assign_load_p (stmt))
    2549         4596 :                 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
    2550              :                                         false);
    2551        35843 :               if (is_gimple_call (stmt))
    2552              :                 {
    2553         5430 :                   unsigned args_num = gimple_call_num_args (stmt);
    2554        16308 :                   for (unsigned i = 0; i < args_num; ++i)
    2555              :                     {
    2556        10878 :                       tree arg = gimple_call_arg (stmt, i);
    2557        10878 :                       if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
    2558        10808 :                         continue;
    2559           70 :                       instrument_object_size (&gsi, arg, false);
    2560              :                     }
    2561              :                 }
    2562              :             }
    2563              : 
    2564        90292 :           if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
    2565              :             {
    2566        38750 :               if (is_gimple_assign (stmt)
    2567        38750 :                   && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
    2568          798 :                 instrument_pointer_overflow (&gsi,
    2569              :                                              gimple_assign_rhs1 (stmt),
    2570              :                                              gimple_assign_rhs2 (stmt));
    2571        38750 :               if (gimple_store_p (stmt))
    2572         5230 :                 maybe_instrument_pointer_overflow (&gsi,
    2573              :                                                    gimple_get_lhs (stmt));
    2574        38750 :               if (gimple_assign_single_p (stmt))
    2575        15051 :                 maybe_instrument_pointer_overflow (&gsi,
    2576              :                                                    gimple_assign_rhs1 (stmt));
    2577        38750 :               if (is_gimple_call (stmt))
    2578              :                 {
    2579         5873 :                   unsigned args_num = gimple_call_num_args (stmt);
    2580        17508 :                   for (unsigned i = 0; i < args_num; ++i)
    2581              :                     {
    2582        11635 :                       tree arg = gimple_call_arg (stmt, i);
    2583        11635 :                       if (is_gimple_reg (arg))
    2584         5161 :                         continue;
    2585         6474 :                       maybe_instrument_pointer_overflow (&gsi, arg);
    2586              :                     }
    2587              :                 }
    2588              :             }
    2589              : 
    2590        90292 :           gsi_next (&gsi);
    2591              :         }
    2592        22720 :       if (gimple_purge_dead_eh_edges (bb))
    2593           52 :         ret = TODO_cleanup_cfg;
    2594              :     }
    2595         4703 :   return ret;
    2596              : }
    2597              : 
    2598              : } // anon namespace
    2599              : 
    2600              : gimple_opt_pass *
    2601       285722 : make_pass_ubsan (gcc::context *ctxt)
    2602              : {
    2603       285722 :   return new pass_ubsan (ctxt);
    2604              : }
    2605              : 
    2606              : #include "gt-ubsan.h"
        

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.