Home | History | Annotate | Line # | Download | only in d
d-diagnostic.cc revision 1.1
      1  1.1  mrg /* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
      2  1.1  mrg    Copyright (C) 2017-2019 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg GCC is free software; you can redistribute it and/or modify
      5  1.1  mrg it under the terms of the GNU General Public License as published by
      6  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
      7  1.1  mrg any later version.
      8  1.1  mrg 
      9  1.1  mrg GCC is distributed in the hope that it will be useful,
     10  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  mrg GNU General Public License for more details.
     13  1.1  mrg 
     14  1.1  mrg You should have received a copy of the GNU General Public License
     15  1.1  mrg along with GCC; see the file COPYING3.  If not see
     16  1.1  mrg <http://www.gnu.org/licenses/>.  */
     17  1.1  mrg 
     18  1.1  mrg #include "config.h"
     19  1.1  mrg #include "system.h"
     20  1.1  mrg #include "coretypes.h"
     21  1.1  mrg 
     22  1.1  mrg #include "dmd/globals.h"
     23  1.1  mrg #include "dmd/errors.h"
     24  1.1  mrg 
     25  1.1  mrg #include "tree.h"
     26  1.1  mrg #include "options.h"
     27  1.1  mrg #include "diagnostic.h"
     28  1.1  mrg 
     29  1.1  mrg #include "d-tree.h"
     30  1.1  mrg 
     31  1.1  mrg 
     32  1.1  mrg /* Rewrite the format string FORMAT to deal with any format extensions not
     33  1.1  mrg    supported by pp_format().
     34  1.1  mrg 
     35  1.1  mrg    The following format specifiers are handled:
     36  1.1  mrg    `...`: text within backticks gets quoted as '%<...%>'.
     37  1.1  mrg    %-10s: left-justify format flag is removed leaving '%s' remaining.
     38  1.1  mrg    %02x: zero-padding format flag is removed leaving '%x' remaining.
     39  1.1  mrg    %X: uppercase unsigned hexadecimals are rewritten as '%x'.
     40  1.1  mrg 
     41  1.1  mrg    The result should be freed by the caller.  */
     42  1.1  mrg 
     43  1.1  mrg static char *
     44  1.1  mrg expand_d_format (const char *format)
     45  1.1  mrg {
     46  1.1  mrg   OutBuffer buf;
     47  1.1  mrg   bool inbacktick = false;
     48  1.1  mrg 
     49  1.1  mrg   for (const char *p = format; *p;)
     50  1.1  mrg     {
     51  1.1  mrg       while (*p != '\0' && *p != '%' && *p != '`')
     52  1.1  mrg 	{
     53  1.1  mrg 	  buf.writeByte (*p);
     54  1.1  mrg 	  p++;
     55  1.1  mrg 	}
     56  1.1  mrg 
     57  1.1  mrg       if (*p == '\0')
     58  1.1  mrg 	break;
     59  1.1  mrg 
     60  1.1  mrg       if (*p == '`')
     61  1.1  mrg 	{
     62  1.1  mrg 	  /* Text enclosed by `...` are translated as a quoted string.  */
     63  1.1  mrg 	  if (inbacktick)
     64  1.1  mrg 	    {
     65  1.1  mrg 	      buf.writestring ("%>");
     66  1.1  mrg 	      inbacktick = false;
     67  1.1  mrg 	    }
     68  1.1  mrg 	  else
     69  1.1  mrg 	    {
     70  1.1  mrg 	      buf.writestring ("%<");
     71  1.1  mrg 	      inbacktick = true;
     72  1.1  mrg 	    }
     73  1.1  mrg 	  p++;
     74  1.1  mrg 	  continue;
     75  1.1  mrg 	}
     76  1.1  mrg 
     77  1.1  mrg       /* Check the conversion specification for unhandled flags.  */
     78  1.1  mrg       buf.writeByte (*p);
     79  1.1  mrg       p++;
     80  1.1  mrg 
     81  1.1  mrg     Lagain:
     82  1.1  mrg       switch (*p)
     83  1.1  mrg 	{
     84  1.1  mrg 	case '\0':
     85  1.1  mrg 	  /* Malformed format string.  */
     86  1.1  mrg 	  gcc_unreachable ();
     87  1.1  mrg 
     88  1.1  mrg 	case '-':
     89  1.1  mrg 	  /* Remove whitespace formatting.  */
     90  1.1  mrg 	  p++;
     91  1.1  mrg 	  while (ISDIGIT (*p))
     92  1.1  mrg 	    p++;
     93  1.1  mrg 	  goto Lagain;
     94  1.1  mrg 
     95  1.1  mrg 	case '0':
     96  1.1  mrg 	  /* Remove zero padding from format string.  */
     97  1.1  mrg 	  while (ISDIGIT (*p))
     98  1.1  mrg 	    p++;
     99  1.1  mrg 	  goto Lagain;
    100  1.1  mrg 
    101  1.1  mrg 	case 'X':
    102  1.1  mrg 	  /* Hex format only supports lower-case.  */
    103  1.1  mrg 	  buf.writeByte ('x');
    104  1.1  mrg 	  p++;
    105  1.1  mrg 	  break;
    106  1.1  mrg 
    107  1.1  mrg 	default:
    108  1.1  mrg 	  break;
    109  1.1  mrg 	}
    110  1.1  mrg     }
    111  1.1  mrg 
    112  1.1  mrg   gcc_assert (!inbacktick);
    113  1.1  mrg   return buf.extractString ();
    114  1.1  mrg }
    115  1.1  mrg 
    116  1.1  mrg /* Helper routine for all error routines.  Reports a diagnostic specified by
    117  1.1  mrg    KIND at the explicit location LOC.  The message FORMAT comes from the dmd
    118  1.1  mrg    front-end, which does not get translated by the gcc diagnostic routines.  */
    119  1.1  mrg 
    120  1.1  mrg static void ATTRIBUTE_GCC_DIAG(3,0)
    121  1.1  mrg d_diagnostic_report_diagnostic (const Loc& loc, int opt, const char *format,
    122  1.1  mrg 				va_list ap, diagnostic_t kind, bool verbatim)
    123  1.1  mrg {
    124  1.1  mrg   va_list argp;
    125  1.1  mrg   va_copy (argp, ap);
    126  1.1  mrg 
    127  1.1  mrg   if (loc.filename || !verbatim)
    128  1.1  mrg     {
    129  1.1  mrg       rich_location rich_loc (line_table, make_location_t (loc));
    130  1.1  mrg       diagnostic_info diagnostic;
    131  1.1  mrg       char *xformat = expand_d_format (format);
    132  1.1  mrg 
    133  1.1  mrg       diagnostic_set_info_translated (&diagnostic, xformat, &argp,
    134  1.1  mrg 				      &rich_loc, kind);
    135  1.1  mrg       if (opt != 0)
    136  1.1  mrg 	diagnostic.option_index = opt;
    137  1.1  mrg 
    138  1.1  mrg       diagnostic_report_diagnostic (global_dc, &diagnostic);
    139  1.1  mrg       free (xformat);
    140  1.1  mrg     }
    141  1.1  mrg   else
    142  1.1  mrg     {
    143  1.1  mrg       /* Write verbatim messages with no location direct to stream.  */
    144  1.1  mrg       text_info text;
    145  1.1  mrg       text.err_no = errno;
    146  1.1  mrg       text.args_ptr = &argp;
    147  1.1  mrg       text.format_spec = expand_d_format (format);
    148  1.1  mrg       text.x_data = NULL;
    149  1.1  mrg 
    150  1.1  mrg       pp_format_verbatim (global_dc->printer, &text);
    151  1.1  mrg       pp_newline_and_flush (global_dc->printer);
    152  1.1  mrg     }
    153  1.1  mrg 
    154  1.1  mrg   va_end (argp);
    155  1.1  mrg }
    156  1.1  mrg 
    157  1.1  mrg /* Print a hard error message with explicit location LOC with an optional
    158  1.1  mrg    message prefix PREFIX1 and PREFIX2, increasing the global or gagged
    159  1.1  mrg    error count.  */
    160  1.1  mrg 
    161  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    162  1.1  mrg error (const Loc& loc, const char *format, ...)
    163  1.1  mrg {
    164  1.1  mrg   va_list ap;
    165  1.1  mrg   va_start (ap, format);
    166  1.1  mrg   verror (loc, format, ap);
    167  1.1  mrg   va_end (ap);
    168  1.1  mrg }
    169  1.1  mrg 
    170  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    171  1.1  mrg verror (const Loc& loc, const char *format, va_list ap,
    172  1.1  mrg 	const char *prefix1, const char *prefix2, const char *)
    173  1.1  mrg {
    174  1.1  mrg   if (!global.gag || global.params.showGaggedErrors)
    175  1.1  mrg     {
    176  1.1  mrg       char *xformat;
    177  1.1  mrg 
    178  1.1  mrg       /* Build string and emit.  */
    179  1.1  mrg       if (prefix2 != NULL)
    180  1.1  mrg 	xformat = xasprintf ("%s %s %s", prefix1, prefix2, format);
    181  1.1  mrg       else if (prefix1 != NULL)
    182  1.1  mrg 	xformat = xasprintf ("%s %s", prefix1, format);
    183  1.1  mrg       else
    184  1.1  mrg 	xformat = xasprintf ("%s", format);
    185  1.1  mrg 
    186  1.1  mrg       d_diagnostic_report_diagnostic (loc, 0, xformat, ap,
    187  1.1  mrg 				      global.gag ? DK_ANACHRONISM : DK_ERROR,
    188  1.1  mrg 				      false);
    189  1.1  mrg       free (xformat);
    190  1.1  mrg     }
    191  1.1  mrg 
    192  1.1  mrg   if (global.gag)
    193  1.1  mrg     global.gaggedErrors++;
    194  1.1  mrg 
    195  1.1  mrg   global.errors++;
    196  1.1  mrg }
    197  1.1  mrg 
    198  1.1  mrg /* Print supplementary message about the last error with explicit location LOC.
    199  1.1  mrg    This doesn't increase the global error count.  */
    200  1.1  mrg 
    201  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    202  1.1  mrg errorSupplemental (const Loc& loc, const char *format, ...)
    203  1.1  mrg {
    204  1.1  mrg   va_list ap;
    205  1.1  mrg   va_start (ap, format);
    206  1.1  mrg   verrorSupplemental (loc, format, ap);
    207  1.1  mrg   va_end (ap);
    208  1.1  mrg }
    209  1.1  mrg 
    210  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    211  1.1  mrg verrorSupplemental (const Loc& loc, const char *format, va_list ap)
    212  1.1  mrg {
    213  1.1  mrg   if (global.gag && !global.params.showGaggedErrors)
    214  1.1  mrg     return;
    215  1.1  mrg 
    216  1.1  mrg   d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
    217  1.1  mrg }
    218  1.1  mrg 
    219  1.1  mrg /* Print a warning message with explicit location LOC, increasing the
    220  1.1  mrg    global warning count.  */
    221  1.1  mrg 
    222  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    223  1.1  mrg warning (const Loc& loc, const char *format, ...)
    224  1.1  mrg {
    225  1.1  mrg   va_list ap;
    226  1.1  mrg   va_start (ap, format);
    227  1.1  mrg   vwarning (loc, format, ap);
    228  1.1  mrg   va_end (ap);
    229  1.1  mrg }
    230  1.1  mrg 
    231  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    232  1.1  mrg vwarning (const Loc& loc, const char *format, va_list ap)
    233  1.1  mrg {
    234  1.1  mrg   if (!global.gag && global.params.warnings != DIAGNOSTICoff)
    235  1.1  mrg     {
    236  1.1  mrg       /* Warnings don't count if not treated as errors.  */
    237  1.1  mrg       if (global.params.warnings == DIAGNOSTICerror)
    238  1.1  mrg 	global.warnings++;
    239  1.1  mrg 
    240  1.1  mrg       d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_WARNING, false);
    241  1.1  mrg     }
    242  1.1  mrg }
    243  1.1  mrg 
    244  1.1  mrg /* Print supplementary message about the last warning with explicit location
    245  1.1  mrg    LOC.  This doesn't increase the global warning count.  */
    246  1.1  mrg 
    247  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    248  1.1  mrg warningSupplemental (const Loc& loc, const char *format, ...)
    249  1.1  mrg {
    250  1.1  mrg   va_list ap;
    251  1.1  mrg   va_start (ap, format);
    252  1.1  mrg   vwarningSupplemental (loc, format, ap);
    253  1.1  mrg   va_end (ap);
    254  1.1  mrg }
    255  1.1  mrg 
    256  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    257  1.1  mrg vwarningSupplemental (const Loc& loc, const char *format, va_list ap)
    258  1.1  mrg {
    259  1.1  mrg   if (global.params.warnings == DIAGNOSTICoff || global.gag)
    260  1.1  mrg     return;
    261  1.1  mrg 
    262  1.1  mrg   d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
    263  1.1  mrg }
    264  1.1  mrg 
    265  1.1  mrg /* Print a deprecation message with explicit location LOC with an optional
    266  1.1  mrg    message prefix PREFIX1 and PREFIX2, increasing the global warning or
    267  1.1  mrg    error count depending on how deprecations are treated.  */
    268  1.1  mrg 
    269  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    270  1.1  mrg deprecation (const Loc& loc, const char *format, ...)
    271  1.1  mrg {
    272  1.1  mrg   va_list ap;
    273  1.1  mrg   va_start (ap, format);
    274  1.1  mrg   vdeprecation (loc, format, ap);
    275  1.1  mrg   va_end (ap);
    276  1.1  mrg }
    277  1.1  mrg 
    278  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    279  1.1  mrg vdeprecation (const Loc& loc, const char *format, va_list ap,
    280  1.1  mrg 	      const char *prefix1, const char *prefix2)
    281  1.1  mrg {
    282  1.1  mrg   if (global.params.useDeprecated == DIAGNOSTICerror)
    283  1.1  mrg     verror (loc, format, ap, prefix1, prefix2);
    284  1.1  mrg   else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
    285  1.1  mrg     {
    286  1.1  mrg       char *xformat;
    287  1.1  mrg 
    288  1.1  mrg       /* Build string and emit.  */
    289  1.1  mrg       if (prefix2 != NULL)
    290  1.1  mrg 	xformat = xasprintf ("%s %s %s", prefix1, prefix2, format);
    291  1.1  mrg       else if (prefix1 != NULL)
    292  1.1  mrg 	xformat = xasprintf ("%s %s", prefix1, format);
    293  1.1  mrg       else
    294  1.1  mrg 	xformat = xasprintf ("%s", format);
    295  1.1  mrg 
    296  1.1  mrg       d_diagnostic_report_diagnostic (loc, OPT_Wdeprecated, xformat, ap,
    297  1.1  mrg 				      DK_WARNING, false);
    298  1.1  mrg       free (xformat);
    299  1.1  mrg     }
    300  1.1  mrg }
    301  1.1  mrg 
    302  1.1  mrg /* Print supplementary message about the last deprecation with explicit
    303  1.1  mrg    location LOC.  This does not increase the global error count.  */
    304  1.1  mrg 
    305  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,3)
    306  1.1  mrg deprecationSupplemental (const Loc& loc, const char *format, ...)
    307  1.1  mrg {
    308  1.1  mrg   va_list ap;
    309  1.1  mrg   va_start (ap, format);
    310  1.1  mrg   vdeprecationSupplemental (loc, format, ap);
    311  1.1  mrg   va_end (ap);
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    315  1.1  mrg vdeprecationSupplemental (const Loc& loc, const char *format, va_list ap)
    316  1.1  mrg {
    317  1.1  mrg   if (global.params.useDeprecated == DIAGNOSTICerror)
    318  1.1  mrg     verrorSupplemental (loc, format, ap);
    319  1.1  mrg   else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
    320  1.1  mrg     d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
    321  1.1  mrg }
    322  1.1  mrg 
    323  1.1  mrg /* Print a verbose message with explicit location LOC.  */
    324  1.1  mrg 
    325  1.1  mrg void ATTRIBUTE_GCC_DIAG(2, 3)
    326  1.1  mrg message (const Loc& loc, const char *format, ...)
    327  1.1  mrg {
    328  1.1  mrg   va_list ap;
    329  1.1  mrg   va_start (ap, format);
    330  1.1  mrg   vmessage (loc, format, ap);
    331  1.1  mrg   va_end (ap);
    332  1.1  mrg }
    333  1.1  mrg 
    334  1.1  mrg void ATTRIBUTE_GCC_DIAG(2,0)
    335  1.1  mrg vmessage (const Loc& loc, const char *format, va_list ap)
    336  1.1  mrg {
    337  1.1  mrg   d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
    338  1.1  mrg }
    339  1.1  mrg 
    340  1.1  mrg /* Same as above, but doesn't take a location argument.  */
    341  1.1  mrg 
    342  1.1  mrg void ATTRIBUTE_GCC_DIAG(1, 2)
    343  1.1  mrg message (const char *format, ...)
    344  1.1  mrg {
    345  1.1  mrg   va_list ap;
    346  1.1  mrg   va_start (ap, format);
    347  1.1  mrg   vmessage (Loc (), format, ap);
    348  1.1  mrg   va_end (ap);
    349  1.1  mrg }
    350  1.1  mrg 
    351  1.1  mrg /* Call this after printing out fatal error messages to clean up and
    352  1.1  mrg    exit the compiler.  */
    353  1.1  mrg 
    354  1.1  mrg void
    355  1.1  mrg fatal (void)
    356  1.1  mrg {
    357  1.1  mrg   exit (FATAL_EXIT_CODE);
    358  1.1  mrg }
    359