1  /* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */
       2  
       3  /* There need to be at least two calls to a function for the
       4     call-summarization code to be used.
       5     TODO: add some kind of test that summarization *was* used.  */
       6  
       7  /* Reduced from an example in Emacs in which string_char_and_length
       8     was being incorrectly summarized, failing to see the write to *length.  */
       9  
      10  typedef long int ptrdiff_t;
      11  typedef struct Lisp_X *Lisp_Word;
      12  typedef Lisp_Word Lisp_Object;
      13  extern _Bool STRING_MULTIBYTE(Lisp_Object str);
      14  extern unsigned char *SDATA(Lisp_Object string);
      15  enum { MAX_2_BYTE_CHAR = 0x7FF };
      16  enum { MAX_3_BYTE_CHAR = 0xFFFF };
      17  enum { MAX_4_BYTE_CHAR = 0x1FFFFF };
      18  enum { MAX_5_BYTE_CHAR = 0x3FFF7F };
      19  extern int make_char_multibyte(int c);
      20  static inline int string_char_and_length(unsigned char const *p, int *length) {
      21    int c = p[0];
      22    if (!(c & 0x80)) {
      23      *length = 1;
      24      return c;
      25    }
      26    ((0xC0 <= c) ? (void)0 : __builtin_unreachable());
      27    int d = (c << 6) + p[1] - ((0xC0 << 6) + 0x80);
      28    if (!(c & 0x20)) {
      29      *length = 2;
      30      return d + (c < 0xC2 ? 0x3FFF80 : 0);
      31    }
      32    d = (d << 6) + p[2] - ((0x20 << 12) + 0x80);
      33    if (!(c & 0x10)) {
      34      *length = 3;
      35      ((MAX_2_BYTE_CHAR < d && d <= MAX_3_BYTE_CHAR)
      36       ? (void)0
      37       : __builtin_unreachable());
      38      return d;
      39    }
      40    d = (d << 6) + p[3] - ((0x10 << 18) + 0x80);
      41    if (!(c & 0x08)) {
      42      *length = 4;
      43      ((MAX_3_BYTE_CHAR < d && d <= MAX_4_BYTE_CHAR)
      44       ? (void)0
      45       : __builtin_unreachable());
      46      return d;
      47    }
      48    d = (d << 6) + p[4] - ((0x08 << 24) + 0x80);
      49    *length = 5;
      50    ((MAX_4_BYTE_CHAR < d && d <= MAX_5_BYTE_CHAR)
      51     ? (void)0
      52     : __builtin_unreachable());
      53    return d;
      54  }
      55  int fetch_string_char_advance(Lisp_Object string,
      56  			      ptrdiff_t *charidx,
      57  			      ptrdiff_t *byteidx) {
      58    int output;
      59    ptrdiff_t b = *byteidx;
      60    unsigned char *chp = SDATA(string) + b;
      61    if (STRING_MULTIBYTE(string)) {
      62      int chlen;
      63      output = string_char_and_length(chp, &chlen);
      64      b += chlen;
      65    } else {
      66      output = *chp;
      67      b++;
      68    }
      69    (*charidx)++;
      70    *byteidx = b;
      71    return output;
      72  }
      73  int fetch_string_char_as_multibyte_advance(Lisp_Object string,
      74  					   ptrdiff_t *charidx,
      75  					   ptrdiff_t *byteidx) {
      76    int output;
      77    ptrdiff_t b = *byteidx;
      78    unsigned char *chp = SDATA(string) + b;
      79    if (STRING_MULTIBYTE(string)) {
      80      int chlen;
      81      output = string_char_and_length(chp, &chlen);
      82      b += chlen;
      83    } else {
      84      output = make_char_multibyte(*chp);
      85      b++;
      86    }
      87    (*charidx)++;
      88    *byteidx = b;
      89    return output;
      90  }