github.com/kidsbmilk/gofronted_all@v0.0.0-20220701224323-6479d5976c5d/go/go-diagnostics.cc (about)

     1  // go-diagnostics.cc -- Go error/warning diagnostics utilities.
     2  
     3  // Copyright 2016 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  #include "go-diagnostics.h"
     8  
     9  static std::string
    10  mformat_value()
    11  {
    12    return std::string(xstrerror(errno));
    13  }
    14  
    15  // Rewrite a format string to expand any extensions not
    16  // supported by sprintf(). See comments in go-diagnostics.h
    17  // for list of supported format specifiers.
    18  
    19  static std::string
    20  expand_format(const char* fmt)
    21  {
    22    std::stringstream ss;
    23    for (const char* c = fmt; *c; ++c)
    24      {
    25        if (*c != '%')
    26          {
    27            ss << *c;
    28            continue;
    29          }
    30        c++;
    31        switch (*c)
    32          {
    33            case '\0':
    34              {
    35                // malformed format string
    36                go_unreachable();
    37              }
    38            case '%':
    39              {
    40                ss << "%";
    41                break;
    42              }
    43            case 'm':
    44              {
    45                ss << mformat_value();
    46                break;
    47              }
    48            case '<':
    49              {
    50                ss << go_open_quote();
    51                break;
    52              }
    53            case '>':
    54              {
    55                ss << go_close_quote();
    56                break;
    57              }
    58            case 'q':
    59              {
    60                ss << go_open_quote();
    61                c++;
    62                if (*c == 'm')
    63                  {
    64                    ss << mformat_value();
    65                  }
    66                else
    67                  {
    68                    ss << "%" << *c;
    69                  }
    70                ss << go_close_quote();
    71                break;
    72              }
    73            default:
    74              {
    75                ss << "%" << *c;
    76              }
    77          }
    78      }
    79    return ss.str();
    80  }
    81  
    82  // Expand message format specifiers, using a combination of
    83  // expand_format above to handle extensions (ex: %m, %q) and vasprintf()
    84  // to handle regular printf-style formatting. A pragma is being used here to
    85  // suppress this warning:
    86  //
    87  //   warning: function ‘std::__cxx11::string expand_message(const char*, __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute [-Wsuggest-attribute=format]
    88  //
    89  // What appears to be happening here is that the checker is deciding that
    90  // because of the call to vasprintf() (which has attribute gnu_printf), the
    91  // calling function must need to have attribute gnu_printf as well, even
    92  // though there is already an attribute declaration for it.
    93  
    94  static std::string
    95  expand_message(const char* fmt, va_list ap) GO_ATTRIBUTE_GCC_DIAG(1,0);
    96  
    97  #pragma GCC diagnostic push
    98  #pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
    99  
   100  static std::string
   101  expand_message(const char* fmt, va_list ap)
   102  {
   103    char* mbuf = 0;
   104    std::string expanded_fmt = expand_format(fmt);
   105    int nwr = vasprintf(&mbuf, expanded_fmt.c_str(), ap);
   106    if (nwr == -1)
   107      {
   108        // memory allocation failed
   109        go_be_error_at(Linemap::unknown_location(),
   110                       "memory allocation failed in vasprintf");
   111        go_assert(0);
   112      }
   113    std::string rval = std::string(mbuf);
   114    free(mbuf);
   115    return rval;
   116  }
   117  
   118  #pragma GCC diagnostic pop
   119  
   120  static const char* cached_open_quote = NULL;
   121  static const char* cached_close_quote = NULL;
   122  
   123  const char*
   124  go_open_quote()
   125  {
   126    if (cached_open_quote == NULL)
   127      go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
   128    return cached_open_quote;
   129  }
   130  
   131  const char*
   132  go_close_quote()
   133  {
   134    if (cached_close_quote == NULL)
   135      go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
   136    return cached_close_quote;
   137  }
   138  
   139  void
   140  go_error_at(const Location location, const char* fmt, ...)
   141  {
   142    va_list ap;
   143  
   144    va_start(ap, fmt);
   145    go_be_error_at(location, expand_message(fmt, ap));
   146    va_end(ap);
   147  }
   148  
   149  void
   150  go_warning_at(const Location location, int opt, const char* fmt, ...)
   151  {
   152    va_list ap;
   153  
   154    va_start(ap, fmt);
   155    go_be_warning_at(location, opt, expand_message(fmt, ap));
   156    va_end(ap);
   157  }
   158  
   159  void
   160  go_fatal_error(const Location location, const char* fmt, ...)
   161  {
   162    va_list ap;
   163  
   164    va_start(ap, fmt);
   165    go_be_fatal_error(location, expand_message(fmt, ap));
   166    va_end(ap);
   167  }
   168  
   169  void
   170  go_inform(const Location location, const char* fmt, ...)
   171  {
   172    va_list ap;
   173  
   174    va_start(ap, fmt);
   175    go_be_inform(location, expand_message(fmt, ap));
   176    va_end(ap);
   177  }
   178  
   179  // go_debug uses normal printf formatting, not GCC diagnostic formatting.
   180  
   181  void
   182  go_debug(const Location location, const char* fmt, ...)
   183  {
   184    va_list ap;
   185  
   186    va_start(ap, fmt);
   187    char* mbuf = NULL;
   188    int nwr = vasprintf(&mbuf, fmt, ap);
   189    va_end(ap);
   190    if (nwr == -1)
   191      {
   192        go_be_error_at(Linemap::unknown_location(),
   193  		     "memory allocation failed in vasprintf");
   194        go_assert(0);
   195      }
   196    std::string rval = std::string(mbuf);
   197    free(mbuf);
   198    go_be_inform(location, rval);
   199  }