LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - go-diagnostics.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 74.3 % 101 75
Test Date: 2026-02-28 14:20:25 Functions: 80.0 % 10 8
Legend: Lines:     hit not hit

            Line data    Source code
       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            0 : mformat_value()
      11              : {
      12            0 :   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         6896 : expand_format(const char* fmt)
      21              : {
      22         6896 :   std::stringstream ss;
      23       164275 :   for (const char* c = fmt; *c; ++c)
      24              :     {
      25       157379 :       if (*c != '%')
      26              :         {
      27       154936 :           ss << *c;
      28       154936 :           continue;
      29              :         }
      30         2443 :       c++;
      31         2443 :       switch (*c)
      32              :         {
      33            0 :           case '\0':
      34            0 :             {
      35              :               // malformed format string
      36            0 :               go_unreachable();
      37              :             }
      38            0 :           case '%':
      39            0 :             {
      40            0 :               ss << "%";
      41            0 :               break;
      42              :             }
      43            0 :           case 'm':
      44            0 :             {
      45            0 :               ss << mformat_value();
      46            0 :               break;
      47              :             }
      48          121 :           case '<':
      49          121 :             {
      50          121 :               ss << go_open_quote();
      51          121 :               break;
      52              :             }
      53          121 :           case '>':
      54          121 :             {
      55          121 :               ss << go_close_quote();
      56          121 :               break;
      57              :             }
      58          386 :           case 'q':
      59          386 :             {
      60          386 :               ss << go_open_quote();
      61          386 :               c++;
      62          386 :               if (*c == 'm')
      63              :                 {
      64            0 :                   ss << mformat_value();
      65              :                 }
      66              :               else
      67              :                 {
      68          386 :                   ss << "%" << *c;
      69              :                 }
      70          386 :               ss << go_close_quote();
      71          386 :               break;
      72              :             }
      73         1815 :           default:
      74         1815 :             {
      75         1815 :               ss << "%" << *c;
      76              :             }
      77              :         }
      78              :     }
      79         6896 :   return ss.str();
      80         6896 : }
      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         6896 : expand_message(const char* fmt, va_list ap)
     102              : {
     103         6896 :   char* mbuf = 0;
     104         6896 :   std::string expanded_fmt = expand_format(fmt);
     105         6896 :   int nwr = vasprintf(&mbuf, expanded_fmt.c_str(), ap);
     106         6896 :   if (nwr == -1)
     107              :     {
     108              :       // memory allocation failed
     109            0 :       go_be_error_at(Linemap::unknown_location(),
     110            0 :                      "memory allocation failed in vasprintf");
     111            0 :       go_assert(0);
     112              :     }
     113         6896 :   std::string rval = std::string(mbuf);
     114         6896 :   free(mbuf);
     115         6896 :   return rval;
     116         6896 : }
     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          525 : go_open_quote()
     125              : {
     126          525 :   if (cached_open_quote == NULL)
     127          187 :     go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
     128          525 :   return cached_open_quote;
     129              : }
     130              : 
     131              : const char*
     132          525 : go_close_quote()
     133              : {
     134          525 :   if (cached_close_quote == NULL)
     135            4 :     go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
     136          525 :   return cached_close_quote;
     137              : }
     138              : 
     139              : void
     140         6789 : go_error_at(const Location location, const char* fmt, ...)
     141              : {
     142         6789 :   va_list ap;
     143              : 
     144         6789 :   va_start(ap, fmt);
     145         6789 :   go_be_error_at(location, expand_message(fmt, ap));
     146         6789 :   va_end(ap);
     147         6789 : }
     148              : 
     149              : void
     150           17 : go_warning_at(const Location location, int opt, const char* fmt, ...)
     151              : {
     152           17 :   va_list ap;
     153              : 
     154           17 :   va_start(ap, fmt);
     155           17 :   go_be_warning_at(location, opt, expand_message(fmt, ap));
     156           17 :   va_end(ap);
     157           17 : }
     158              : 
     159              : void
     160            0 : go_fatal_error(const Location location, const char* fmt, ...)
     161              : {
     162            0 :   va_list ap;
     163              : 
     164            0 :   va_start(ap, fmt);
     165            0 :   go_be_fatal_error(location, expand_message(fmt, ap));
     166            0 :   va_end(ap);
     167            0 : }
     168              : 
     169              : void
     170           90 : go_inform(const Location location, const char* fmt, ...)
     171              : {
     172           90 :   va_list ap;
     173              : 
     174           90 :   va_start(ap, fmt);
     175           90 :   go_be_inform(location, expand_message(fmt, ap));
     176           90 :   va_end(ap);
     177           90 : }
     178              : 
     179              : // go_debug uses normal printf formatting, not GCC diagnostic formatting.
     180              : 
     181              : void
     182            9 : go_debug(const Location location, const char* fmt, ...)
     183              : {
     184            9 :   va_list ap;
     185              : 
     186            9 :   va_start(ap, fmt);
     187            9 :   char* mbuf = NULL;
     188            9 :   int nwr = vasprintf(&mbuf, fmt, ap);
     189            9 :   va_end(ap);
     190            9 :   if (nwr == -1)
     191              :     {
     192            0 :       go_be_error_at(Linemap::unknown_location(),
     193            0 :                      "memory allocation failed in vasprintf");
     194            0 :       go_assert(0);
     195              :     }
     196            9 :   std::string rval = std::string(mbuf);
     197            9 :   free(mbuf);
     198            9 :   go_be_inform(location, rval);
     199            9 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.