Mercurial > hg > CbC > CbC_gcc
comparison gcc/go/gofrontend/go-diagnostics.cc @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
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 } |