(root)/
gcc-13.2.0/
libiberty/
testsuite/
test-demangle.c
       1  /* Demangler test program,
       2     Copyright (C) 2002-2023 Free Software Foundation, Inc.
       3     Written by Zack Weinberg <zack@codesourcery.com
       4  
       5     This file is part of GNU libiberty.
       6  
       7     This program is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 2 of the License, or
      10     (at your option) any later version.
      11  
      12     This program is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this program; if not, write to the Free Software
      19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
      20  */
      21  
      22  #ifdef HAVE_CONFIG_H
      23  #include "config.h"
      24  #endif
      25  #include "ansidecl.h"
      26  #include <stdio.h>
      27  #include "libiberty.h"
      28  #include "demangle.h"
      29  #ifdef HAVE_STRING_H
      30  #include <string.h>
      31  #endif
      32  #if HAVE_STDLIB_H
      33  # include <stdlib.h>
      34  #endif
      35  #ifdef HAVE_UNISTD_H
      36  #include <unistd.h>
      37  #endif
      38  
      39  struct line
      40  {
      41    size_t alloced;
      42    char *data;
      43  };
      44  
      45  static unsigned int lineno;
      46  
      47  /* Safely read a single line of arbitrary length from standard input.  */
      48  
      49  #define LINELEN 80
      50  
      51  static void
      52  get_line(buf)
      53       struct line *buf;
      54  {
      55    char *data = buf->data;
      56    size_t alloc = buf->alloced;
      57    size_t count = 0;
      58    int c;
      59  
      60    if (data == 0)
      61      {
      62        data = xmalloc (LINELEN);
      63        alloc = LINELEN;
      64      }
      65  
      66    /* Skip comment lines.  */
      67    while ((c = getchar()) == '#')
      68      {
      69        while ((c = getchar()) != EOF && c != '\n');
      70        lineno++;
      71      }
      72  
      73    /* c is the first character on the line, and it's not a comment
      74       line: copy this line into the buffer and return.  */
      75    while (c != EOF && c != '\n')
      76      {
      77        if (count + 1 >= alloc)
      78  	{
      79  	  alloc *= 2;
      80  	  data = xrealloc (data, alloc);
      81  	}
      82        data[count++] = c;
      83        c = getchar();
      84      }
      85    lineno++;
      86    data[count] = '\0';
      87  
      88    buf->data = data;
      89    buf->alloced = alloc;
      90  }
      91  
      92  /* If we have mmap() and mprotect(), copy the string S just before a
      93     protected page, so that if the demangler runs over the end of the
      94     string we'll get a fault, and return the address of the new string.
      95     If no mmap, or it fails, or it looks too hard, just return S.  */
      96  
      97  #ifdef HAVE_SYS_MMAN_H
      98  #include <sys/mman.h>
      99  #endif
     100  #if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
     101  #define MAP_ANONYMOUS MAP_ANON
     102  #endif
     103  
     104  static const char *
     105  protect_end (const char * s)
     106  {
     107  #if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
     108    size_t pagesize = getpagesize();
     109    static char * buf;
     110    size_t s_len = strlen (s);
     111    char * result;
     112    
     113    /* Don't try if S is too long.  */
     114    if (s_len >= pagesize)
     115      return s;
     116  
     117    /* Allocate one page of allocated space followed by an unmapped
     118       page.  */
     119    if (buf == NULL)
     120      {
     121        buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
     122  		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     123        if (! buf)
     124  	return s;
     125        munmap (buf + pagesize, pagesize);
     126      }
     127    
     128    result = buf + (pagesize - s_len - 1);
     129    memcpy (result, s, s_len + 1);
     130    return result;
     131  #else
     132    return s;
     133  #endif
     134  }
     135  
     136  static void
     137  fail (lineno, opts, in, out, exp)
     138       int lineno;
     139       const char *opts;
     140       const char *in;
     141       const char *out;
     142       const char *exp;
     143  {
     144    printf ("\
     145  FAIL at line %d, options %s:\n\
     146  in:  %s\n\
     147  out: %s\n\
     148  exp: %s\n",
     149  	  lineno, opts, in, out != NULL ? out : "(null)", exp);
     150  }
     151  
     152  /* The tester operates on a data file consisting of groups of lines:
     153     options
     154     input to be demangled
     155     expected output
     156  
     157     Supported options:
     158       --format=<name>     Sets the demangling style.
     159       --no-params         There are two lines of expected output; the first
     160                           is with DMGL_PARAMS, the second is without it.
     161       --is-v3-ctor        Calls is_gnu_v3_mangled_ctor on input; expected
     162                           output is an integer representing ctor_kind.
     163       --is-v3-dtor        Likewise, but for dtors.
     164       --ret-postfix       Passes the DMGL_RET_POSTFIX option
     165       --ret-drop          Passes the DMGL_RET_DROP option
     166  
     167     For compatibility, just in case it matters, the options line may be
     168     empty, to mean --format=auto.  If it doesn't start with --, then it
     169     may contain only a format name.
     170  */
     171  
     172  int
     173  main(argc, argv)
     174       int argc;
     175       char **argv;
     176  {
     177    enum demangling_styles style = auto_demangling;
     178    int no_params;
     179    int is_v3_ctor;
     180    int is_v3_dtor;
     181    int ret_postfix, ret_drop;
     182    struct line format;
     183    struct line input;
     184    struct line expect;
     185    char *result;
     186    int failures = 0;
     187    int tests = 0;
     188  
     189    if (argc > 1)
     190      {
     191        fprintf (stderr, "usage: %s < test-set\n", argv[0]);
     192        return 2;
     193      }
     194  
     195    format.data = 0;
     196    input.data = 0;
     197    expect.data = 0;
     198  
     199    for (;;)
     200      {
     201        const char *inp;
     202        
     203        get_line (&format);
     204        if (feof (stdin))
     205  	break;
     206  
     207        get_line (&input);
     208        get_line (&expect);
     209  
     210        inp = protect_end (input.data);
     211  
     212        tests++;
     213  
     214        no_params = 0;
     215        ret_postfix = 0;
     216        ret_drop = 0;
     217        is_v3_ctor = 0;
     218        is_v3_dtor = 0;
     219        if (format.data[0] == '\0')
     220  	style = auto_demangling;
     221        else if (format.data[0] != '-')
     222  	{
     223  	  style = cplus_demangle_name_to_style (format.data);
     224  	  if (style == unknown_demangling)
     225  	    {
     226  	      printf ("FAIL at line %d: unknown demangling style %s\n",
     227  		      lineno, format.data);
     228  	      failures++;
     229  	      continue;
     230  	    }
     231  	}
     232        else
     233  	{
     234  	  char *p;
     235  	  char *opt;
     236  
     237  	  p = format.data;
     238  	  while (*p != '\0')
     239  	    {
     240  	      char c;
     241  
     242  	      opt = p;
     243  	      p += strcspn (p, " \t=");
     244  	      c = *p;
     245  	      *p = '\0';
     246  	      if (strcmp (opt, "--format") == 0 && c == '=')
     247  		{
     248  		  char *fstyle;
     249  
     250  		  *p = c;
     251  		  ++p;
     252  		  fstyle = p;
     253  		  p += strcspn (p, " \t");
     254  		  c = *p;
     255  		  *p = '\0';
     256  		  style = cplus_demangle_name_to_style (fstyle);
     257  		  if (style == unknown_demangling)
     258  		    {
     259  		      printf ("FAIL at line %d: unknown demangling style %s\n",
     260  			      lineno, fstyle);
     261  		      failures++;
     262  		      continue;
     263  		    }
     264  		}
     265  	      else if (strcmp (opt, "--no-params") == 0)
     266  		no_params = 1;
     267  	      else if (strcmp (opt, "--is-v3-ctor") == 0)
     268  		is_v3_ctor = 1;
     269  	      else if (strcmp (opt, "--is-v3-dtor") == 0)
     270  		is_v3_dtor = 1;
     271  	      else if (strcmp (opt, "--ret-postfix") == 0)
     272  		ret_postfix = 1;
     273  	      else if (strcmp (opt, "--ret-drop") == 0)
     274  		ret_drop = 1;
     275  	      else
     276  		{
     277  		  printf ("FAIL at line %d: unrecognized option %s\n",
     278  			  lineno, opt);
     279  		  failures++;
     280  		  continue;
     281  		}
     282  	      *p = c;
     283  	      p += strspn (p, " \t");
     284  	    }
     285  	}
     286  
     287        if (is_v3_ctor || is_v3_dtor)
     288  	{
     289  	  char buf[20];
     290  
     291  	  if (is_v3_ctor)
     292  	    {
     293  	      enum gnu_v3_ctor_kinds kc;
     294  
     295  	      kc = is_gnu_v3_mangled_ctor (inp);
     296  	      sprintf (buf, "%d", (int) kc);
     297  	    }
     298  	  else
     299  	    {
     300  	      enum gnu_v3_dtor_kinds kd;
     301  
     302  	      kd = is_gnu_v3_mangled_dtor (inp);
     303  	      sprintf (buf, "%d", (int) kd);
     304  	    }
     305  
     306  	  if (strcmp (buf, expect.data) != 0)
     307  	    {
     308  	      fail (lineno, format.data, input.data, buf, expect.data);
     309  	      failures++;
     310  	    }
     311  
     312  	  continue;
     313  	}
     314  
     315        cplus_demangle_set_style (style);
     316  
     317        result = cplus_demangle (inp, (DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES
     318  				     | (ret_postfix ? DMGL_RET_POSTFIX : 0)
     319  				     | (ret_drop ? DMGL_RET_DROP : 0)));
     320  
     321        if (result
     322  	  ? strcmp (result, expect.data)
     323  	  : strcmp (input.data, expect.data))
     324  	{
     325  	  fail (lineno, format.data, input.data, result, expect.data);
     326  	  failures++;
     327  	}
     328        free (result);
     329  
     330        if (no_params)
     331  	{
     332  	  get_line (&expect);
     333  	  result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
     334  
     335  	  if (result
     336  	      ? strcmp (result, expect.data)
     337  	      : strcmp (input.data, expect.data))
     338  	    {
     339  	      fail (lineno, format.data, input.data, result, expect.data);
     340  	      failures++;
     341  	    }
     342  	  free (result);
     343  	}
     344      }
     345  
     346    free (format.data);
     347    free (input.data);
     348    free (expect.data);
     349  
     350    printf ("%s: %d tests, %d failures\n", argv[0], tests, failures);
     351    return failures ? 1 : 0;
     352  }