2018-07-05 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / go / gofrontend / go-diagnostics.cc
blob21e45b3af37e2360b1e4d29b40dd74a7c9cff687
1 // go-diagnostics.cc -- Go error/warning diagnostics utilities.
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.
7 #include "go-diagnostics.h"
9 static std::string
10 mformat_value()
12 return std::string(xstrerror(errno));
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.
19 static std::string
20 expand_format(const char* fmt)
22 std::stringstream ss;
23 for (const char* c = fmt; *c; ++c)
25 if (*c != '%')
27 ss << *c;
28 continue;
30 c++;
31 switch (*c)
33 case '\0':
35 // malformed format string
36 go_unreachable();
38 case '%':
40 ss << "%";
41 break;
43 case 'm':
45 ss << mformat_value();
46 break;
48 case '<':
50 ss << go_open_quote();
51 break;
53 case '>':
55 ss << go_close_quote();
56 break;
58 case 'q':
60 ss << go_open_quote();
61 c++;
62 if (*c == 'm')
64 ss << mformat_value();
66 else
68 ss << "%" << *c;
70 ss << go_close_quote();
71 break;
73 default:
75 ss << "%" << *c;
79 return ss.str();
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:
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]
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.
94 static std::string
95 expand_message(const char* fmt, va_list ap) GO_ATTRIBUTE_GCC_DIAG(1,0);
97 #pragma GCC diagnostic push
98 #pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
100 static std::string
101 expand_message(const char* fmt, va_list ap)
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)
108 // memory allocation failed
109 go_be_error_at(Linemap::unknown_location(),
110 "memory allocation failed in vasprintf");
111 go_assert(0);
113 std::string rval = std::string(mbuf);
114 free(mbuf);
115 return rval;
118 #pragma GCC diagnostic pop
120 static const char* cached_open_quote = NULL;
121 static const char* cached_close_quote = NULL;
123 const char*
124 go_open_quote()
126 if (cached_open_quote == NULL)
127 go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
128 return cached_open_quote;
131 const char*
132 go_close_quote()
134 if (cached_close_quote == NULL)
135 go_be_get_quotechars(&cached_open_quote, &cached_close_quote);
136 return cached_close_quote;
139 void
140 go_error_at(const Location location, const char* fmt, ...)
142 va_list ap;
144 va_start(ap, fmt);
145 go_be_error_at(location, expand_message(fmt, ap));
146 va_end(ap);
149 void
150 go_warning_at(const Location location, int opt, const char* fmt, ...)
152 va_list ap;
154 va_start(ap, fmt);
155 go_be_warning_at(location, opt, expand_message(fmt, ap));
156 va_end(ap);
159 void
160 go_fatal_error(const Location location, const char* fmt, ...)
162 va_list ap;
164 va_start(ap, fmt);
165 go_be_fatal_error(location, expand_message(fmt, ap));
166 va_end(ap);
169 void
170 go_inform(const Location location, const char* fmt, ...)
172 va_list ap;
174 va_start(ap, fmt);
175 go_be_inform(location, expand_message(fmt, ap));
176 va_end(ap);