1  /* Reduced from linux-5.10.162's drivers-base-bus.c  */
       2  /* { dg-additional-options "-fno-delete-null-pointer-checks -O2" } */
       3  
       4  #define NULL ((void*)0)
       5  
       6  typedef unsigned int __kernel_size_t;
       7  typedef int __kernel_ssize_t;
       8  typedef __kernel_size_t size_t;
       9  typedef __kernel_ssize_t ssize_t;
      10  
      11  struct list_head
      12  {
      13    struct list_head *next, *prev;
      14  };
      15  
      16  struct kobject
      17  {
      18    /* [...snip...] */
      19  };
      20  
      21  struct attribute
      22  {
      23    /* [...snip...] */
      24  };
      25  
      26  static inline
      27  void
      28  sysfs_remove_file_ns(struct kobject* kobj,
      29                       const struct attribute* attr,
      30                       const void* ns)
      31  {
      32  }
      33  
      34  static inline
      35  void
      36  sysfs_remove_file(struct kobject* kobj, const struct attribute* attr)
      37  {
      38    sysfs_remove_file_ns(kobj, attr, NULL);
      39  }
      40  
      41  extern struct kobject*
      42  kobject_get(struct kobject* kobj);
      43  
      44  extern void
      45  kobject_put(struct kobject* kobj);
      46  
      47  struct kset
      48  {
      49    struct list_head list;
      50    /* [...snip...] */
      51    struct kobject kobj;
      52    /* [...snip...] */
      53  } __attribute__((__designated_init__));
      54  
      55  static inline
      56  struct kset*
      57  to_kset(struct kobject* kobj)
      58  {
      59    return kobj ? ({
      60      void* __mptr = (void*)(kobj);
      61      ((struct kset*)(__mptr - __builtin_offsetof(struct kset, kobj)));
      62    }) : NULL;
      63  }
      64  
      65  static inline
      66  struct kset*
      67  kset_get(struct kset* k)
      68  {
      69    return k ? to_kset(kobject_get(&k->kobj)) : NULL;
      70  }
      71  
      72  static inline
      73  void
      74  kset_put(struct kset* k)
      75  {
      76    kobject_put(&k->kobj);
      77  }
      78  
      79  struct bus_type
      80  {
      81    /* [...snip...] */
      82    struct device* dev_root;
      83    /* [...snip...] */
      84    struct subsys_private* p;
      85    /* [...snip...] */
      86  };
      87  
      88  struct bus_attribute
      89  {
      90    struct attribute attr;
      91    /* [...snip...] */
      92  };
      93  
      94  extern void
      95  device_unregister(struct device* dev);
      96  
      97  struct subsys_private
      98  {
      99    struct kset subsys;
     100    /* [...snip...] */
     101  };
     102  
     103  static struct bus_type*
     104  bus_get(struct bus_type* bus)
     105  {
     106    if (bus) { /* { dg-bogus "check of 'bus' for NULL after already dereferencing it" } */
     107      kset_get(&bus->p->subsys);
     108      return bus;
     109    }
     110    return NULL;
     111  }
     112  
     113  static void
     114  bus_put(struct bus_type* bus)
     115  {
     116    if (bus)
     117      kset_put(&bus->p->subsys);
     118  }
     119  
     120  void
     121  bus_remove_file(struct bus_type* bus, struct bus_attribute* attr)
     122  {
     123    if (bus_get(bus)) {
     124      sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);
     125      bus_put(bus);
     126    }
     127  }
     128  
     129  extern ssize_t
     130  drivers_autoprobe_show(struct bus_type* bus, char* buf);
     131  
     132  extern ssize_t
     133  drivers_autoprobe_store(struct bus_type* bus, const char* buf, size_t count);
     134  
     135  extern struct bus_attribute bus_attr_drivers_autoprobe;
     136  
     137  static void
     138  remove_probe_files(struct bus_type* bus)
     139  {
     140    bus_remove_file(bus, &bus_attr_drivers_autoprobe);
     141    /* [...snip...] */
     142  }
     143  
     144  void
     145  bus_unregister(struct bus_type* bus)
     146  {
     147    /* [...snip...] */
     148    if (bus->dev_root) /* { dg-bogus "pointer 'bus' is dereferenced here" } */
     149      device_unregister(bus->dev_root);
     150    /* [...snip...] */
     151    remove_probe_files(bus);
     152    /* [...snip...] */
     153  }