/src/cppcheck/oss-fuzz/build/templatesimplifier.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "matchcompiler.h" |
2 | | #include <string> |
3 | | #include <cstring> |
4 | | #include "errorlogger.h" |
5 | | #include "token.h" |
6 | | // pattern: requires |
7 | 0 | static inline bool match1(const Token* tok) { |
8 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("requires"))) |
9 | 0 | return false; |
10 | 0 | return true; |
11 | 0 | } |
12 | | // pattern: %oror%|&&|requires %name%|( |
13 | 0 | static inline bool match2(const Token* tok) { |
14 | 0 | if (!tok || !((tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->str() == MatchCompiler::makeConstString("requires")))) |
15 | 0 | return false; |
16 | 0 | tok = tok->next(); |
17 | 0 | if (!tok || !(tok->isName() || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
18 | 0 | return false; |
19 | 0 | return true; |
20 | 0 | } |
21 | | // pattern: requires ( |
22 | 0 | static inline bool match3(const Token* tok) { |
23 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("requires"))) |
24 | 0 | return false; |
25 | 0 | tok = tok->next(); |
26 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
27 | 0 | return false; |
28 | 0 | return true; |
29 | 0 | } |
30 | | // pattern: ) { |
31 | 0 | static inline bool match4(const Token* tok) { |
32 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
33 | 0 | return false; |
34 | 0 | tok = tok->next(); |
35 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
36 | 0 | return false; |
37 | 0 | return true; |
38 | 0 | } |
39 | | // pattern: %name% :: %name% |
40 | 0 | static inline bool match5(const Token* tok) { |
41 | 0 | if (!tok || !tok->isName()) |
42 | 0 | return false; |
43 | 0 | tok = tok->next(); |
44 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
45 | 0 | return false; |
46 | 0 | tok = tok->next(); |
47 | 0 | if (!tok || !tok->isName()) |
48 | 0 | return false; |
49 | 0 | return true; |
50 | 0 | } |
51 | | // pattern: %name% < |
52 | 0 | static inline bool match6(const Token* tok) { |
53 | 0 | if (!tok || !tok->isName()) |
54 | 0 | return false; |
55 | 0 | tok = tok->next(); |
56 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
57 | 0 | return false; |
58 | 0 | return true; |
59 | 0 | } |
60 | | // pattern: template < > |
61 | 0 | static inline bool match7(const Token* tok) { |
62 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
63 | 0 | return false; |
64 | 0 | tok = tok->next(); |
65 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
66 | 0 | return false; |
67 | 0 | tok = tok->next(); |
68 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
69 | 0 | return false; |
70 | 0 | return true; |
71 | 0 | } |
72 | | // pattern: > template < |
73 | 0 | static inline bool match8(const Token* tok) { |
74 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
75 | 0 | return false; |
76 | 0 | tok = tok->next(); |
77 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
78 | 0 | return false; |
79 | 0 | tok = tok->next(); |
80 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
81 | 0 | return false; |
82 | 0 | return true; |
83 | 0 | } |
84 | | // pattern: >|%name% :: |
85 | 0 | static inline bool match9(const Token* tok) { |
86 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || tok->isName())) |
87 | 0 | return false; |
88 | 0 | tok = tok->next(); |
89 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
90 | 0 | return false; |
91 | 0 | return true; |
92 | 0 | } |
93 | | // pattern: class|struct|union %name% <|{|:|;|:: |
94 | 0 | static inline bool match10(const Token* tok) { |
95 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")))) |
96 | 0 | return false; |
97 | 0 | tok = tok->next(); |
98 | 0 | if (!tok || !tok->isName()) |
99 | 0 | return false; |
100 | 0 | tok = tok->next(); |
101 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
102 | 0 | return false; |
103 | 0 | return true; |
104 | 0 | } |
105 | | // pattern: %name% ... |
106 | 0 | template<class T> static inline T * findmatch11(T * start_tok, const Token * end) { |
107 | 0 | for (; start_tok && start_tok != end; start_tok = start_tok->next()) { |
108 | |
|
109 | 0 | T * tok = start_tok; |
110 | 0 | if (!tok || !tok->isName()) |
111 | 0 | continue; |
112 | 0 | tok = tok->next(); |
113 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
114 | 0 | continue; |
115 | 0 | return start_tok; |
116 | 0 | } |
117 | 0 | return nullptr; |
118 | 0 | } |
119 | | // pattern: =|; |
120 | 0 | static inline bool match12(const Token* tok) { |
121 | 0 | if (!tok || !(((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || (tok->str() == MatchCompiler::makeConstString(";")))) |
122 | 0 | return false; |
123 | 0 | return true; |
124 | 0 | } |
125 | | // pattern: ;|{ |
126 | 9.83k | static inline bool match13(const Token* tok) { |
127 | 9.83k | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
128 | 5.88k | return false; |
129 | 3.95k | return true; |
130 | 9.83k | } |
131 | | // pattern: (|[ |
132 | 727 | static inline bool match14(const Token* tok) { |
133 | 727 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))) |
134 | 701 | return false; |
135 | 26 | return true; |
136 | 727 | } |
137 | | // pattern: :: ~ |
138 | 0 | static inline bool match15(const Token* tok) { |
139 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
140 | 0 | return false; |
141 | 0 | tok = tok->next(); |
142 | 0 | if (!tok || !((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("~"))) |
143 | 0 | return false; |
144 | 0 | return true; |
145 | 0 | } |
146 | | // pattern: %name% :: |
147 | 1.04k | static inline bool match16(const Token* tok) { |
148 | 1.04k | if (!tok || !tok->isName()) |
149 | 567 | return false; |
150 | 473 | tok = tok->next(); |
151 | 473 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
152 | 473 | return false; |
153 | 0 | return true; |
154 | 473 | } |
155 | | // pattern: > :: |
156 | 0 | static inline bool match17(const Token* tok) { |
157 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
158 | 0 | return false; |
159 | 0 | tok = tok->next(); |
160 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
161 | 0 | return false; |
162 | 0 | return true; |
163 | 0 | } |
164 | | // pattern: [;{}] |
165 | 19.6k | static inline bool match18(const Token* tok) { |
166 | 19.6k | if (!tok || tok->str().size() != 1U || !strchr(";{}", tok->str()[0])) |
167 | 14.5k | return false; |
168 | 5.09k | return true; |
169 | 19.6k | } |
170 | | // pattern: ; |
171 | 0 | template<class T> static inline T * findmatch19(T * start_tok) { |
172 | 0 | for (; start_tok; start_tok = start_tok->next()) { |
173 | |
|
174 | 0 | T * tok = start_tok; |
175 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
176 | 0 | continue; |
177 | 0 | return start_tok; |
178 | 0 | } |
179 | 0 | return nullptr; |
180 | 0 | } Unexecuted instantiation: templatesimplifier.cpp:Token const* findmatch19<Token const>(Token const*) Unexecuted instantiation: templatesimplifier.cpp:Token* findmatch19<Token>(Token*) |
181 | | // pattern: ( { |
182 | 20.3k | static inline bool match20(const Token* tok) { |
183 | 20.3k | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
184 | 19.2k | return false; |
185 | 1.14k | tok = tok->next(); |
186 | 1.14k | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
187 | 1.14k | return false; |
188 | 0 | return true; |
189 | 1.14k | } |
190 | | // pattern: try { |
191 | 19.2k | static inline bool match21(const Token* tok) { |
192 | 19.2k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("try"))) |
193 | 19.2k | return false; |
194 | 0 | tok = tok->next(); |
195 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
196 | 0 | return false; |
197 | 0 | return true; |
198 | 0 | } |
199 | | // pattern: } catch ( |
200 | 0 | static inline bool match22(const Token* tok) { |
201 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))) |
202 | 0 | return false; |
203 | 0 | tok = tok->next(); |
204 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("catch"))) |
205 | 0 | return false; |
206 | 0 | tok = tok->next(); |
207 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
208 | 0 | return false; |
209 | 0 | return true; |
210 | 0 | } |
211 | | // pattern: typedef|typename |
212 | 5.88k | static inline bool match23(const Token* tok) { |
213 | 5.88k | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("typedef")) || (tok->str() == MatchCompiler::makeConstString("typename")))) |
214 | 5.88k | return false; |
215 | 0 | return true; |
216 | 5.88k | } |
217 | | // pattern: %type% :: |
218 | 5.88k | static inline bool match24(const Token* tok) { |
219 | 5.88k | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
220 | 1.14k | return false; |
221 | 4.74k | tok = tok->next(); |
222 | 4.74k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
223 | 4.74k | return false; |
224 | 0 | return true; |
225 | 4.74k | } |
226 | | // pattern: %type% < |
227 | 5.88k | static inline bool match25(const Token* tok) { |
228 | 5.88k | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
229 | 1.14k | return false; |
230 | 4.74k | tok = tok->next(); |
231 | 4.74k | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
232 | 4.74k | return false; |
233 | 0 | return true; |
234 | 4.74k | } |
235 | | // pattern: template |
236 | 0 | static inline bool match26(const Token* tok) { |
237 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
238 | 0 | return false; |
239 | 0 | return true; |
240 | 0 | } |
241 | | // pattern: ; |
242 | 0 | static inline bool match27(const Token* tok) { |
243 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
244 | 0 | return false; |
245 | 0 | return true; |
246 | 0 | } |
247 | | // pattern: { |
248 | 0 | static inline bool match28(const Token* tok) { |
249 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
250 | 0 | return false; |
251 | 0 | return true; |
252 | 0 | } |
253 | | // pattern: >|%type% |
254 | 0 | static inline bool match29(const Token* tok) { |
255 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || (tok->isName() && tok->varId() == 0U))) |
256 | 0 | return false; |
257 | 0 | return true; |
258 | 0 | } |
259 | | // pattern: } ; |
260 | 0 | static inline bool match30(const Token* tok) { |
261 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))) |
262 | 0 | return false; |
263 | 0 | tok = tok->next(); |
264 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
265 | 0 | return false; |
266 | 0 | return true; |
267 | 0 | } |
268 | | // pattern: operator < |
269 | 0 | static inline bool match31(const Token* tok) { |
270 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("operator"))) |
271 | 0 | return false; |
272 | 0 | tok = tok->next(); |
273 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
274 | 0 | return false; |
275 | 0 | return true; |
276 | 0 | } |
277 | | // pattern: %type% |
278 | 0 | static inline bool match32(const Token* tok) { |
279 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
280 | 0 | return false; |
281 | 0 | return true; |
282 | 0 | } |
283 | | // pattern: *| %type%|%num% ; |
284 | 0 | static inline bool match33(const Token* tok) { |
285 | 0 | if (tok && (((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))) |
286 | 0 | tok = tok->next(); |
287 | 0 | if (!tok || !((tok->isName() && tok->varId() == 0U) || tok->isNumber())) |
288 | 0 | return false; |
289 | 0 | tok = tok->next(); |
290 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
291 | 0 | return false; |
292 | 0 | return true; |
293 | 0 | } |
294 | | // pattern: *| %type% . %type% ; |
295 | 0 | static inline bool match34(const Token* tok) { |
296 | 0 | if (tok && (((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))) |
297 | 0 | tok = tok->next(); |
298 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
299 | 0 | return false; |
300 | 0 | tok = tok->next(); |
301 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("."))) |
302 | 0 | return false; |
303 | 0 | tok = tok->next(); |
304 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
305 | 0 | return false; |
306 | 0 | tok = tok->next(); |
307 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
308 | 0 | return false; |
309 | 0 | return true; |
310 | 0 | } |
311 | | // pattern: (|{ |
312 | 1.06k | static inline bool match35(const Token* tok) { |
313 | 1.06k | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
314 | 1.04k | return false; |
315 | 27 | return true; |
316 | 1.06k | } |
317 | | // pattern: < typename |
318 | 0 | static inline bool match36(const Token* tok) { |
319 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
320 | 0 | return false; |
321 | 0 | tok = tok->next(); |
322 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("typename"))) |
323 | 0 | return false; |
324 | 0 | return true; |
325 | 0 | } |
326 | | // pattern: <|, %type% < |
327 | 0 | static inline bool match37(const Token* tok) { |
328 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))) |
329 | 0 | return false; |
330 | 0 | tok = tok->next(); |
331 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
332 | 0 | return false; |
333 | 0 | tok = tok->next(); |
334 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
335 | 0 | return false; |
336 | 0 | return true; |
337 | 0 | } |
338 | | // pattern: < %type% |
339 | 0 | static inline bool match38(const Token* tok) { |
340 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
341 | 0 | return false; |
342 | 0 | tok = tok->next(); |
343 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
344 | 0 | return false; |
345 | 0 | return true; |
346 | 0 | } |
347 | | // pattern: %var% < |
348 | 366 | static inline bool match39(const Token* tok) { |
349 | 366 | if (!tok || !(tok->varId() != 0)) |
350 | 366 | return false; |
351 | 0 | tok = tok->next(); |
352 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
353 | 0 | return false; |
354 | 0 | return true; |
355 | 0 | } |
356 | | // pattern: template < |
357 | 114k | static inline bool match40(const Token* tok) { |
358 | 114k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
359 | 114k | return false; |
360 | 0 | tok = tok->next(); |
361 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
362 | 0 | return false; |
363 | 0 | return true; |
364 | 0 | } |
365 | | // pattern: >|>>|>>= |
366 | 701 | static inline bool match41(const Token* tok) { |
367 | 701 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || (tok->str() == MatchCompiler::makeConstString(">>=")))) |
368 | 674 | return false; |
369 | 27 | return true; |
370 | 701 | } |
371 | | // pattern: const|volatile |
372 | 1.09k | static inline bool match42(const Token* tok) { |
373 | 1.09k | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("volatile")))) |
374 | 1.09k | return false; |
375 | 0 | return true; |
376 | 1.09k | } |
377 | | // pattern: struct|union |
378 | 1.06k | static inline bool match43(const Token* tok) { |
379 | 1.06k | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")))) |
380 | 1.06k | return false; |
381 | 0 | return true; |
382 | 1.06k | } |
383 | | // pattern: & ::| %name% |
384 | 1.06k | static inline bool match44(const Token* tok) { |
385 | 1.06k | if (!tok || !((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&"))) |
386 | 1.06k | return false; |
387 | 2 | tok = tok->next(); |
388 | 2 | if (tok && ((tok->str() == MatchCompiler::makeConstString("::")))) |
389 | 0 | tok = tok->next(); |
390 | 2 | if (!tok || !tok->isName()) |
391 | 0 | return false; |
392 | 2 | return true; |
393 | 2 | } |
394 | | // pattern: ... |
395 | 1.06k | static inline bool match45(const Token* tok) { |
396 | 1.06k | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
397 | 1.06k | return false; |
398 | 0 | return true; |
399 | 1.06k | } |
400 | | // pattern: <|,|:: |
401 | 0 | static inline bool match46(const Token* tok) { |
402 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
403 | 0 | return false; |
404 | 0 | return true; |
405 | 0 | } |
406 | | // pattern: >|&|&&|* |
407 | 0 | static inline bool match47(const Token* tok) { |
408 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")))) |
409 | 0 | return false; |
410 | 0 | return true; |
411 | 0 | } |
412 | | // pattern: =|?|: |
413 | 1.06k | static inline bool match48(const Token* tok) { |
414 | 1.06k | if (!tok || !(((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")))) |
415 | 1.05k | return false; |
416 | 12 | return true; |
417 | 1.06k | } |
418 | | // pattern: *|&|&&|const |
419 | 724 | static inline bool match49(const Token* tok) { |
420 | 724 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")))) |
421 | 698 | return false; |
422 | 26 | return true; |
423 | 724 | } |
424 | | // pattern: %num% |
425 | 24 | static inline bool match50(const Token* tok) { |
426 | 24 | if (!tok || !tok->isNumber()) |
427 | 24 | return false; |
428 | 0 | return true; |
429 | 24 | } |
430 | | // pattern: %name% (|{ |
431 | 0 | static inline bool match51(const Token* tok) { |
432 | 0 | if (!tok || !tok->isName()) |
433 | 0 | return false; |
434 | 0 | tok = tok->next(); |
435 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
436 | 0 | return false; |
437 | 0 | return true; |
438 | 0 | } |
439 | | // pattern: %any% %any% |
440 | 0 | static inline bool match52(const Token* tok) { |
441 | 0 | if (!tok || false) |
442 | 0 | return false; |
443 | 0 | tok = tok->next(); |
444 | 0 | if (!tok || false) |
445 | 0 | return false; |
446 | 0 | return true; |
447 | 0 | } |
448 | | // pattern: %name%|...|,|=|> |
449 | 0 | static inline bool match53(const Token* tok) { |
450 | 0 | if (!tok || !(tok->isName() || ((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("...")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
451 | 0 | return false; |
452 | 0 | return true; |
453 | 0 | } |
454 | | // pattern: decltype ( |
455 | 0 | static inline bool match54(const Token* tok) { |
456 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("decltype"))) |
457 | 0 | return false; |
458 | 0 | tok = tok->next(); |
459 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
460 | 0 | return false; |
461 | 0 | return true; |
462 | 0 | } |
463 | | // pattern: {|=|; |
464 | 0 | static inline bool match55(const Token* tok) { |
465 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || (tok->str() == MatchCompiler::makeConstString(";")))) |
466 | 0 | return false; |
467 | 0 | return true; |
468 | 0 | } |
469 | | // pattern: %name% ( |
470 | 0 | static inline bool match56(const Token* tok) { |
471 | 0 | if (!tok || !tok->isName()) |
472 | 0 | return false; |
473 | 0 | tok = tok->next(); |
474 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
475 | 0 | return false; |
476 | 0 | return true; |
477 | 0 | } |
478 | | // pattern: > ( |
479 | 0 | static inline bool match57(const Token* tok) { |
480 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
481 | 0 | return false; |
482 | 0 | tok = tok->next(); |
483 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
484 | 0 | return false; |
485 | 0 | return true; |
486 | 0 | } |
487 | | // pattern: ) const |
488 | 0 | static inline bool match58(const Token* tok) { |
489 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
490 | 0 | return false; |
491 | 0 | tok = tok->next(); |
492 | 0 | if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const"))) |
493 | 0 | return false; |
494 | 0 | return true; |
495 | 0 | } |
496 | | // pattern: typename|class %name% ,|> |
497 | 0 | static inline bool match59(const Token* tok) { |
498 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("typename")) || (tok->str() == MatchCompiler::makeConstString("class")))) |
499 | 0 | return false; |
500 | 0 | tok = tok->next(); |
501 | 0 | if (!tok || !tok->isName()) |
502 | 0 | return false; |
503 | 0 | tok = tok->next(); |
504 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
505 | 0 | return false; |
506 | 0 | return true; |
507 | 0 | } |
508 | | // pattern: %type% %name% ::|< |
509 | 0 | static inline bool match60(const Token* tok) { |
510 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
511 | 0 | return false; |
512 | 0 | tok = tok->next(); |
513 | 0 | if (!tok || !tok->isName()) |
514 | 0 | return false; |
515 | 0 | tok = tok->next(); |
516 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("::")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))) |
517 | 0 | return false; |
518 | 0 | return true; |
519 | 0 | } |
520 | | // pattern: [,:] private|protected|public %name% ::|< |
521 | 0 | static inline bool match61(const Token* tok) { |
522 | 0 | if (!tok || tok->str().size() != 1U || !strchr(",:", tok->str()[0])) |
523 | 0 | return false; |
524 | 0 | tok = tok->next(); |
525 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("private")) || (tok->str() == MatchCompiler::makeConstString("protected")) || (tok->str() == MatchCompiler::makeConstString("public")))) |
526 | 0 | return false; |
527 | 0 | tok = tok->next(); |
528 | 0 | if (!tok || !tok->isName()) |
529 | 0 | return false; |
530 | 0 | tok = tok->next(); |
531 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("::")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))) |
532 | 0 | return false; |
533 | 0 | return true; |
534 | 0 | } |
535 | | // pattern: (|{|}|;|=|>|<<|:|.|*|&|return|<|,|!|[ %name% ::|<|( |
536 | 0 | static inline bool match62(const Token* tok) { |
537 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(".")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))) |
538 | 0 | return false; |
539 | 0 | tok = tok->next(); |
540 | 0 | if (!tok || !tok->isName()) |
541 | 0 | return false; |
542 | 0 | tok = tok->next(); |
543 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("::")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
544 | 0 | return false; |
545 | 0 | return true; |
546 | 0 | } |
547 | | // pattern: (|{|}|;|=|<<|:|.|*|&|return|<|,|!|[ :: %name% ::|<|( |
548 | 0 | static inline bool match63(const Token* tok) { |
549 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(".")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("!")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))) |
550 | 0 | return false; |
551 | 0 | tok = tok->next(); |
552 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
553 | 0 | return false; |
554 | 0 | tok = tok->next(); |
555 | 0 | if (!tok || !tok->isName()) |
556 | 0 | return false; |
557 | 0 | tok = tok->next(); |
558 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("::")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
559 | 0 | return false; |
560 | 0 | return true; |
561 | 0 | } |
562 | | // pattern: template using %name% < |
563 | 0 | static inline bool match64(const Token* tok) { |
564 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
565 | 0 | return false; |
566 | 0 | tok = tok->next(); |
567 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("using"))) |
568 | 0 | return false; |
569 | 0 | tok = tok->next(); |
570 | 0 | if (!tok || !tok->isName()) |
571 | 0 | return false; |
572 | 0 | tok = tok->next(); |
573 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
574 | 0 | return false; |
575 | 0 | return true; |
576 | 0 | } |
577 | | // pattern: using %name% < |
578 | 0 | static inline bool match65(const Token* tok) { |
579 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("using"))) |
580 | 0 | return false; |
581 | 0 | tok = tok->next(); |
582 | 0 | if (!tok || !tok->isName()) |
583 | 0 | return false; |
584 | 0 | tok = tok->next(); |
585 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
586 | 0 | return false; |
587 | 0 | return true; |
588 | 0 | } |
589 | | // pattern: %num%|%str%|%char%|%bool% ,|) |
590 | 0 | static inline bool match66(const Token* tok) { |
591 | 0 | if (!tok || !(tok->isNumber() || (tok->tokType() == Token::eString) || (tok->tokType() == Token::eChar) || tok->isBoolean())) |
592 | 0 | return false; |
593 | 0 | tok = tok->next(); |
594 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))) |
595 | 0 | return false; |
596 | 0 | return true; |
597 | 0 | } |
598 | | // pattern: const| %type% &| %name%| ,|) |
599 | 0 | static inline bool match67(const Token* tok) { |
600 | 0 | if (tok && (((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")))) |
601 | 0 | tok = tok->next(); |
602 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
603 | 0 | return false; |
604 | 0 | tok = tok->next(); |
605 | 0 | if (tok && (((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))) |
606 | 0 | tok = tok->next(); |
607 | 0 | if (tok && (tok->isName())) |
608 | 0 | tok = tok->next(); |
609 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))) |
610 | 0 | return false; |
611 | 0 | return true; |
612 | 0 | } |
613 | | // pattern: const_cast|dynamic_cast|reinterpret_cast|static_cast |
614 | 0 | static inline bool match68(const Token* tok) { |
615 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("const_cast")) || (tok->str() == MatchCompiler::makeConstString("dynamic_cast")) || (tok->str() == MatchCompiler::makeConstString("reinterpret_cast")) || (tok->str() == MatchCompiler::makeConstString("static_cast")))) |
616 | 0 | return false; |
617 | 0 | return true; |
618 | 0 | } |
619 | | // pattern: ,|< %name% < |
620 | 0 | static inline bool match69(const Token* tok) { |
621 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))) |
622 | 0 | return false; |
623 | 0 | tok = tok->next(); |
624 | 0 | if (!tok || !tok->isName()) |
625 | 0 | return false; |
626 | 0 | tok = tok->next(); |
627 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
628 | 0 | return false; |
629 | 0 | return true; |
630 | 0 | } |
631 | | // pattern: class|struct |
632 | 0 | static inline bool match70(const Token* tok) { |
633 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")))) |
634 | 0 | return false; |
635 | 0 | return true; |
636 | 0 | } |
637 | | // pattern: {|(|[ |
638 | 0 | static inline bool match71(const Token* tok) { |
639 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))) |
640 | 0 | return false; |
641 | 0 | return true; |
642 | 0 | } |
643 | | // pattern: typename|class|%type% %name% ,|> |
644 | 0 | static inline bool match72(const Token* tok) { |
645 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("typename")) || (tok->str() == MatchCompiler::makeConstString("class")) || (tok->isName() && tok->varId() == 0U))) |
646 | 0 | return false; |
647 | 0 | tok = tok->next(); |
648 | 0 | if (!tok || !tok->isName()) |
649 | 0 | return false; |
650 | 0 | tok = tok->next(); |
651 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
652 | 0 | return false; |
653 | 0 | return true; |
654 | 0 | } |
655 | | // pattern: = !!> |
656 | 0 | static inline bool match73(const Token* tok) { |
657 | 0 | if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("="))) |
658 | 0 | return false; |
659 | 0 | tok = tok->next(); |
660 | 0 | if (tok && tok->str() == MatchCompiler::makeConstString(">")) |
661 | 0 | return false; |
662 | 0 | return true; |
663 | 0 | } |
664 | | // pattern: (|[|{ |
665 | 0 | static inline bool match74(const Token* tok) { |
666 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
667 | 0 | return false; |
668 | 0 | return true; |
669 | 0 | } |
670 | | // pattern: )|]|} |
671 | 0 | static inline bool match75(const Token* tok) { |
672 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))) |
673 | 0 | return false; |
674 | 0 | return true; |
675 | 0 | } |
676 | | // pattern: ;|)|}|] |
677 | 0 | static inline bool match76(const Token* tok) { |
678 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))) |
679 | 0 | return false; |
680 | 0 | return true; |
681 | 0 | } |
682 | | // pattern: (|{|[ |
683 | 0 | static inline bool match77(const Token* tok) { |
684 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")))) |
685 | 0 | return false; |
686 | 0 | return true; |
687 | 0 | } |
688 | | // pattern: ,|> |
689 | 0 | static inline bool match78(const Token* tok) { |
690 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
691 | 0 | return false; |
692 | 0 | return true; |
693 | 0 | } |
694 | | // pattern: [,>;{}] |
695 | 0 | static inline bool match79(const Token* tok) { |
696 | 0 | if (!tok || tok->str().size() != 1U || !strchr(",>;{}", tok->str()[0])) |
697 | 0 | return false; |
698 | 0 | return true; |
699 | 0 | } |
700 | | // pattern: %type% ( |
701 | 0 | static inline bool match80(const Token* tok) { |
702 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
703 | 0 | return false; |
704 | 0 | tok = tok->next(); |
705 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
706 | 0 | return false; |
707 | 0 | return true; |
708 | 0 | } |
709 | | // pattern: ;|{|(|using |
710 | 0 | static inline bool match81(const Token* tok) { |
711 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || (tok->str() == MatchCompiler::makeConstString("using")))) |
712 | 0 | return false; |
713 | 0 | return true; |
714 | 0 | } |
715 | | // pattern: %type% =|; |
716 | 0 | static inline bool match82(const Token* tok) { |
717 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
718 | 0 | return false; |
719 | 0 | tok = tok->next(); |
720 | 0 | if (!tok || !(((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || (tok->str() == MatchCompiler::makeConstString(";")))) |
721 | 0 | return false; |
722 | 0 | return true; |
723 | 0 | } |
724 | | // pattern: > friend| class|struct|union %type% :|<|;|{|:: |
725 | 0 | static inline bool match83(const Token* tok) { |
726 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
727 | 0 | return false; |
728 | 0 | tok = tok->next(); |
729 | 0 | if (tok && ((tok->str() == MatchCompiler::makeConstString("friend")))) |
730 | 0 | tok = tok->next(); |
731 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")))) |
732 | 0 | return false; |
733 | 0 | tok = tok->next(); |
734 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
735 | 0 | return false; |
736 | 0 | tok = tok->next(); |
737 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
738 | 0 | return false; |
739 | 0 | return true; |
740 | 0 | } |
741 | | // pattern: %type% :: %type% |
742 | 0 | static inline bool match84(const Token* tok) { |
743 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
744 | 0 | return false; |
745 | 0 | tok = tok->next(); |
746 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
747 | 0 | return false; |
748 | 0 | tok = tok->next(); |
749 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
750 | 0 | return false; |
751 | 0 | return true; |
752 | 0 | } |
753 | | // pattern: > :: %type% |
754 | 0 | static inline bool match85(const Token* tok) { |
755 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
756 | 0 | return false; |
757 | 0 | tok = tok->next(); |
758 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
759 | 0 | return false; |
760 | 0 | tok = tok->next(); |
761 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
762 | 0 | return false; |
763 | 0 | return true; |
764 | 0 | } |
765 | | // pattern: > using %name% = |
766 | 0 | static inline bool match86(const Token* tok) { |
767 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
768 | 0 | return false; |
769 | 0 | tok = tok->next(); |
770 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("using"))) |
771 | 0 | return false; |
772 | 0 | tok = tok->next(); |
773 | 0 | if (!tok || !tok->isName()) |
774 | 0 | return false; |
775 | 0 | tok = tok->next(); |
776 | 0 | if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("="))) |
777 | 0 | return false; |
778 | 0 | return true; |
779 | 0 | } |
780 | | // pattern: class|struct|union|enum %name%| { |
781 | 0 | static inline bool match87(const Token* tok) { |
782 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("enum")))) |
783 | 0 | return false; |
784 | 0 | tok = tok->next(); |
785 | 0 | if (tok && (tok->isName())) |
786 | 0 | tok = tok->next(); |
787 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
788 | 0 | return false; |
789 | 0 | return true; |
790 | 0 | } |
791 | | // pattern: {|[|( |
792 | 0 | static inline bool match88(const Token* tok) { |
793 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
794 | 0 | return false; |
795 | 0 | return true; |
796 | 0 | } |
797 | | // pattern: ;|{|: |
798 | 0 | static inline bool match89(const Token* tok) { |
799 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")))) |
800 | 0 | return false; |
801 | 0 | return true; |
802 | 0 | } |
803 | | // pattern: <|(|{ |
804 | 0 | static inline bool match90(const Token* tok) { |
805 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
806 | 0 | return false; |
807 | 0 | return true; |
808 | 0 | } |
809 | | // pattern: >|)|} |
810 | 0 | static inline bool match91(const Token* tok) { |
811 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")))) |
812 | 0 | return false; |
813 | 0 | return true; |
814 | 0 | } |
815 | | // pattern: <|, %type% >|, |
816 | 0 | static inline bool match92(const Token* tok) { |
817 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))) |
818 | 0 | return false; |
819 | 0 | tok = tok->next(); |
820 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
821 | 0 | return false; |
822 | 0 | tok = tok->next(); |
823 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))) |
824 | 0 | return false; |
825 | 0 | return true; |
826 | 0 | } |
827 | | // pattern: %name% ... %name% |
828 | 0 | static inline bool match93(const Token* tok) { |
829 | 0 | if (!tok || !tok->isName()) |
830 | 0 | return false; |
831 | 0 | tok = tok->next(); |
832 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
833 | 0 | return false; |
834 | 0 | tok = tok->next(); |
835 | 0 | if (!tok || !tok->isName()) |
836 | 0 | return false; |
837 | 0 | return true; |
838 | 0 | } |
839 | | // pattern: const |
840 | 0 | static inline bool match94(const Token* tok) { |
841 | 0 | if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const"))) |
842 | 0 | return false; |
843 | 0 | return true; |
844 | 0 | } |
845 | | // pattern: . template |
846 | 0 | static inline bool match95(const Token* tok) { |
847 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("."))) |
848 | 0 | return false; |
849 | 0 | tok = tok->next(); |
850 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
851 | 0 | return false; |
852 | 0 | return true; |
853 | 0 | } |
854 | | // pattern: [|{|( |
855 | 0 | static inline bool match96(const Token* tok) { |
856 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
857 | 0 | return false; |
858 | 0 | return true; |
859 | 0 | } |
860 | | // pattern: ]|}|) |
861 | 0 | static inline bool match97(const Token* tok) { |
862 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))) |
863 | 0 | return false; |
864 | 0 | return true; |
865 | 0 | } |
866 | | // pattern: }|;|extern |
867 | 0 | static inline bool match98(const Token* tok) { |
868 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("extern")))) |
869 | 0 | return false; |
870 | 0 | return true; |
871 | 0 | } |
872 | | // pattern: template !!< |
873 | 0 | static inline bool match99(const Token* tok) { |
874 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("template"))) |
875 | 0 | return false; |
876 | 0 | tok = tok->next(); |
877 | 0 | if (tok && tok->str() == MatchCompiler::makeConstString("<")) |
878 | 0 | return false; |
879 | 0 | return true; |
880 | 0 | } |
881 | | // pattern: class|typename|struct |
882 | 0 | static inline bool match100(const Token* tok) { |
883 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || (tok->str() == MatchCompiler::makeConstString("typename")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")))) |
884 | 0 | return false; |
885 | 0 | return true; |
886 | 0 | } |
887 | | // pattern: const_cast|dynamic_cast|reinterpret_cast|static_cast < |
888 | 0 | static inline bool match101(const Token* tok) { |
889 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("const_cast")) || (tok->str() == MatchCompiler::makeConstString("dynamic_cast")) || (tok->str() == MatchCompiler::makeConstString("reinterpret_cast")) || (tok->str() == MatchCompiler::makeConstString("static_cast")))) |
890 | 0 | return false; |
891 | 0 | tok = tok->next(); |
892 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
893 | 0 | return false; |
894 | 0 | return true; |
895 | 0 | } |
896 | | // pattern: < |
897 | 0 | static inline bool match102(const Token* tok) { |
898 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
899 | 0 | return false; |
900 | 0 | return true; |
901 | 0 | } |
902 | | // pattern: (|:: |
903 | 0 | static inline bool match103(const Token* tok) { |
904 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
905 | 0 | return false; |
906 | 0 | return true; |
907 | 0 | } |
908 | | // pattern: > friend class|struct|union |
909 | 0 | static inline bool match104(const Token* tok) { |
910 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
911 | 0 | return false; |
912 | 0 | tok = tok->next(); |
913 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("friend"))) |
914 | 0 | return false; |
915 | 0 | tok = tok->next(); |
916 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("union")))) |
917 | 0 | return false; |
918 | 0 | return true; |
919 | 0 | } |
920 | | // pattern: [:{=;[]),] |
921 | 0 | static inline bool match105(const Token* tok) { |
922 | 0 | if (!tok || tok->str().size() != 1U || !strchr(":{=;[]),", tok->str()[0])) |
923 | 0 | return false; |
924 | 0 | return true; |
925 | 0 | } |
926 | | // pattern: template|static_cast|const_cast|reinterpret_cast|dynamic_cast |
927 | 0 | static inline bool match106(const Token* tok) { |
928 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("template")) || (tok->str() == MatchCompiler::makeConstString("static_cast")) || (tok->str() == MatchCompiler::makeConstString("const_cast")) || (tok->str() == MatchCompiler::makeConstString("reinterpret_cast")) || (tok->str() == MatchCompiler::makeConstString("dynamic_cast")))) |
929 | 0 | return false; |
930 | 0 | return true; |
931 | 0 | } |
932 | | // pattern: >|>> |
933 | 0 | static inline bool match107(const Token* tok) { |
934 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")))) |
935 | 0 | return false; |
936 | 0 | return true; |
937 | 0 | } |
938 | | // pattern: & |
939 | 0 | static inline bool match108(const Token* tok) { |
940 | 0 | if (!tok || !((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&"))) |
941 | 0 | return false; |
942 | 0 | return true; |
943 | 0 | } |
944 | | // pattern: } >|,|{ |
945 | 0 | static inline bool match109(const Token* tok) { |
946 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))) |
947 | 0 | return false; |
948 | 0 | tok = tok->next(); |
949 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
950 | 0 | return false; |
951 | 0 | return true; |
952 | 0 | } |
953 | | // pattern: }|;|(|[|]|)|,|?|:|%oror%|return|throw|case |
954 | 0 | static inline bool match110(const Token* tok) { |
955 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("[")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || (tok->str() == MatchCompiler::makeConstString("throw")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
956 | 0 | return false; |
957 | 0 | return true; |
958 | 0 | } |
959 | | // pattern: %comp%|<<|>> |
960 | 0 | static inline bool match111(const Token* tok) { |
961 | 0 | if (!tok || !(tok->isComparisonOp() || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")))) |
962 | 0 | return false; |
963 | 0 | return true; |
964 | 0 | } |
965 | | // pattern: +|- |
966 | 0 | static inline bool match112(const Token* tok) { |
967 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-")))) |
968 | 0 | return false; |
969 | 0 | return true; |
970 | 0 | } |
971 | | // pattern: [*/%] |
972 | 0 | static inline bool match113(const Token* tok) { |
973 | 0 | if (!tok || tok->str().size() != 1U || !strchr("*/%", tok->str()[0])) |
974 | 0 | return false; |
975 | 0 | return true; |
976 | 0 | } |
977 | | // pattern: * %num% / |
978 | 0 | static inline bool match114(const Token* tok) { |
979 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
980 | 0 | return false; |
981 | 0 | tok = tok->next(); |
982 | 0 | if (!tok || !tok->isNumber()) |
983 | 0 | return false; |
984 | 0 | tok = tok->next(); |
985 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("/"))) |
986 | 0 | return false; |
987 | 0 | return true; |
988 | 0 | } |
989 | | // pattern: [/%] |
990 | 0 | static inline bool match115(const Token* tok) { |
991 | 0 | if (!tok || tok->str().size() != 1U || !strchr("/%", tok->str()[0])) |
992 | 0 | return false; |
993 | 0 | return true; |
994 | 0 | } |
995 | | // pattern: [+-] |
996 | 0 | static inline bool match116(const Token* tok) { |
997 | 0 | if (!tok || tok->str().size() != 1U || !strchr("+-", tok->str()[0])) |
998 | 0 | return false; |
999 | 0 | return true; |
1000 | 0 | } |
1001 | | // pattern: >>|<< |
1002 | 0 | static inline bool match117(const Token* tok) { |
1003 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")))) |
1004 | 0 | return false; |
1005 | 0 | return true; |
1006 | 0 | } |
1007 | | // pattern: [/%] 0 |
1008 | 0 | static inline bool match118(const Token* tok) { |
1009 | 0 | if (!tok || tok->str().size() != 1U || !strchr("/%", tok->str()[0])) |
1010 | 0 | return false; |
1011 | 0 | tok = tok->next(); |
1012 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1013 | 0 | return false; |
1014 | 0 | return true; |
1015 | 0 | } |
1016 | | // pattern: >>|<<|&|^|%or% |
1017 | 0 | static inline bool match119(const Token* tok) { |
1018 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("<<")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("^")) || (tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") ))) |
1019 | 0 | return false; |
1020 | 0 | return true; |
1021 | 0 | } |
1022 | | // pattern: %oror%|&& |
1023 | 0 | static inline bool match120(const Token* tok) { |
1024 | 0 | if (!tok || !((tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")))) |
1025 | 0 | return false; |
1026 | 0 | return true; |
1027 | 0 | } |
1028 | | // pattern: - %num% - %num% |
1029 | 0 | static inline bool match121(const Token* tok) { |
1030 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))) |
1031 | 0 | return false; |
1032 | 0 | tok = tok->next(); |
1033 | 0 | if (!tok || !tok->isNumber()) |
1034 | 0 | return false; |
1035 | 0 | tok = tok->next(); |
1036 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))) |
1037 | 0 | return false; |
1038 | 0 | tok = tok->next(); |
1039 | 0 | if (!tok || !tok->isNumber()) |
1040 | 0 | return false; |
1041 | 0 | return true; |
1042 | 0 | } |
1043 | | // pattern: - %num% + %num% |
1044 | 0 | static inline bool match122(const Token* tok) { |
1045 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("-"))) |
1046 | 0 | return false; |
1047 | 0 | tok = tok->next(); |
1048 | 0 | if (!tok || !tok->isNumber()) |
1049 | 0 | return false; |
1050 | 0 | tok = tok->next(); |
1051 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("+"))) |
1052 | 0 | return false; |
1053 | 0 | tok = tok->next(); |
1054 | 0 | if (!tok || !tok->isNumber()) |
1055 | 0 | return false; |
1056 | 0 | return true; |
1057 | 0 | } |
1058 | | // pattern: [{};)] |
1059 | 0 | static inline bool match123(const Token* tok) { |
1060 | 0 | if (!tok || tok->str().size() != 1U || !strchr("{};)", tok->str()[0])) |
1061 | 0 | return false; |
1062 | 0 | return true; |
1063 | 0 | } |
1064 | | // pattern: ( %char% ) |
1065 | 0 | static inline bool match124(const Token* tok) { |
1066 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1067 | 0 | return false; |
1068 | 0 | tok = tok->next(); |
1069 | 0 | if (!tok || !(tok->tokType() == Token::eChar)) |
1070 | 0 | return false; |
1071 | 0 | tok = tok->next(); |
1072 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1073 | 0 | return false; |
1074 | 0 | return true; |
1075 | 0 | } |
1076 | | // pattern: ( %str% ) |
1077 | 0 | static inline bool match125(const Token* tok) { |
1078 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1079 | 0 | return false; |
1080 | 0 | tok = tok->next(); |
1081 | 0 | if (!tok || !(tok->tokType() == Token::eString)) |
1082 | 0 | return false; |
1083 | 0 | tok = tok->next(); |
1084 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1085 | 0 | return false; |
1086 | 0 | return true; |
1087 | 0 | } |
1088 | | // pattern: ( %type% * ) |
1089 | 0 | static inline bool match126(const Token* tok) { |
1090 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1091 | 0 | return false; |
1092 | 0 | tok = tok->next(); |
1093 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
1094 | 0 | return false; |
1095 | 0 | tok = tok->next(); |
1096 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1097 | 0 | return false; |
1098 | 0 | tok = tok->next(); |
1099 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1100 | 0 | return false; |
1101 | 0 | return true; |
1102 | 0 | } |
1103 | | // pattern: ( * ) |
1104 | 0 | static inline bool match127(const Token* tok) { |
1105 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1106 | 0 | return false; |
1107 | 0 | tok = tok->next(); |
1108 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1109 | 0 | return false; |
1110 | 0 | tok = tok->next(); |
1111 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1112 | 0 | return false; |
1113 | 0 | return true; |
1114 | 0 | } |
1115 | | // pattern: ( %type% ) |
1116 | 0 | static inline bool match128(const Token* tok) { |
1117 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1118 | 0 | return false; |
1119 | 0 | tok = tok->next(); |
1120 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
1121 | 0 | return false; |
1122 | 0 | tok = tok->next(); |
1123 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1124 | 0 | return false; |
1125 | 0 | return true; |
1126 | 0 | } |
1127 | | // pattern: %num% %comp% %num% |
1128 | 0 | static inline bool match129(const Token* tok) { |
1129 | 0 | if (!tok || !tok->isNumber()) |
1130 | 0 | return false; |
1131 | 0 | tok = tok->next(); |
1132 | 0 | if (!tok || !tok->isComparisonOp()) |
1133 | 0 | return false; |
1134 | 0 | tok = tok->next(); |
1135 | 0 | if (!tok || !tok->isNumber()) |
1136 | 0 | return false; |
1137 | 0 | return true; |
1138 | 0 | } |
1139 | | // pattern: (|&&|%oror%|, |
1140 | 0 | static inline bool match130(const Token* tok) { |
1141 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")))) |
1142 | 0 | return false; |
1143 | 0 | return true; |
1144 | 0 | } |
1145 | | // pattern: )|&&|%oror%|? |
1146 | 0 | static inline bool match131(const Token* tok) { |
1147 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("?")))) |
1148 | 0 | return false; |
1149 | 0 | return true; |
1150 | 0 | } |
1151 | | // pattern: ( %bool%|%num% ) |
1152 | 0 | static inline bool match132(const Token* tok) { |
1153 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1154 | 0 | return false; |
1155 | 0 | tok = tok->next(); |
1156 | 0 | if (!tok || !(tok->isBoolean() || tok->isNumber())) |
1157 | 0 | return false; |
1158 | 0 | tok = tok->next(); |
1159 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1160 | 0 | return false; |
1161 | 0 | return true; |
1162 | 0 | } |
1163 | | // pattern: false|0 |
1164 | 0 | static inline bool match133(const Token* tok) { |
1165 | 0 | if (!tok || !(((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("false")) || (tok->str() == MatchCompiler::makeConstString("0")))) |
1166 | 0 | return false; |
1167 | 0 | return true; |
1168 | 0 | } |
1169 | | // pattern: )|}|]|;|,|:|> |
1170 | 0 | static inline bool match134(const Token* tok) { |
1171 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
1172 | 0 | return false; |
1173 | 0 | return true; |
1174 | 0 | } |
1175 | | // pattern: ( %num%|%bool% ) |
1176 | 0 | static inline bool match135(const Token* tok) { |
1177 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1178 | 0 | return false; |
1179 | 0 | tok = tok->next(); |
1180 | 0 | if (!tok || !(tok->isNumber() || tok->isBoolean())) |
1181 | 0 | return false; |
1182 | 0 | tok = tok->next(); |
1183 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1184 | 0 | return false; |
1185 | 0 | return true; |
1186 | 0 | } |
1187 | | // pattern: ( %name% ) ;|)|,|] |
1188 | 0 | static inline bool match136(const Token* tok) { |
1189 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1190 | 0 | return false; |
1191 | 0 | tok = tok->next(); |
1192 | 0 | if (!tok || !tok->isName()) |
1193 | 0 | return false; |
1194 | 0 | tok = tok->next(); |
1195 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1196 | 0 | return false; |
1197 | 0 | tok = tok->next(); |
1198 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))) |
1199 | 0 | return false; |
1200 | 0 | return true; |
1201 | 0 | } |
1202 | | // pattern: ( %name% ) %cop% |
1203 | 0 | static inline bool match137(const Token* tok) { |
1204 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1205 | 0 | return false; |
1206 | 0 | tok = tok->next(); |
1207 | 0 | if (!tok || !tok->isName()) |
1208 | 0 | return false; |
1209 | 0 | tok = tok->next(); |
1210 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1211 | 0 | return false; |
1212 | 0 | tok = tok->next(); |
1213 | 0 | if (!tok || !tok->isConstOp()) |
1214 | 0 | return false; |
1215 | 0 | return true; |
1216 | 0 | } |
1217 | | // pattern: [*&+-~] |
1218 | 0 | static inline bool match138(const Token* tok) { |
1219 | 0 | if (!tok || tok->str().size() != 1U || !strchr("*&+-~", tok->str()[0])) |
1220 | 0 | return false; |
1221 | 0 | return true; |
1222 | 0 | } |
1223 | | // pattern: (|&&|%oror% %char% %comp% %num% &&|%oror%|) |
1224 | 0 | static inline bool match139(const Token* tok) { |
1225 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")))) |
1226 | 0 | return false; |
1227 | 0 | tok = tok->next(); |
1228 | 0 | if (!tok || !(tok->tokType() == Token::eChar)) |
1229 | 0 | return false; |
1230 | 0 | tok = tok->next(); |
1231 | 0 | if (!tok || !tok->isComparisonOp()) |
1232 | 0 | return false; |
1233 | 0 | tok = tok->next(); |
1234 | 0 | if (!tok || !tok->isNumber()) |
1235 | 0 | return false; |
1236 | 0 | tok = tok->next(); |
1237 | 0 | if (!tok || !(((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")))) |
1238 | 0 | return false; |
1239 | 0 | return true; |
1240 | 0 | } |
1241 | | // pattern: decltype ( %type% { } ) |
1242 | 0 | static inline bool match140(const Token* tok) { |
1243 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("decltype"))) |
1244 | 0 | return false; |
1245 | 0 | tok = tok->next(); |
1246 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1247 | 0 | return false; |
1248 | 0 | tok = tok->next(); |
1249 | 0 | if (!tok || !(tok->isName() && tok->varId() == 0U)) |
1250 | 0 | return false; |
1251 | 0 | tok = tok->next(); |
1252 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
1253 | 0 | return false; |
1254 | 0 | tok = tok->next(); |
1255 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))) |
1256 | 0 | return false; |
1257 | 0 | tok = tok->next(); |
1258 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1259 | 0 | return false; |
1260 | 0 | return true; |
1261 | 0 | } |
1262 | | // pattern: decltype ( %bool%|%num% ) |
1263 | 0 | static inline bool match141(const Token* tok) { |
1264 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("decltype"))) |
1265 | 0 | return false; |
1266 | 0 | tok = tok->next(); |
1267 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1268 | 0 | return false; |
1269 | 0 | tok = tok->next(); |
1270 | 0 | if (!tok || !(tok->isBoolean() || tok->isNumber())) |
1271 | 0 | return false; |
1272 | 0 | tok = tok->next(); |
1273 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1274 | 0 | return false; |
1275 | 0 | return true; |
1276 | 0 | } |
1277 | | // pattern: char|short|int|long { } |
1278 | 0 | static inline bool match142(const Token* tok) { |
1279 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("char")) || (tok->str() == MatchCompiler::makeConstString("short")) || (tok->str() == MatchCompiler::makeConstString("int")) || (tok->str() == MatchCompiler::makeConstString("long")))) |
1280 | 0 | return false; |
1281 | 0 | tok = tok->next(); |
1282 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{"))) |
1283 | 0 | return false; |
1284 | 0 | tok = tok->next(); |
1285 | 0 | if (!tok || !((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}"))) |
1286 | 0 | return false; |
1287 | 0 | return true; |
1288 | 0 | } |
1289 | | // pattern: char|short|int|long ( ) |
1290 | 0 | static inline bool match143(const Token* tok) { |
1291 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("char")) || (tok->str() == MatchCompiler::makeConstString("short")) || (tok->str() == MatchCompiler::makeConstString("int")) || (tok->str() == MatchCompiler::makeConstString("long")))) |
1292 | 0 | return false; |
1293 | 0 | tok = tok->next(); |
1294 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1295 | 0 | return false; |
1296 | 0 | tok = tok->next(); |
1297 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1298 | 0 | return false; |
1299 | 0 | return true; |
1300 | 0 | } |
1301 | | // pattern: [(=,] 0 && |
1302 | 0 | static inline bool match144(const Token* tok) { |
1303 | 0 | if (!tok || tok->str().size() != 1U || !strchr("(=,", tok->str()[0])) |
1304 | 0 | return false; |
1305 | 0 | tok = tok->next(); |
1306 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1307 | 0 | return false; |
1308 | 0 | tok = tok->next(); |
1309 | 0 | if (!tok || !((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))) |
1310 | 0 | return false; |
1311 | 0 | return true; |
1312 | 0 | } |
1313 | | // pattern: [(=,] 1 %oror% |
1314 | 0 | static inline bool match145(const Token* tok) { |
1315 | 0 | if (!tok || tok->str().size() != 1U || !strchr("(=,", tok->str()[0])) |
1316 | 0 | return false; |
1317 | 0 | tok = tok->next(); |
1318 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1319 | 0 | return false; |
1320 | 0 | tok = tok->next(); |
1321 | 0 | if (!tok || !(tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))) |
1322 | 0 | return false; |
1323 | 0 | return true; |
1324 | 0 | } |
1325 | | // pattern: [+-] 0 %cop%|; |
1326 | 0 | static inline bool match146(const Token* tok) { |
1327 | 0 | if (!tok || tok->str().size() != 1U || !strchr("+-", tok->str()[0])) |
1328 | 0 | return false; |
1329 | 0 | tok = tok->next(); |
1330 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1331 | 0 | return false; |
1332 | 0 | tok = tok->next(); |
1333 | 0 | if (!tok || !(tok->isConstOp() || (tok->str() == MatchCompiler::makeConstString(";")))) |
1334 | 0 | return false; |
1335 | 0 | return true; |
1336 | 0 | } |
1337 | | // pattern: %or% 0 %cop%|; |
1338 | 0 | static inline bool match147(const Token* tok) { |
1339 | 0 | if (!tok || !(tok->tokType() == Token::eBitOp && tok->str() == MatchCompiler::makeConstString("|") )) |
1340 | 0 | return false; |
1341 | 0 | tok = tok->next(); |
1342 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1343 | 0 | return false; |
1344 | 0 | tok = tok->next(); |
1345 | 0 | if (!tok || !(tok->isConstOp() || (tok->str() == MatchCompiler::makeConstString(";")))) |
1346 | 0 | return false; |
1347 | 0 | return true; |
1348 | 0 | } |
1349 | | // pattern: [;{}] %name% = %name% [+-|] 0 ; |
1350 | 0 | static inline bool match148(const Token* tok) { |
1351 | 0 | if (!tok || tok->str().size() != 1U || !strchr(";{}", tok->str()[0])) |
1352 | 0 | return false; |
1353 | 0 | tok = tok->next(); |
1354 | 0 | if (!tok || !tok->isName()) |
1355 | 0 | return false; |
1356 | 0 | tok = tok->next(); |
1357 | 0 | if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("="))) |
1358 | 0 | return false; |
1359 | 0 | tok = tok->next(); |
1360 | 0 | if (!tok || !tok->isName()) |
1361 | 0 | return false; |
1362 | 0 | tok = tok->next(); |
1363 | 0 | if (!tok || tok->str().size() != 1U || !strchr("+-|", tok->str()[0])) |
1364 | 0 | return false; |
1365 | 0 | tok = tok->next(); |
1366 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1367 | 0 | return false; |
1368 | 0 | tok = tok->next(); |
1369 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString(";"))) |
1370 | 0 | return false; |
1371 | 0 | return true; |
1372 | 0 | } |
1373 | | // pattern: [=([,] 0 [+|] |
1374 | 0 | static inline bool match149(const Token* tok) { |
1375 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=([,", tok->str()[0])) |
1376 | 0 | return false; |
1377 | 0 | tok = tok->next(); |
1378 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1379 | 0 | return false; |
1380 | 0 | tok = tok->next(); |
1381 | 0 | if (!tok || tok->str().size() != 1U || !strchr("+|", tok->str()[0])) |
1382 | 0 | return false; |
1383 | 0 | return true; |
1384 | 0 | } |
1385 | | // pattern: return|case 0 [+|] |
1386 | 0 | static inline bool match150(const Token* tok) { |
1387 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1388 | 0 | return false; |
1389 | 0 | tok = tok->next(); |
1390 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1391 | 0 | return false; |
1392 | 0 | tok = tok->next(); |
1393 | 0 | if (!tok || tok->str().size() != 1U || !strchr("+|", tok->str()[0])) |
1394 | 0 | return false; |
1395 | 0 | return true; |
1396 | 0 | } |
1397 | | // pattern: [=[(,] 0 * %name%|%num% ,|]|)|;|=|%cop% |
1398 | 0 | static inline bool match151(const Token* tok) { |
1399 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=[(,", tok->str()[0])) |
1400 | 0 | return false; |
1401 | 0 | tok = tok->next(); |
1402 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1403 | 0 | return false; |
1404 | 0 | tok = tok->next(); |
1405 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1406 | 0 | return false; |
1407 | 0 | tok = tok->next(); |
1408 | 0 | if (!tok || !(tok->isName() || tok->isNumber())) |
1409 | 0 | return false; |
1410 | 0 | tok = tok->next(); |
1411 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1412 | 0 | return false; |
1413 | 0 | return true; |
1414 | 0 | } |
1415 | | // pattern: return|case 0 *|&& %name%|%num% ,|:|;|=|%cop% |
1416 | 0 | static inline bool match152(const Token* tok) { |
1417 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1418 | 0 | return false; |
1419 | 0 | tok = tok->next(); |
1420 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1421 | 0 | return false; |
1422 | 0 | tok = tok->next(); |
1423 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")))) |
1424 | 0 | return false; |
1425 | 0 | tok = tok->next(); |
1426 | 0 | if (!tok || !(tok->isName() || tok->isNumber())) |
1427 | 0 | return false; |
1428 | 0 | tok = tok->next(); |
1429 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1430 | 0 | return false; |
1431 | 0 | return true; |
1432 | 0 | } |
1433 | | // pattern: [=[(,] 0 * ( |
1434 | 0 | static inline bool match153(const Token* tok) { |
1435 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=[(,", tok->str()[0])) |
1436 | 0 | return false; |
1437 | 0 | tok = tok->next(); |
1438 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1439 | 0 | return false; |
1440 | 0 | tok = tok->next(); |
1441 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1442 | 0 | return false; |
1443 | 0 | tok = tok->next(); |
1444 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1445 | 0 | return false; |
1446 | 0 | return true; |
1447 | 0 | } |
1448 | | // pattern: return|case 0 *|&& ( |
1449 | 0 | static inline bool match154(const Token* tok) { |
1450 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1451 | 0 | return false; |
1452 | 0 | tok = tok->next(); |
1453 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1454 | 0 | return false; |
1455 | 0 | tok = tok->next(); |
1456 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")))) |
1457 | 0 | return false; |
1458 | 0 | tok = tok->next(); |
1459 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1460 | 0 | return false; |
1461 | 0 | return true; |
1462 | 0 | } |
1463 | | // pattern: [=[(,] 0 && *|& %any% ,|]|)|;|=|%cop% |
1464 | 0 | static inline bool match155(const Token* tok) { |
1465 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=[(,", tok->str()[0])) |
1466 | 0 | return false; |
1467 | 0 | tok = tok->next(); |
1468 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1469 | 0 | return false; |
1470 | 0 | tok = tok->next(); |
1471 | 0 | if (!tok || !((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))) |
1472 | 0 | return false; |
1473 | 0 | tok = tok->next(); |
1474 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))) |
1475 | 0 | return false; |
1476 | 0 | tok = tok->next(); |
1477 | 0 | if (!tok || false) |
1478 | 0 | return false; |
1479 | 0 | tok = tok->next(); |
1480 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1481 | 0 | return false; |
1482 | 0 | return true; |
1483 | 0 | } |
1484 | | // pattern: return|case 0 && *|& %any% ,|:|;|=|%cop% |
1485 | 0 | static inline bool match156(const Token* tok) { |
1486 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1487 | 0 | return false; |
1488 | 0 | tok = tok->next(); |
1489 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1490 | 0 | return false; |
1491 | 0 | tok = tok->next(); |
1492 | 0 | if (!tok || !((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&"))) |
1493 | 0 | return false; |
1494 | 0 | tok = tok->next(); |
1495 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))) |
1496 | 0 | return false; |
1497 | 0 | tok = tok->next(); |
1498 | 0 | if (!tok || false) |
1499 | 0 | return false; |
1500 | 0 | tok = tok->next(); |
1501 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1502 | 0 | return false; |
1503 | 0 | return true; |
1504 | 0 | } |
1505 | | // pattern: [=[(,] 1 %oror% %any% ,|]|)|;|=|%cop% |
1506 | 0 | static inline bool match157(const Token* tok) { |
1507 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=[(,", tok->str()[0])) |
1508 | 0 | return false; |
1509 | 0 | tok = tok->next(); |
1510 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1511 | 0 | return false; |
1512 | 0 | tok = tok->next(); |
1513 | 0 | if (!tok || !(tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))) |
1514 | 0 | return false; |
1515 | 0 | tok = tok->next(); |
1516 | 0 | if (!tok || false) |
1517 | 0 | return false; |
1518 | 0 | tok = tok->next(); |
1519 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1520 | 0 | return false; |
1521 | 0 | return true; |
1522 | 0 | } |
1523 | | // pattern: return|case 1 %oror% %any% ,|:|;|=|%cop% |
1524 | 0 | static inline bool match158(const Token* tok) { |
1525 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1526 | 0 | return false; |
1527 | 0 | tok = tok->next(); |
1528 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1529 | 0 | return false; |
1530 | 0 | tok = tok->next(); |
1531 | 0 | if (!tok || !(tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))) |
1532 | 0 | return false; |
1533 | 0 | tok = tok->next(); |
1534 | 0 | if (!tok || false) |
1535 | 0 | return false; |
1536 | 0 | tok = tok->next(); |
1537 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1538 | 0 | return false; |
1539 | 0 | return true; |
1540 | 0 | } |
1541 | | // pattern: [=[(,] 1 %oror% *|& %any% ,|]|)|;|=|%cop% |
1542 | 0 | static inline bool match159(const Token* tok) { |
1543 | 0 | if (!tok || tok->str().size() != 1U || !strchr("=[(,", tok->str()[0])) |
1544 | 0 | return false; |
1545 | 0 | tok = tok->next(); |
1546 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1547 | 0 | return false; |
1548 | 0 | tok = tok->next(); |
1549 | 0 | if (!tok || !(tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))) |
1550 | 0 | return false; |
1551 | 0 | tok = tok->next(); |
1552 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))) |
1553 | 0 | return false; |
1554 | 0 | tok = tok->next(); |
1555 | 0 | if (!tok || false) |
1556 | 0 | return false; |
1557 | 0 | tok = tok->next(); |
1558 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1559 | 0 | return false; |
1560 | 0 | return true; |
1561 | 0 | } |
1562 | | // pattern: return|case 1 %oror% *|& %any% ,|:|;|=|%cop% |
1563 | 0 | static inline bool match160(const Token* tok) { |
1564 | 0 | if (!tok || !(((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("return")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("case")))) |
1565 | 0 | return false; |
1566 | 0 | tok = tok->next(); |
1567 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1568 | 0 | return false; |
1569 | 0 | tok = tok->next(); |
1570 | 0 | if (!tok || !(tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||"))) |
1571 | 0 | return false; |
1572 | 0 | tok = tok->next(); |
1573 | 0 | if (!tok || !(((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*")) || ((tok->tokType() == Token::eBitOp) && tok->str() == MatchCompiler::makeConstString("&")))) |
1574 | 0 | return false; |
1575 | 0 | tok = tok->next(); |
1576 | 0 | if (!tok || false) |
1577 | 0 | return false; |
1578 | 0 | tok = tok->next(); |
1579 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(":")) || (tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || tok->isConstOp())) |
1580 | 0 | return false; |
1581 | 0 | return true; |
1582 | 0 | } |
1583 | | // pattern: %any% * 1 |
1584 | 0 | static inline bool match161(const Token* tok) { |
1585 | 0 | if (!tok || false) |
1586 | 0 | return false; |
1587 | 0 | tok = tok->next(); |
1588 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1589 | 0 | return false; |
1590 | 0 | tok = tok->next(); |
1591 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1592 | 0 | return false; |
1593 | 0 | return true; |
1594 | 0 | } |
1595 | | // pattern: %any% 1 * |
1596 | 0 | static inline bool match162(const Token* tok) { |
1597 | 0 | if (!tok || false) |
1598 | 0 | return false; |
1599 | 0 | tok = tok->next(); |
1600 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("1"))) |
1601 | 0 | return false; |
1602 | 0 | tok = tok->next(); |
1603 | 0 | if (!tok || !((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString("*"))) |
1604 | 0 | return false; |
1605 | 0 | return true; |
1606 | 0 | } |
1607 | | // pattern: %op%|< ( %num% ) |
1608 | 0 | static inline bool match163(const Token* tok) { |
1609 | 0 | if (!tok || !(tok->isOp() || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))) |
1610 | 0 | return false; |
1611 | 0 | tok = tok->next(); |
1612 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1613 | 0 | return false; |
1614 | 0 | tok = tok->next(); |
1615 | 0 | if (!tok || !tok->isNumber()) |
1616 | 0 | return false; |
1617 | 0 | tok = tok->next(); |
1618 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1619 | 0 | return false; |
1620 | 0 | return true; |
1621 | 0 | } |
1622 | | // pattern: ( 0 [|+] |
1623 | 0 | static inline bool match164(const Token* tok) { |
1624 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1625 | 0 | return false; |
1626 | 0 | tok = tok->next(); |
1627 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1628 | 0 | return false; |
1629 | 0 | tok = tok->next(); |
1630 | 0 | if (!tok || tok->str().size() != 1U || !strchr("|+", tok->str()[0])) |
1631 | 0 | return false; |
1632 | 0 | return true; |
1633 | 0 | } |
1634 | | // pattern: [|+-] 0 ) |
1635 | 0 | static inline bool match165(const Token* tok) { |
1636 | 0 | if (!tok || tok->str().size() != 1U || !strchr("|+-", tok->str()[0])) |
1637 | 0 | return false; |
1638 | 0 | tok = tok->next(); |
1639 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("0"))) |
1640 | 0 | return false; |
1641 | 0 | tok = tok->next(); |
1642 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1643 | 0 | return false; |
1644 | 0 | return true; |
1645 | 0 | } |
1646 | | // pattern: [|+-] |
1647 | 0 | static inline bool match166(const Token* tok) { |
1648 | 0 | if (!tok || tok->str().size() != 1U || !strchr("|+-", tok->str()[0])) |
1649 | 0 | return false; |
1650 | 0 | return true; |
1651 | 0 | } |
1652 | | // pattern: (|&&|%oror% |
1653 | 0 | static inline bool match167(const Token* tok) { |
1654 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eLogicalOp) && tok->str() == MatchCompiler::makeConstString("&&")) || (tok->tokType() == Token::eLogicalOp && tok->str() == MatchCompiler::makeConstString("||")))) |
1655 | 0 | return false; |
1656 | 0 | return true; |
1657 | 0 | } |
1658 | | // pattern: %name% ,|>|= |
1659 | 0 | static inline bool match168(const Token* tok) { |
1660 | 0 | if (!tok || !tok->isName()) |
1661 | 0 | return false; |
1662 | 0 | tok = tok->next(); |
1663 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")))) |
1664 | 0 | return false; |
1665 | 0 | return true; |
1666 | 0 | } |
1667 | | // pattern: %name% !!< |
1668 | 0 | static inline bool match169(const Token* tok) { |
1669 | 0 | if (!tok || !tok->isName()) |
1670 | 0 | return false; |
1671 | 0 | tok = tok->next(); |
1672 | 0 | if (tok && tok->str() == MatchCompiler::makeConstString("<")) |
1673 | 0 | return false; |
1674 | 0 | return true; |
1675 | 0 | } |
1676 | | // pattern: %num%| ] |
1677 | 0 | static inline bool match170(const Token* tok) { |
1678 | 0 | if (tok && (tok->isNumber())) |
1679 | 0 | tok = tok->next(); |
1680 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]"))) |
1681 | 0 | return false; |
1682 | 0 | return true; |
1683 | 0 | } |
1684 | | // pattern: <|,|:: %name% < |
1685 | 0 | static inline bool match171(const Token* tok) { |
1686 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
1687 | 0 | return false; |
1688 | 0 | tok = tok->next(); |
1689 | 0 | if (!tok || !tok->isName()) |
1690 | 0 | return false; |
1691 | 0 | tok = tok->next(); |
1692 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<"))) |
1693 | 0 | return false; |
1694 | 0 | return true; |
1695 | 0 | } |
1696 | | // pattern: > ,|>|:: |
1697 | 0 | static inline bool match172(const Token* tok) { |
1698 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
1699 | 0 | return false; |
1700 | 0 | tok = tok->next(); |
1701 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(",")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || (tok->str() == MatchCompiler::makeConstString("::")))) |
1702 | 0 | return false; |
1703 | 0 | return true; |
1704 | 0 | } |
1705 | | // pattern: [<,] |
1706 | 0 | static inline bool match173(const Token* tok) { |
1707 | 0 | if (!tok || tok->str().size() != 1U || !strchr("<,", tok->str()[0])) |
1708 | 0 | return false; |
1709 | 0 | return true; |
1710 | 0 | } |
1711 | | // pattern: )|] |
1712 | 0 | static inline bool match174(const Token* tok) { |
1713 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eExtendedOp || tok->tokType() == Token::eLambda) && tok->str() == MatchCompiler::makeConstString("]")))) |
1714 | 0 | return false; |
1715 | 0 | return true; |
1716 | 0 | } |
1717 | | // pattern: class|struct|enum |
1718 | 0 | static inline bool match175(const Token* tok) { |
1719 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("class")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("struct")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("enum")))) |
1720 | 0 | return false; |
1721 | 0 | return true; |
1722 | 0 | } |
1723 | | // pattern: >|%name% :: %name% |
1724 | 0 | static inline bool match176(const Token* tok) { |
1725 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || tok->isName())) |
1726 | 0 | return false; |
1727 | 0 | tok = tok->next(); |
1728 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("::"))) |
1729 | 0 | return false; |
1730 | 0 | tok = tok->next(); |
1731 | 0 | if (!tok || !tok->isName()) |
1732 | 0 | return false; |
1733 | 0 | return true; |
1734 | 0 | } |
1735 | | // pattern: ;|{|}|=|const |
1736 | 0 | static inline bool match177(const Token* tok) { |
1737 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString(";")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || ((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("=")) || ((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("const")))) |
1738 | 0 | return false; |
1739 | 0 | return true; |
1740 | 0 | } |
1741 | | // pattern: > (|{ |
1742 | 0 | static inline bool match178(const Token* tok) { |
1743 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
1744 | 0 | return false; |
1745 | 0 | tok = tok->next(); |
1746 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")))) |
1747 | 0 | return false; |
1748 | 0 | return true; |
1749 | 0 | } |
1750 | | // pattern: template|const_cast|dynamic_cast|reinterpret_cast|static_cast |
1751 | 0 | static inline bool match179(const Token* tok) { |
1752 | 0 | if (!tok || !((tok->str() == MatchCompiler::makeConstString("template")) || (tok->str() == MatchCompiler::makeConstString("const_cast")) || (tok->str() == MatchCompiler::makeConstString("dynamic_cast")) || (tok->str() == MatchCompiler::makeConstString("reinterpret_cast")) || (tok->str() == MatchCompiler::makeConstString("static_cast")))) |
1753 | 0 | return false; |
1754 | 0 | return true; |
1755 | 0 | } |
1756 | | // pattern: > |
1757 | 0 | static inline bool match180(const Token* tok) { |
1758 | 0 | if (!tok || !((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">"))) |
1759 | 0 | return false; |
1760 | 0 | return true; |
1761 | 0 | } |
1762 | | // pattern: {|(|< |
1763 | 0 | static inline bool match181(const Token* tok) { |
1764 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("{")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString("<")))) |
1765 | 0 | return false; |
1766 | 0 | return true; |
1767 | 0 | } |
1768 | | // pattern: }|)|> |
1769 | 0 | static inline bool match182(const Token* tok) { |
1770 | 0 | if (!tok || !(((tok->tokType() == Token::eBracket) && tok->str() == MatchCompiler::makeConstString("}")) || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")))) |
1771 | 0 | return false; |
1772 | 0 | return true; |
1773 | 0 | } |
1774 | | // pattern: sizeof ... |
1775 | 56.8k | static inline bool match183(const Token* tok) { |
1776 | 56.8k | if (!tok || !((tok->tokType() == Token::eKeyword) && tok->str() == MatchCompiler::makeConstString("sizeof"))) |
1777 | 56.8k | return false; |
1778 | 0 | tok = tok->next(); |
1779 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
1780 | 0 | return false; |
1781 | 0 | return true; |
1782 | 0 | } |
1783 | | // pattern: typename %name% |
1784 | 56.8k | static inline bool match184(const Token* tok) { |
1785 | 56.8k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("typename"))) |
1786 | 56.8k | return false; |
1787 | 0 | tok = tok->next(); |
1788 | 0 | if (!tok || !tok->isName()) |
1789 | 0 | return false; |
1790 | 0 | return true; |
1791 | 0 | } |
1792 | | // pattern: using %name% = |
1793 | 0 | static inline bool match185(const Token* tok) { |
1794 | 0 | if (!tok || !(tok->str() == MatchCompiler::makeConstString("using"))) |
1795 | 0 | return false; |
1796 | 0 | tok = tok->next(); |
1797 | 0 | if (!tok || !tok->isName()) |
1798 | 0 | return false; |
1799 | 0 | tok = tok->next(); |
1800 | 0 | if (!tok || !((tok->tokType() == Token::eAssignmentOp) && tok->str() == MatchCompiler::makeConstString("="))) |
1801 | 0 | return false; |
1802 | 0 | return true; |
1803 | 0 | } |
1804 | | // pattern: )|>|>> requires %name%|( |
1805 | 56.8k | static inline bool match186(const Token* tok) { |
1806 | 56.8k | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || ((tok->tokType() == Token::eBracket || tok->tokType() == Token::eComparisonOp) && tok->str() == MatchCompiler::makeConstString(">")) || ((tok->tokType() == Token::eArithmeticalOp) && tok->str() == MatchCompiler::makeConstString(">>")))) |
1807 | 54.4k | return false; |
1808 | 2.45k | tok = tok->next(); |
1809 | 2.45k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("requires"))) |
1810 | 2.45k | return false; |
1811 | 0 | tok = tok->next(); |
1812 | 0 | if (!tok || !(tok->isName() || ((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("(")))) |
1813 | 0 | return false; |
1814 | 0 | return true; |
1815 | 0 | } |
1816 | | // pattern: explicit ( |
1817 | 56.8k | static inline bool match187(const Token* tok) { |
1818 | 56.8k | if (!tok || !(tok->str() == MatchCompiler::makeConstString("explicit"))) |
1819 | 56.8k | return false; |
1820 | 0 | tok = tok->next(); |
1821 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1822 | 0 | return false; |
1823 | 0 | return true; |
1824 | 0 | } |
1825 | | // pattern: false ) |
1826 | 0 | static inline bool match188(const Token* tok) { |
1827 | 0 | if (!tok || !((tok->tokType() == Token::eBoolean) && tok->str() == MatchCompiler::makeConstString("false"))) |
1828 | 0 | return false; |
1829 | 0 | tok = tok->next(); |
1830 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1831 | 0 | return false; |
1832 | 0 | return true; |
1833 | 0 | } |
1834 | | // pattern: )|; |
1835 | 0 | static inline bool match189(const Token* tok) { |
1836 | 0 | if (!tok || !(((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")")) || (tok->str() == MatchCompiler::makeConstString(";")))) |
1837 | 0 | return false; |
1838 | 0 | return true; |
1839 | 0 | } |
1840 | | // pattern: ( ... %op% |
1841 | 0 | static inline bool match190(const Token* tok) { |
1842 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1843 | 0 | return false; |
1844 | 0 | tok = tok->next(); |
1845 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
1846 | 0 | return false; |
1847 | 0 | tok = tok->next(); |
1848 | 0 | if (!tok || !tok->isOp()) |
1849 | 0 | return false; |
1850 | 0 | return true; |
1851 | 0 | } |
1852 | | // pattern: ( %name% %op% ... |
1853 | 0 | static inline bool match191(const Token* tok) { |
1854 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString("("))) |
1855 | 0 | return false; |
1856 | 0 | tok = tok->next(); |
1857 | 0 | if (!tok || !tok->isName()) |
1858 | 0 | return false; |
1859 | 0 | tok = tok->next(); |
1860 | 0 | if (!tok || !tok->isOp()) |
1861 | 0 | return false; |
1862 | 0 | tok = tok->next(); |
1863 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
1864 | 0 | return false; |
1865 | 0 | return true; |
1866 | 0 | } |
1867 | | // pattern: %op% ... ) |
1868 | 0 | static inline bool match192(const Token* tok) { |
1869 | 0 | if (!tok || !tok->isOp()) |
1870 | 0 | return false; |
1871 | 0 | tok = tok->next(); |
1872 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
1873 | 0 | return false; |
1874 | 0 | tok = tok->next(); |
1875 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1876 | 0 | return false; |
1877 | 0 | return true; |
1878 | 0 | } |
1879 | | // pattern: ... %op% %name% ) |
1880 | 0 | static inline bool match193(const Token* tok) { |
1881 | 0 | if (!tok || !((tok->tokType() == Token::eEllipsis) && tok->str() == MatchCompiler::makeConstString("..."))) |
1882 | 0 | return false; |
1883 | 0 | tok = tok->next(); |
1884 | 0 | if (!tok || !tok->isOp()) |
1885 | 0 | return false; |
1886 | 0 | tok = tok->next(); |
1887 | 0 | if (!tok || !tok->isName()) |
1888 | 0 | return false; |
1889 | 0 | tok = tok->next(); |
1890 | 0 | if (!tok || !((tok->tokType() == Token::eExtendedOp) && tok->str() == MatchCompiler::makeConstString(")"))) |
1891 | 0 | return false; |
1892 | 0 | return true; |
1893 | 0 | } |
1894 | | /* |
1895 | | * Cppcheck - A tool for static C/C++ code analysis |
1896 | | * Copyright (C) 2007-2024 Cppcheck team. |
1897 | | * |
1898 | | * This program is free software: you can redistribute it and/or modify |
1899 | | * it under the terms of the GNU General Public License as published by |
1900 | | * the Free Software Foundation, either version 3 of the License, or |
1901 | | * (at your option) any later version. |
1902 | | * |
1903 | | * This program is distributed in the hope that it will be useful, |
1904 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1905 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1906 | | * GNU General Public License for more details. |
1907 | | * |
1908 | | * You should have received a copy of the GNU General Public License |
1909 | | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1910 | | */ |
1911 | | |
1912 | | #include "templatesimplifier.h" |
1913 | | |
1914 | | #include "errorlogger.h" |
1915 | | #include "errortypes.h" |
1916 | | #include "mathlib.h" |
1917 | | #include "settings.h" |
1918 | | #include "standards.h" |
1919 | | #include "token.h" |
1920 | | #include "tokenize.h" |
1921 | | #include "tokenlist.h" |
1922 | | #include "utils.h" |
1923 | | |
1924 | | #include <algorithm> |
1925 | | #include <cassert> |
1926 | | #include <iostream> |
1927 | | #include <map> |
1928 | | #include <memory> |
1929 | | #include <stack> |
1930 | | #include <type_traits> |
1931 | | #include <utility> |
1932 | | |
1933 | | static Token *skipRequires(Token *tok) |
1934 | 0 | { |
1935 | 0 | if (!match1(tok)) |
1936 | 0 | return tok; |
1937 | | |
1938 | 0 | while (match2(tok)) { |
1939 | 0 | Token *after = tok->next(); |
1940 | 0 | if (after->str() == MatchCompiler::makeConstString("(")) { |
1941 | 0 | tok = after->link()->next(); |
1942 | 0 | continue; |
1943 | 0 | } |
1944 | 0 | if (match3(after) && match4(after->linkAt(1))) { |
1945 | 0 | tok = after->linkAt(1)->linkAt(1)->next(); |
1946 | 0 | continue; |
1947 | 0 | } |
1948 | 0 | while (match5(after)) |
1949 | 0 | after = after->tokAt(2); |
1950 | 0 | if (match6(after)) { |
1951 | 0 | after = after->next()->findClosingBracket(); |
1952 | 0 | tok = after ? after->next() : nullptr; |
1953 | 0 | } else |
1954 | 0 | break; |
1955 | 0 | } |
1956 | 0 | return tok; |
1957 | 0 | } |
1958 | | |
1959 | | namespace { |
1960 | | class FindToken { |
1961 | | public: |
1962 | 0 | explicit FindToken(const Token *token) : mToken(token) {} |
1963 | 0 | bool operator()(const TemplateSimplifier::TokenAndName &tokenAndName) const { |
1964 | 0 | return tokenAndName.token() == mToken; |
1965 | 0 | } |
1966 | | private: |
1967 | | const Token * const mToken; |
1968 | | }; |
1969 | | |
1970 | | class FindName { |
1971 | | public: |
1972 | 0 | explicit FindName(std::string name) : mName(std::move(name)) {} |
1973 | 0 | bool operator()(const TemplateSimplifier::TokenAndName &tokenAndName) const { |
1974 | 0 | return tokenAndName.name() == mName; |
1975 | 0 | } |
1976 | | private: |
1977 | | const std::string mName; |
1978 | | }; |
1979 | | |
1980 | | class FindFullName { |
1981 | | public: |
1982 | 0 | explicit FindFullName(std::string fullName) : mFullName(std::move(fullName)) {} |
1983 | 0 | bool operator()(const TemplateSimplifier::TokenAndName &tokenAndName) const { |
1984 | 0 | return tokenAndName.fullName() == mFullName; |
1985 | 0 | } |
1986 | | private: |
1987 | | const std::string mFullName; |
1988 | | }; |
1989 | | } |
1990 | | |
1991 | | TemplateSimplifier::TokenAndName::TokenAndName(Token *token, std::string scope) : |
1992 | 0 | mToken(token), mScope(std::move(scope)), mName(mToken ? mToken->str() : ""), |
1993 | 0 | mFullName(mScope.empty() ? mName : (mScope + " :: " + mName)), |
1994 | 0 | mNameToken(nullptr), mParamEnd(nullptr), mFlags(0) |
1995 | 0 | { |
1996 | 0 | if (mToken) { |
1997 | 0 | if (mToken->strAt(1) == MatchCompiler::makeConstString("<")) { |
1998 | 0 | const Token *end = mToken->next()->findClosingBracket(); |
1999 | 0 | if (end && end->strAt(1) == MatchCompiler::makeConstString("(")) { |
2000 | 0 | isFunction(true); |
2001 | 0 | } |
2002 | 0 | } |
2003 | 0 | mToken->templateSimplifierPointer(this); |
2004 | 0 | } |
2005 | 0 | } |
2006 | | |
2007 | | TemplateSimplifier::TokenAndName::TokenAndName(Token *token, std::string scope, const Token *nameToken, const Token *paramEnd) : |
2008 | 0 | mToken(token), mScope(std::move(scope)), mName(nameToken->str()), |
2009 | 0 | mFullName(mScope.empty() ? mName : (mScope + " :: " + mName)), |
2010 | 0 | mNameToken(nameToken), mParamEnd(paramEnd), mFlags(0) |
2011 | 0 | { |
2012 | | // only set flags for declaration |
2013 | 0 | if (mToken && mNameToken && mParamEnd) { |
2014 | 0 | isSpecialization(match7(mToken)); |
2015 | |
|
2016 | 0 | if (!isSpecialization()) { |
2017 | 0 | if (match8(mToken->next()->findClosingBracket())) { |
2018 | 0 | const Token * temp = mNameToken->tokAt(-2); |
2019 | 0 | while (match9(temp)) { |
2020 | 0 | if (temp->str() == MatchCompiler::makeConstString(">")) |
2021 | 0 | temp = temp->findOpeningBracket()->previous(); |
2022 | 0 | else |
2023 | 0 | temp = temp->tokAt(-2); |
2024 | 0 | } |
2025 | 0 | isPartialSpecialization(temp->strAt(1) == MatchCompiler::makeConstString("<")); |
2026 | 0 | } else |
2027 | 0 | isPartialSpecialization(mNameToken->strAt(1) == MatchCompiler::makeConstString("<")); |
2028 | 0 | } |
2029 | |
|
2030 | 0 | isAlias(mParamEnd->strAt(1) == MatchCompiler::makeConstString("using")); |
2031 | |
|
2032 | 0 | if (isAlias() && isPartialSpecialization()) { |
2033 | 0 | throw InternalError(mToken, "partial specialization of alias templates is not permitted", InternalError::SYNTAX); |
2034 | 0 | } |
2035 | 0 | if (isAlias() && isSpecialization()) { |
2036 | 0 | throw InternalError(mToken, "explicit specialization of alias templates is not permitted", InternalError::SYNTAX); |
2037 | 0 | } |
2038 | | |
2039 | 0 | isFriend(mParamEnd->strAt(1) == MatchCompiler::makeConstString("friend")); |
2040 | 0 | const Token *next = mParamEnd->next(); |
2041 | 0 | if (isFriend()) |
2042 | 0 | next = next->next(); |
2043 | |
|
2044 | 0 | isClass(match10(next)); |
2045 | 0 | if (mToken->strAt(1) == MatchCompiler::makeConstString("<") && !isSpecialization()) { |
2046 | 0 | const Token *end = mToken->next()->findClosingBracket(); |
2047 | 0 | isVariadic(end && findmatch11(mToken->tokAt(2), end) ); |
2048 | 0 | } |
2049 | 0 | const Token *tok1 = mNameToken->next(); |
2050 | 0 | if (tok1->str() == MatchCompiler::makeConstString("<")) { |
2051 | 0 | const Token *closing = tok1->findClosingBracket(); |
2052 | 0 | if (closing) |
2053 | 0 | tok1 = closing->next(); |
2054 | 0 | else |
2055 | 0 | throw InternalError(mToken, "unsupported syntax", InternalError::SYNTAX); |
2056 | 0 | } |
2057 | 0 | isFunction(tok1->str() == MatchCompiler::makeConstString("(")); |
2058 | 0 | isVariable(!isClass() && !isAlias() && !isFriend() && match12(tok1)); |
2059 | 0 | if (!isFriend()) { |
2060 | 0 | if (isVariable()) |
2061 | 0 | isForwardDeclaration(tok1->str() == MatchCompiler::makeConstString(";")); |
2062 | 0 | else if (!isAlias()) { |
2063 | 0 | if (isFunction()) |
2064 | 0 | tok1 = tok1->link()->next(); |
2065 | 0 | while (tok1 && !match13(tok1)) { |
2066 | 0 | if (tok1->str() == MatchCompiler::makeConstString("<")) |
2067 | 0 | tok1 = tok1->findClosingBracket(); |
2068 | 0 | else if (match14(tok1) && tok1->link()) |
2069 | 0 | tok1 = tok1->link(); |
2070 | 0 | if (tok1) |
2071 | 0 | tok1 = tok1->next(); |
2072 | 0 | } |
2073 | 0 | if (tok1) |
2074 | 0 | isForwardDeclaration(tok1->str() == MatchCompiler::makeConstString(";")); |
2075 | 0 | } |
2076 | 0 | } |
2077 | | // check for member class or function and adjust scope |
2078 | 0 | if ((isFunction() || isClass()) && |
2079 | 0 | (mNameToken->strAt(-1) == MatchCompiler::makeConstString("::") || match15(mNameToken->tokAt(-2)))) { |
2080 | 0 | const Token * start = mNameToken; |
2081 | 0 | if (start->strAt(-1) == MatchCompiler::makeConstString("~")) |
2082 | 0 | start = start->previous(); |
2083 | 0 | const Token *end = start; |
2084 | |
|
2085 | 0 | while (start && (match16(start->tokAt(-2)) || |
2086 | 0 | (match17(start->tokAt(-2)) && |
2087 | 0 | start->tokAt(-2)->findOpeningBracket() && |
2088 | 0 | match6(start->tokAt(-2)->findOpeningBracket()->previous())))) { |
2089 | 0 | if (start->strAt(-2) == MatchCompiler::makeConstString(">")) |
2090 | 0 | start = start->tokAt(-2)->findOpeningBracket()->previous(); |
2091 | 0 | else |
2092 | 0 | start = start->tokAt(-2); |
2093 | 0 | } |
2094 | |
|
2095 | 0 | if (start && start != end) { |
2096 | 0 | if (!mScope.empty()) |
2097 | 0 | mScope += " ::"; |
2098 | 0 | while (start && start->next() != end) { |
2099 | 0 | if (start->str() == MatchCompiler::makeConstString("<")) |
2100 | 0 | start = start->findClosingBracket(); |
2101 | 0 | else { |
2102 | 0 | if (!mScope.empty()) |
2103 | 0 | mScope += " "; |
2104 | 0 | mScope += start->str(); |
2105 | 0 | } |
2106 | 0 | start = start->next(); |
2107 | 0 | } |
2108 | 0 | if (start) |
2109 | 0 | mFullName = mScope.empty() ? mName : (mScope + " :: " + mName); |
2110 | 0 | } |
2111 | 0 | } |
2112 | 0 | } |
2113 | | |
2114 | | // make sure at most only one family flag is set |
2115 | 0 | assert(isClass() ? !(isFunction() || isVariable()) : true); |
2116 | 0 | assert(isFunction() ? !(isClass() || isVariable()) : true); |
2117 | 0 | assert(isVariable() ? !(isClass() || isFunction()) : true); |
2118 | | |
2119 | 0 | if (mToken) |
2120 | 0 | mToken->templateSimplifierPointer(this); |
2121 | 0 | } |
2122 | | |
2123 | | TemplateSimplifier::TokenAndName::TokenAndName(const TokenAndName& other) : |
2124 | 0 | mToken(other.mToken), mScope(other.mScope), mName(other.mName), mFullName(other.mFullName), |
2125 | 0 | mNameToken(other.mNameToken), mParamEnd(other.mParamEnd), mFlags(other.mFlags) |
2126 | 0 | { |
2127 | 0 | if (mToken) |
2128 | 0 | mToken->templateSimplifierPointer(this); |
2129 | 0 | } |
2130 | | |
2131 | | TemplateSimplifier::TokenAndName::~TokenAndName() |
2132 | 0 | { |
2133 | 0 | if (mToken && mToken->templateSimplifierPointers()) |
2134 | 0 | mToken->templateSimplifierPointers()->erase(this); |
2135 | 0 | } |
2136 | | |
2137 | 0 | std::string TemplateSimplifier::TokenAndName::dump(const std::vector<std::string>& fileNames) const { |
2138 | 0 | std::string ret = " <TokenAndName name=\"" + ErrorLogger::toxml(mName) + "\" file=\"" + ErrorLogger::toxml(fileNames.at(mToken->fileIndex())) + "\" line=\"" + std::to_string(mToken->linenr()) + "\">\n"; |
2139 | 0 | for (const Token* tok = mToken; tok && !match18(tok); tok = tok->next()) |
2140 | 0 | ret += " <template-token str=\"" + ErrorLogger::toxml(tok->str()) + "\"/>\n"; |
2141 | 0 | return ret + " </TokenAndName>\n"; |
2142 | 0 | } |
2143 | | |
2144 | | const Token * TemplateSimplifier::TokenAndName::aliasStartToken() const |
2145 | 0 | { |
2146 | 0 | if (mParamEnd) |
2147 | 0 | return mParamEnd->tokAt(4); |
2148 | 0 | return nullptr; |
2149 | 0 | } |
2150 | | |
2151 | | const Token * TemplateSimplifier::TokenAndName::aliasEndToken() const |
2152 | 0 | { |
2153 | 0 | if (aliasStartToken()) |
2154 | 0 | return findmatch19(aliasStartToken()) ; |
2155 | 0 | return nullptr; |
2156 | 0 | } |
2157 | | |
2158 | | bool TemplateSimplifier::TokenAndName::isAliasToken(const Token *tok) const |
2159 | 0 | { |
2160 | 0 | const Token *end = aliasEndToken(); |
2161 | |
|
2162 | 0 | for (const Token *tok1 = aliasStartToken(); tok1 != end; tok1 = tok1->next()) { |
2163 | 0 | if (tok1 == tok) |
2164 | 0 | return true; |
2165 | 0 | } |
2166 | 0 | return false; |
2167 | 0 | } |
2168 | | |
2169 | | TemplateSimplifier::TemplateSimplifier(Tokenizer &tokenizer) |
2170 | 868 | : mTokenizer(tokenizer), mTokenList(mTokenizer.list), mSettings(mTokenizer.getSettings()), |
2171 | 868 | mErrorLogger(mTokenizer.mErrorLogger) |
2172 | 868 | {} |
2173 | | |
2174 | | void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() |
2175 | 790 | { |
2176 | | // check for more complicated syntax errors when using templates.. |
2177 | 21.1k | for (const Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
2178 | | // skip executing scopes (ticket #3183).. |
2179 | 20.3k | if (match20(tok)) { |
2180 | 0 | tok = tok->link(); |
2181 | 0 | if (!tok) |
2182 | 0 | syntaxError(nullptr); |
2183 | 0 | } |
2184 | | // skip executing scopes.. |
2185 | 20.3k | const Token *start = Tokenizer::startOfExecutableScope(tok); |
2186 | 20.3k | if (start) { |
2187 | 1.14k | tok = start->link(); |
2188 | 1.14k | } |
2189 | | |
2190 | | // skip executing scopes (ticket #1985).. |
2191 | 19.2k | else if (match21(tok)) { |
2192 | 0 | tok = tok->linkAt(1); |
2193 | 0 | while (match22(tok)) { |
2194 | 0 | tok = tok->linkAt(2); |
2195 | 0 | if (match4(tok)) |
2196 | 0 | tok = tok->linkAt(1); |
2197 | 0 | } |
2198 | 0 | } |
2199 | | |
2200 | 20.3k | if (!tok) |
2201 | 0 | syntaxError(nullptr); |
2202 | | // not start of statement? |
2203 | 20.3k | if (tok->previous() && !match18(tok)) |
2204 | 14.5k | continue; |
2205 | | |
2206 | | // skip starting tokens.. ;;; typedef typename foo::bar::.. |
2207 | 9.83k | while (match13(tok)) |
2208 | 3.95k | tok = tok->next(); |
2209 | 5.88k | while (match23(tok)) |
2210 | 0 | tok = tok->next(); |
2211 | 5.88k | while (match24(tok)) |
2212 | 0 | tok = tok->tokAt(2); |
2213 | 5.88k | if (!tok) |
2214 | 0 | break; |
2215 | | |
2216 | | // template variable or type.. |
2217 | 5.88k | if (match25(tok) && !match26(tok)) { |
2218 | | // these are used types.. |
2219 | 0 | std::set<std::string> usedtypes; |
2220 | | |
2221 | | // parse this statement and see if the '<' and '>' are matching |
2222 | 0 | unsigned int level = 0; |
2223 | 0 | for (const Token *tok2 = tok; tok2 && !match27(tok2); tok2 = tok2->next()) { |
2224 | 0 | if (match28(tok2) && |
2225 | 0 | (!match29(tok2->previous()) || match30(tok2->link()))) |
2226 | 0 | break; |
2227 | 0 | if (tok2->str() == MatchCompiler::makeConstString("(")) |
2228 | 0 | tok2 = tok2->link(); |
2229 | 0 | else if (tok2->str() == MatchCompiler::makeConstString("<")) { |
2230 | 0 | bool inclevel = false; |
2231 | 0 | if (match31(tok2->previous())) |
2232 | 0 | ; |
2233 | 0 | else if (level == 0 && match32(tok2->previous())) { |
2234 | | // @todo add better expression detection |
2235 | 0 | if (!(match33(tok2->next()) || |
2236 | 0 | match34(tok2->next()))) { |
2237 | 0 | inclevel = true; |
2238 | 0 | } |
2239 | 0 | } else if (tok2->next() && tok2->next()->isStandardType() && !match35(tok2->tokAt(2))) |
2240 | 0 | inclevel = true; |
2241 | 0 | else if (match36(tok2)) |
2242 | 0 | inclevel = true; |
2243 | 0 | else if (match37(tok2->tokAt(-2)) && usedtypes.find(tok2->strAt(-1)) != usedtypes.end()) |
2244 | 0 | inclevel = true; |
2245 | 0 | else if (match38(tok2) && usedtypes.find(tok2->strAt(1)) != usedtypes.end()) |
2246 | 0 | inclevel = true; |
2247 | 0 | else if (match38(tok2)) { |
2248 | | // is the next token a type and not a variable/constant? |
2249 | | // assume it's a type if there comes another "<" |
2250 | 0 | const Token *tok3 = tok2->next(); |
2251 | 0 | while (match24(tok3)) |
2252 | 0 | tok3 = tok3->tokAt(2); |
2253 | 0 | if (match25(tok3)) |
2254 | 0 | inclevel = true; |
2255 | 0 | } else if (tok2->strAt(-1) == MatchCompiler::makeConstString(">")) |
2256 | 0 | syntaxError(tok); |
2257 | |
|
2258 | 0 | if (inclevel) { |
2259 | 0 | ++level; |
2260 | 0 | if (match37(tok2->tokAt(-2))) |
2261 | 0 | usedtypes.insert(tok2->strAt(-1)); |
2262 | 0 | } |
2263 | 0 | } else if (tok2->str() == MatchCompiler::makeConstString(">")) { |
2264 | 0 | if (level > 0) |
2265 | 0 | --level; |
2266 | 0 | } else if (tok2->str() == MatchCompiler::makeConstString(">>")) { |
2267 | 0 | if (level > 0) |
2268 | 0 | --level; |
2269 | 0 | if (level > 0) |
2270 | 0 | --level; |
2271 | 0 | } |
2272 | 0 | } |
2273 | 0 | if (level > 0) |
2274 | 0 | syntaxError(tok); |
2275 | 0 | } |
2276 | 5.88k | } |
2277 | 790 | } |
2278 | | |
2279 | | unsigned int TemplateSimplifier::templateParameters(const Token *tok) |
2280 | 8.61k | { |
2281 | 8.61k | unsigned int numberOfParameters = 1; |
2282 | | |
2283 | 8.61k | if (!tok) |
2284 | 0 | return 0; |
2285 | 8.61k | if (tok->str() != MatchCompiler::makeConstString("<")) |
2286 | 8.25k | return 0; |
2287 | 366 | if (match39(tok->previous())) |
2288 | 0 | return 0; |
2289 | 366 | tok = tok->next(); |
2290 | 366 | if (!tok || tok->str() == MatchCompiler::makeConstString(">")) |
2291 | 0 | return 0; |
2292 | | |
2293 | 366 | unsigned int level = 0; |
2294 | | |
2295 | 1.06k | while (tok) { |
2296 | | // skip template template |
2297 | 1.06k | if (level == 0 && match40(tok)) { |
2298 | 0 | const Token *closing = tok->next()->findClosingBracket(); |
2299 | 0 | if (closing) { |
2300 | 0 | if (closing->str() == MatchCompiler::makeConstString(">>")) |
2301 | 0 | return numberOfParameters; |
2302 | 0 | tok = closing->next(); |
2303 | 0 | if (!tok) |
2304 | 0 | syntaxError(tok); |
2305 | 0 | if (match41(tok)) |
2306 | 0 | return numberOfParameters; |
2307 | 0 | if (tok->str() == MatchCompiler::makeConstString(",")) { |
2308 | 0 | ++numberOfParameters; |
2309 | 0 | tok = tok->next(); |
2310 | 0 | continue; |
2311 | 0 | } |
2312 | 0 | } else |
2313 | 0 | return 0; |
2314 | 0 | } |
2315 | | |
2316 | | // skip const/volatile |
2317 | 1.06k | if (match42(tok)) |
2318 | 0 | tok = tok->next(); |
2319 | | |
2320 | | // skip struct/union |
2321 | 1.06k | if (match43(tok)) |
2322 | 0 | tok = tok->next(); |
2323 | | |
2324 | | // Skip '&' |
2325 | 1.06k | if (match44(tok)) |
2326 | 2 | tok = tok->next(); |
2327 | | |
2328 | | // Skip variadic types (Ticket #5774, #6059, #6172) |
2329 | 1.06k | if (match45(tok)) { |
2330 | 0 | if ((tok->previous()->isName() && !match46(tok->tokAt(-2))) || |
2331 | 0 | (!tok->previous()->isName() && !match47(tok->previous()))) |
2332 | 0 | return 0; // syntax error |
2333 | 0 | tok = tok->next(); |
2334 | 0 | if (!tok) |
2335 | 0 | return 0; |
2336 | 0 | if (tok->str() == MatchCompiler::makeConstString(">")) { |
2337 | 0 | if (level == 0) |
2338 | 0 | return numberOfParameters; |
2339 | 0 | --level; |
2340 | 0 | } else if (tok->str() == MatchCompiler::makeConstString(">>") || tok->str() == MatchCompiler::makeConstString(">>=")) { |
2341 | 0 | if (level == 1) |
2342 | 0 | return numberOfParameters; |
2343 | 0 | level -= 2; |
2344 | 0 | } else if (tok->str() == MatchCompiler::makeConstString(",")) { |
2345 | 0 | if (level == 0) |
2346 | 0 | ++numberOfParameters; |
2347 | 0 | tok = tok->next(); |
2348 | 0 | continue; |
2349 | 0 | } |
2350 | 0 | } |
2351 | | |
2352 | | // Skip '=', '?', ':' |
2353 | 1.06k | if (match48(tok)) |
2354 | 12 | tok = tok->next(); |
2355 | 1.06k | if (!tok) |
2356 | 0 | return 0; |
2357 | | |
2358 | | // Skip links |
2359 | 1.06k | if (match35(tok)) { |
2360 | 27 | tok = tok->link(); |
2361 | 27 | if (tok) |
2362 | 27 | tok = tok->next(); |
2363 | 27 | if (!tok) |
2364 | 0 | return 0; |
2365 | 27 | if (tok->str() == MatchCompiler::makeConstString(">") && level == 0) |
2366 | 0 | return numberOfParameters; |
2367 | 27 | if ((tok->str() == MatchCompiler::makeConstString(">>") || tok->str() == MatchCompiler::makeConstString(">>=")) && level == 1) |
2368 | 0 | return numberOfParameters; |
2369 | 27 | if (tok->str() == MatchCompiler::makeConstString(",")) { |
2370 | 0 | if (level == 0) |
2371 | 0 | ++numberOfParameters; |
2372 | 0 | tok = tok->next(); |
2373 | 0 | } |
2374 | 27 | continue; |
2375 | 27 | } |
2376 | | |
2377 | | // skip std:: |
2378 | 1.04k | if (tok->str() == MatchCompiler::makeConstString("::")) |
2379 | 0 | tok = tok->next(); |
2380 | 1.04k | while (match16(tok)) { |
2381 | 0 | tok = tok->tokAt(2); |
2382 | 0 | if (tok && tok->str() == MatchCompiler::makeConstString("*")) // Ticket #5759: Class member pointer as a template argument; skip '*' |
2383 | 0 | tok = tok->next(); |
2384 | 0 | } |
2385 | 1.04k | if (!tok) |
2386 | 0 | return 0; |
2387 | | |
2388 | | // num/type .. |
2389 | 1.04k | if (!tok->isNumber() && tok->tokType() != Token::eChar && tok->tokType() != Token::eString && !tok->isName() && !tok->isOp()) |
2390 | 342 | return 0; |
2391 | 698 | tok = tok->next(); |
2392 | 698 | if (!tok) |
2393 | 0 | return 0; |
2394 | | |
2395 | | // * / const |
2396 | 724 | while (match49(tok)) |
2397 | 26 | tok = tok->next(); |
2398 | | |
2399 | 698 | if (!tok) |
2400 | 0 | return 0; |
2401 | | |
2402 | | // Function pointer or prototype.. |
2403 | 724 | while (match14(tok)) { |
2404 | 26 | if (!tok->link()) |
2405 | 0 | syntaxError(tok); |
2406 | | |
2407 | 26 | tok = tok->link()->next(); |
2408 | 26 | while (match42(tok)) // Ticket #5786: Skip function cv-qualifiers |
2409 | 0 | tok = tok->next(); |
2410 | 26 | } |
2411 | 698 | if (!tok) |
2412 | 0 | return 0; |
2413 | | |
2414 | | // inner template |
2415 | 698 | if (tok->str() == MatchCompiler::makeConstString("<") && tok->previous()->isName()) { |
2416 | 26 | ++level; |
2417 | 26 | tok = tok->next(); |
2418 | 26 | } |
2419 | | |
2420 | 698 | if (!tok) |
2421 | 0 | return 0; |
2422 | | |
2423 | | // ,/> |
2424 | 701 | while (match41(tok)) { |
2425 | 27 | if (level == 0) |
2426 | 24 | return tok->str() == MatchCompiler::makeConstString(">") && !match50(tok->next()) ? numberOfParameters : 0; |
2427 | 3 | --level; |
2428 | 3 | if (tok->str() == MatchCompiler::makeConstString(">>") || tok->str() == MatchCompiler::makeConstString(">>=")) { |
2429 | 0 | if (level == 0) |
2430 | 0 | return !match50(tok->next()) ? numberOfParameters : 0; |
2431 | 0 | --level; |
2432 | 0 | } |
2433 | 3 | tok = tok->next(); |
2434 | | |
2435 | 3 | if (match14(tok)) |
2436 | 0 | tok = tok->link()->next(); |
2437 | | |
2438 | 3 | if (!tok) |
2439 | 0 | return 0; |
2440 | 3 | } |
2441 | | |
2442 | 674 | if (tok->str() != MatchCompiler::makeConstString(",")) |
2443 | 674 | continue; |
2444 | 0 | if (level == 0) |
2445 | 0 | ++numberOfParameters; |
2446 | 0 | tok = tok->next(); |
2447 | 0 | } |
2448 | 0 | return 0; |
2449 | 366 | } |
2450 | | |
2451 | | template<class T, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )> |
2452 | | static T *findTemplateDeclarationEndImpl(T *tok) |
2453 | 0 | { |
2454 | 0 | if (match40(tok)) { |
2455 | 0 | tok = tok->next()->findClosingBracket(); |
2456 | 0 | if (tok) |
2457 | 0 | tok = tok->next(); |
2458 | 0 | } |
2459 | |
|
2460 | 0 | if (!tok) |
2461 | 0 | return nullptr; |
2462 | | |
2463 | 0 | T * tok2 = tok; |
2464 | 0 | bool in_init = false; |
2465 | 0 | while (tok2 && !match13(tok2)) { |
2466 | 0 | if (tok2->str() == MatchCompiler::makeConstString("<")) |
2467 | 0 | tok2 = tok2->findClosingBracket(); |
2468 | 0 | else if (match14(tok2) && tok2->link()) |
2469 | 0 | tok2 = tok2->link(); |
2470 | 0 | else if (tok2->str() == MatchCompiler::makeConstString(":")) |
2471 | 0 | in_init = true; |
2472 | 0 | else if (in_init && match51(tok2)) { |
2473 | 0 | tok2 = tok2->linkAt(1); |
2474 | 0 | if (tok2->strAt(1) == MatchCompiler::makeConstString("{")) |
2475 | 0 | in_init = false; |
2476 | 0 | } |
2477 | 0 | if (tok2) |
2478 | 0 | tok2 = tok2->next(); |
2479 | 0 | } |
2480 | 0 | if (tok2 && tok2->str() == MatchCompiler::makeConstString("{")) { |
2481 | 0 | tok = tok2->link(); |
2482 | 0 | if (tok && tok->strAt(1) == MatchCompiler::makeConstString(";")) |
2483 | 0 | tok = tok->next(); |
2484 | 0 | } else if (tok2 && tok2->str() == MatchCompiler::makeConstString(";")) |
2485 | 0 | tok = tok2; |
2486 | 0 | else |
2487 | 0 | tok = nullptr; |
2488 | |
|
2489 | 0 | return tok; |
2490 | 0 | } Unexecuted instantiation: templatesimplifier.cpp:Token* findTemplateDeclarationEndImpl<Token, void>(Token*) Unexecuted instantiation: templatesimplifier.cpp:Token const* findTemplateDeclarationEndImpl<Token const, void>(Token const*) |
2491 | | |
2492 | | Token *TemplateSimplifier::findTemplateDeclarationEnd(Token *tok) |
2493 | 0 | { |
2494 | 0 | return findTemplateDeclarationEndImpl(tok); |
2495 | 0 | } |
2496 | | |
2497 | | const Token *TemplateSimplifier::findTemplateDeclarationEnd(const Token *tok) |
2498 | 0 | { |
2499 | 0 | return findTemplateDeclarationEndImpl(tok); |
2500 | 0 | } |
2501 | | |
2502 | | void TemplateSimplifier::eraseTokens(Token *begin, const Token *end) |
2503 | 0 | { |
2504 | 0 | if (!begin || begin == end) |
2505 | 0 | return; |
2506 | | |
2507 | 0 | while (begin->next() && begin->next() != end) { |
2508 | 0 | begin->deleteNext(); |
2509 | 0 | } |
2510 | 0 | } |
2511 | | |
2512 | | void TemplateSimplifier::deleteToken(Token *tok) |
2513 | 0 | { |
2514 | 0 | if (tok->next()) |
2515 | 0 | tok->next()->deletePrevious(); |
2516 | 0 | else |
2517 | 0 | tok->deleteThis(); |
2518 | 0 | } |
2519 | | |
2520 | 0 | static void invalidateForwardDecls(const Token* beg, const Token* end, std::map<Token*, Token*>* forwardDecls) { |
2521 | 0 | if (!forwardDecls) |
2522 | 0 | return; |
2523 | 0 | for (auto& fwd : *forwardDecls) { |
2524 | 0 | for (const Token* tok = beg; tok != end; tok = tok->next()) |
2525 | 0 | if (fwd.second == tok) { |
2526 | 0 | fwd.second = nullptr; |
2527 | 0 | break; |
2528 | 0 | } |
2529 | 0 | } |
2530 | 0 | } |
2531 | | |
2532 | | bool TemplateSimplifier::removeTemplate(Token *tok, std::map<Token*, Token*>* forwardDecls) |
2533 | 0 | { |
2534 | 0 | if (!match40(tok)) |
2535 | 0 | return false; |
2536 | | |
2537 | 0 | Token *end = findTemplateDeclarationEnd(tok); |
2538 | 0 | if (end && end->next()) { |
2539 | 0 | invalidateForwardDecls(tok, end->next(), forwardDecls); |
2540 | 0 | eraseTokens(tok, end->next()); |
2541 | 0 | deleteToken(tok); |
2542 | 0 | return true; |
2543 | 0 | } |
2544 | | |
2545 | 0 | return false; |
2546 | 0 | } |
2547 | | |
2548 | | bool TemplateSimplifier::getTemplateDeclarations() |
2549 | 790 | { |
2550 | 790 | bool codeWithTemplates = false; |
2551 | 57.6k | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
2552 | 56.8k | if (!match40(tok)) |
2553 | 56.8k | continue; |
2554 | | // ignore template template parameter |
2555 | 0 | if (tok->strAt(-1) == MatchCompiler::makeConstString("<") || tok->strAt(-1) == MatchCompiler::makeConstString(",")) |
2556 | 0 | continue; |
2557 | | // ignore nested template |
2558 | 0 | if (tok->strAt(-1) == MatchCompiler::makeConstString(">")) |
2559 | 0 | continue; |
2560 | | // skip to last nested template parameter |
2561 | 0 | const Token *tok1 = tok; |
2562 | 0 | while (tok1 && tok1->next()) { |
2563 | 0 | const Token *closing = tok1->next()->findClosingBracket(); |
2564 | 0 | if (!match8(closing)) |
2565 | 0 | break; |
2566 | 0 | tok1 = closing->next(); |
2567 | 0 | } |
2568 | 0 | if (!match52(tok)) |
2569 | 0 | syntaxError(tok); |
2570 | 0 | if (tok->strAt(2)==MatchCompiler::makeConstString("typename") && |
2571 | 0 | !match53(tok->tokAt(3))) |
2572 | 0 | syntaxError(tok->next()); |
2573 | 0 | codeWithTemplates = true; |
2574 | 0 | const Token * const parmEnd = tok1->next()->findClosingBracket(); |
2575 | 0 | for (const Token *tok2 = parmEnd; tok2; tok2 = tok2->next()) { |
2576 | 0 | if (tok2->str() == MatchCompiler::makeConstString("(") && tok2->link()) |
2577 | 0 | tok2 = tok2->link(); |
2578 | 0 | else if (tok2->str() == MatchCompiler::makeConstString(")")) |
2579 | 0 | break; |
2580 | | // skip decltype(...) |
2581 | 0 | else if (match54(tok2)) |
2582 | 0 | tok2 = tok2->linkAt(1); |
2583 | 0 | else if (match55(tok2)) { |
2584 | 0 | const int namepos = getTemplateNamePosition(parmEnd); |
2585 | 0 | if (namepos > 0) { |
2586 | 0 | TokenAndName decl(tok, tok->scopeInfo()->name, parmEnd->tokAt(namepos), parmEnd); |
2587 | 0 | if (decl.isForwardDeclaration()) { |
2588 | | // Declaration => add to mTemplateForwardDeclarations |
2589 | 0 | mTemplateForwardDeclarations.emplace_back(std::move(decl)); |
2590 | 0 | } else { |
2591 | | // Implementation => add to mTemplateDeclarations |
2592 | 0 | mTemplateDeclarations.emplace_back(std::move(decl)); |
2593 | 0 | } |
2594 | 0 | Token *end = findTemplateDeclarationEnd(tok); |
2595 | 0 | if (end) |
2596 | 0 | tok = end; |
2597 | 0 | break; |
2598 | 0 | } |
2599 | 0 | } |
2600 | 0 | } |
2601 | 0 | } |
2602 | 790 | return codeWithTemplates; |
2603 | 790 | } |
2604 | | |
2605 | | void TemplateSimplifier::addInstantiation(Token *token, const std::string &scope) |
2606 | 0 | { |
2607 | 0 | simplifyTemplateArgs(token->tokAt(2), token->next()->findClosingBracket()); |
2608 | |
|
2609 | 0 | TokenAndName instantiation(token, scope); |
2610 | | |
2611 | | // check if instantiation already exists before adding it |
2612 | 0 | const auto it = std::find(mTemplateInstantiations.cbegin(), |
2613 | 0 | mTemplateInstantiations.cend(), |
2614 | 0 | instantiation); |
2615 | |
|
2616 | 0 | if (it == mTemplateInstantiations.cend()) |
2617 | 0 | mTemplateInstantiations.emplace_back(std::move(instantiation)); |
2618 | 0 | } |
2619 | | |
2620 | | static const Token* getFunctionToken(const Token* nameToken) |
2621 | 0 | { |
2622 | 0 | if (match56(nameToken)) |
2623 | 0 | return nameToken->next(); |
2624 | | |
2625 | 0 | if (match6(nameToken)) { |
2626 | 0 | const Token* end = nameToken->next()->findClosingBracket(); |
2627 | 0 | if (match57(end)) |
2628 | 0 | return end->next(); |
2629 | 0 | } |
2630 | | |
2631 | 0 | return nullptr; |
2632 | 0 | } |
2633 | | |
2634 | | static void getFunctionArguments(const Token* nameToken, std::vector<const Token*>& args) |
2635 | 0 | { |
2636 | 0 | const Token* functionToken = getFunctionToken(nameToken); |
2637 | 0 | if (!functionToken) |
2638 | 0 | return; |
2639 | | |
2640 | 0 | const Token* argToken = functionToken->next(); |
2641 | |
|
2642 | 0 | if (argToken->str() == MatchCompiler::makeConstString(")")) |
2643 | 0 | return; |
2644 | | |
2645 | 0 | args.push_back(argToken); |
2646 | |
|
2647 | 0 | while ((argToken = argToken->nextArgumentBeforeCreateLinks2())) |
2648 | 0 | args.push_back(argToken); |
2649 | 0 | } |
2650 | | |
2651 | | static bool isConstMethod(const Token* nameToken) |
2652 | 0 | { |
2653 | 0 | const Token* functionToken = getFunctionToken(nameToken); |
2654 | 0 | if (!functionToken) |
2655 | 0 | return false; |
2656 | 0 | const Token* endToken = functionToken->link(); |
2657 | 0 | return match58(endToken); |
2658 | 0 | } |
2659 | | |
2660 | | static bool areAllParamsTypes(const std::vector<const Token *> ¶ms) |
2661 | 0 | { |
2662 | 0 | if (params.empty()) |
2663 | 0 | return false; |
2664 | | |
2665 | 0 | return std::all_of(params.cbegin(), params.cend(), [](const Token* param) { |
2666 | 0 | return match59(param->previous()); |
2667 | 0 | }); |
2668 | 0 | } |
2669 | | |
2670 | | static bool isTemplateInstantion(const Token* tok) |
2671 | 0 | { |
2672 | 0 | if (!tok->isName() || (tok->isKeyword() && !tok->isOperatorKeyword())) |
2673 | 0 | return false; |
2674 | 0 | if (match60(tok->tokAt(-1))) |
2675 | 0 | return true; |
2676 | 0 | if (match61(tok->tokAt(-2))) |
2677 | 0 | return true; |
2678 | 0 | if (match62(tok->tokAt(-1))) |
2679 | 0 | return true; |
2680 | 0 | return match63(tok->tokAt(-2)); |
2681 | 0 | } |
2682 | | |
2683 | | void TemplateSimplifier::getTemplateInstantiations() |
2684 | 0 | { |
2685 | 0 | std::multimap<std::string, const TokenAndName *> functionNameMap; |
2686 | |
|
2687 | 0 | for (const auto & decl : mTemplateDeclarations) { |
2688 | 0 | if (decl.isFunction()) |
2689 | 0 | functionNameMap.emplace(decl.name(), &decl); |
2690 | 0 | } |
2691 | |
|
2692 | 0 | for (const auto & decl : mTemplateForwardDeclarations) { |
2693 | 0 | if (decl.isFunction()) |
2694 | 0 | functionNameMap.emplace(decl.name(), &decl); |
2695 | 0 | } |
2696 | |
|
2697 | 0 | const Token *skip = nullptr; |
2698 | |
|
2699 | 0 | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
2700 | | |
2701 | | // template definition.. skip it |
2702 | 0 | if (match40(tok)) { |
2703 | 0 | tok = tok->next()->findClosingBracket(); |
2704 | 0 | if (!tok) |
2705 | 0 | break; |
2706 | | |
2707 | 0 | const bool isUsing = tok->strAt(1) == MatchCompiler::makeConstString("using"); |
2708 | 0 | if (isUsing && match6(tok->tokAt(2))) { |
2709 | | // Can't have specialized type alias so ignore it |
2710 | 0 | Token *tok2 = findmatch19(tok->tokAt(3)) ; |
2711 | 0 | if (tok2) |
2712 | 0 | tok = tok2; |
2713 | 0 | } else if (tok->strAt(-1) == MatchCompiler::makeConstString("<")) { |
2714 | | // Don't ignore user specialization but don't consider it an instantiation. |
2715 | | // Instantiations in return type, function parameters, and executable code |
2716 | | // are not ignored. |
2717 | 0 | const unsigned int pos = getTemplateNamePosition(tok); |
2718 | 0 | if (pos > 0) |
2719 | 0 | skip = tok->tokAt(pos); |
2720 | 0 | } else { |
2721 | | // #7914 |
2722 | | // Ignore template instantiations within template definitions: they will only be |
2723 | | // handled if the definition is actually instantiated |
2724 | |
|
2725 | 0 | Token * tok2 = findTemplateDeclarationEnd(tok->next()); |
2726 | 0 | if (tok2) |
2727 | 0 | tok = tok2; |
2728 | 0 | } |
2729 | 0 | } else if (match64(tok)) { |
2730 | | // Can't have specialized type alias so ignore it |
2731 | 0 | Token *tok2 = findmatch19(tok->tokAt(3)) ; |
2732 | 0 | if (tok2) |
2733 | 0 | tok = tok2; |
2734 | 0 | } else if (match65(tok)) { |
2735 | | // Can't have specialized type alias so ignore it |
2736 | 0 | Token *tok2 = findmatch19(tok->tokAt(2)) ; |
2737 | 0 | if (tok2) |
2738 | 0 | tok = tok2; |
2739 | 0 | } else if (isTemplateInstantion(tok)) { |
2740 | 0 | if (!tok->scopeInfo()) |
2741 | 0 | syntaxError(tok); |
2742 | 0 | std::string scopeName = tok->scopeInfo()->name; |
2743 | 0 | std::string qualification; |
2744 | 0 | Token * qualificationTok = tok; |
2745 | 0 | while (match5(tok)) { |
2746 | 0 | qualification += (qualification.empty() ? "" : " :: ") + tok->str(); |
2747 | 0 | tok = tok->tokAt(2); |
2748 | 0 | } |
2749 | | |
2750 | | // skip specialization |
2751 | 0 | if (tok == skip) { |
2752 | 0 | skip = nullptr; |
2753 | 0 | continue; |
2754 | 0 | } |
2755 | | |
2756 | | // look for function instantiation with type deduction |
2757 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("(")) { |
2758 | 0 | std::vector<const Token *> instantiationArgs; |
2759 | 0 | getFunctionArguments(tok, instantiationArgs); |
2760 | |
|
2761 | 0 | std::string fullName; |
2762 | 0 | if (!qualification.empty()) |
2763 | 0 | fullName = qualification + " :: " + tok->str(); |
2764 | 0 | else if (!scopeName.empty()) |
2765 | 0 | fullName = scopeName + " :: " + tok->str(); |
2766 | 0 | else |
2767 | 0 | fullName = tok->str(); |
2768 | | |
2769 | | // get all declarations with this name |
2770 | 0 | auto range = functionNameMap.equal_range(tok->str()); |
2771 | 0 | for (auto pos = range.first; pos != range.second; ++pos) { |
2772 | | // look for declaration with same qualification or constructor with same qualification |
2773 | 0 | if (pos->second->fullName() == fullName || |
2774 | 0 | (pos->second->scope() == fullName && tok->str() == pos->second->name())) { |
2775 | 0 | std::vector<const Token *> templateParams; |
2776 | 0 | getTemplateParametersInDeclaration(pos->second->token()->tokAt(2), templateParams); |
2777 | | |
2778 | | // todo: handle more than one template parameter |
2779 | 0 | if (templateParams.size() != 1 || !areAllParamsTypes(templateParams)) |
2780 | 0 | continue; |
2781 | | |
2782 | 0 | std::vector<const Token *> declarationParams; |
2783 | 0 | getFunctionArguments(pos->second->nameToken(), declarationParams); |
2784 | | |
2785 | | // function argument counts must match |
2786 | 0 | if (instantiationArgs.empty() || instantiationArgs.size() != declarationParams.size()) |
2787 | 0 | continue; |
2788 | | |
2789 | 0 | size_t match = 0; |
2790 | 0 | size_t argMatch = 0; |
2791 | 0 | for (size_t i = 0; i < declarationParams.size(); ++i) { |
2792 | | // fixme: only type deduction from literals is supported |
2793 | 0 | const bool isArgLiteral = match66(instantiationArgs[i]); |
2794 | 0 | if (isArgLiteral && match67(declarationParams[i])) { |
2795 | 0 | match++; |
2796 | | |
2797 | | // check if parameter types match |
2798 | 0 | if (templateParams[0]->str() == declarationParams[i]->str()) |
2799 | 0 | argMatch = i; |
2800 | 0 | else { |
2801 | | // todo: check if non-template args match for function overloads |
2802 | 0 | } |
2803 | 0 | } |
2804 | 0 | } |
2805 | |
|
2806 | 0 | if (match == declarationParams.size()) { |
2807 | 0 | const Token *arg = instantiationArgs[argMatch]; |
2808 | 0 | tok->insertToken(">"); |
2809 | 0 | switch (arg->tokType()) { |
2810 | 0 | case Token::eBoolean: |
2811 | 0 | tok->insertToken("bool"); |
2812 | 0 | break; |
2813 | 0 | case Token::eChar: |
2814 | 0 | if (arg->isLong()) |
2815 | 0 | tok->insertToken("wchar_t"); |
2816 | 0 | else |
2817 | 0 | tok->insertToken("char"); |
2818 | 0 | break; |
2819 | 0 | case Token::eString: |
2820 | 0 | tok->insertToken("*"); |
2821 | 0 | if (arg->isLong()) |
2822 | 0 | tok->insertToken("wchar_t"); |
2823 | 0 | else |
2824 | 0 | tok->insertToken("char"); |
2825 | 0 | tok->insertToken("const"); |
2826 | 0 | break; |
2827 | 0 | case Token::eNumber: { |
2828 | 0 | MathLib::value num(arg->str()); |
2829 | 0 | if (num.isFloat()) { |
2830 | | // MathLib::getSuffix doesn't work for floating point numbers |
2831 | 0 | const char suffix = arg->str().back(); |
2832 | 0 | if (suffix == 'f' || suffix == 'F') |
2833 | 0 | tok->insertToken("float"); |
2834 | 0 | else if (suffix == 'l' || suffix == 'L') { |
2835 | 0 | tok->insertToken("double"); |
2836 | 0 | tok->next()->isLong(true); |
2837 | 0 | } else |
2838 | 0 | tok->insertToken("double"); |
2839 | 0 | } else if (num.isInt()) { |
2840 | 0 | std::string suffix = MathLib::getSuffix(tok->strAt(3)); |
2841 | 0 | if (suffix.find("LL") != std::string::npos) { |
2842 | 0 | tok->insertToken("long"); |
2843 | 0 | tok->next()->isLong(true); |
2844 | 0 | } else if (suffix.find('L') != std::string::npos) |
2845 | 0 | tok->insertToken("long"); |
2846 | 0 | else |
2847 | 0 | tok->insertToken("int"); |
2848 | 0 | if (suffix.find('U') != std::string::npos) |
2849 | 0 | tok->next()->isUnsigned(true); |
2850 | 0 | } |
2851 | 0 | break; |
2852 | 0 | } |
2853 | 0 | default: |
2854 | 0 | break; |
2855 | 0 | } |
2856 | 0 | tok->insertToken("<"); |
2857 | 0 | break; |
2858 | 0 | } |
2859 | 0 | } |
2860 | 0 | } |
2861 | 0 | } |
2862 | | |
2863 | 0 | if (!match6(tok) || |
2864 | 0 | match68(tok)) |
2865 | 0 | continue; |
2866 | | |
2867 | 0 | if (tok == skip) { |
2868 | 0 | skip = nullptr; |
2869 | 0 | continue; |
2870 | 0 | } |
2871 | | |
2872 | | // Add inner template instantiations first => go to the ">" |
2873 | | // and then parse backwards, adding all seen instantiations |
2874 | 0 | Token *tok2 = tok->next()->findClosingBracket(); |
2875 | | |
2876 | | // parse backwards and add template instantiations |
2877 | | // TODO |
2878 | 0 | for (; tok2 && tok2 != tok; tok2 = tok2->previous()) { |
2879 | 0 | if (match69(tok2) && |
2880 | 0 | (tok2->strAt(3) == MatchCompiler::makeConstString(">") || templateParameters(tok2->tokAt(2)))) { |
2881 | 0 | addInstantiation(tok2->next(), tok->scopeInfo()->name); |
2882 | 0 | } else if (match70(tok2->next())) |
2883 | 0 | tok2->deleteNext(); |
2884 | 0 | } |
2885 | | |
2886 | | // Add outer template.. |
2887 | 0 | if (templateParameters(tok->next()) || tok->strAt(2) == MatchCompiler::makeConstString(">")) { |
2888 | 0 | while (true) { |
2889 | 0 | const std::string fullName = scopeName + (scopeName.empty()?"":" :: ") + |
2890 | 0 | qualification + (qualification.empty()?"":" :: ") + tok->str(); |
2891 | 0 | const auto it = std::find_if(mTemplateDeclarations.cbegin(), mTemplateDeclarations.cend(), FindFullName(fullName)); |
2892 | 0 | if (it != mTemplateDeclarations.end()) { |
2893 | | // full name matches |
2894 | 0 | addInstantiation(tok, it->scope()); |
2895 | 0 | break; |
2896 | 0 | } |
2897 | | // full name doesn't match so try with using namespaces if available |
2898 | 0 | bool found = false; |
2899 | 0 | for (const auto & nameSpace : tok->scopeInfo()->usingNamespaces) { |
2900 | 0 | std::string fullNameSpace = scopeName + (scopeName.empty()?"":" :: ") + |
2901 | 0 | nameSpace + (qualification.empty()?"":" :: ") + qualification; |
2902 | 0 | std::string newFullName = fullNameSpace + " :: " + tok->str(); |
2903 | 0 | const auto it1 = std::find_if(mTemplateDeclarations.cbegin(), mTemplateDeclarations.cend(), FindFullName(std::move(newFullName))); |
2904 | 0 | if (it1 != mTemplateDeclarations.end()) { |
2905 | | // insert using namespace into token stream |
2906 | 0 | std::string::size_type offset = 0; |
2907 | 0 | std::string::size_type pos = 0; |
2908 | 0 | while ((pos = nameSpace.find(' ', offset)) != std::string::npos) { |
2909 | 0 | qualificationTok->insertTokenBefore(nameSpace.substr(offset, pos - offset)); |
2910 | 0 | offset = pos + 1; |
2911 | 0 | } |
2912 | 0 | qualificationTok->insertTokenBefore(nameSpace.substr(offset)); |
2913 | 0 | qualificationTok->insertTokenBefore("::"); |
2914 | 0 | addInstantiation(tok, it1->scope()); |
2915 | 0 | found = true; |
2916 | 0 | break; |
2917 | 0 | } |
2918 | 0 | } |
2919 | 0 | if (found) |
2920 | 0 | break; |
2921 | | |
2922 | 0 | if (scopeName.empty()) { |
2923 | 0 | if (!qualification.empty()) |
2924 | 0 | addInstantiation(tok, qualification); |
2925 | 0 | else |
2926 | 0 | addInstantiation(tok, tok->scopeInfo()->name); |
2927 | 0 | break; |
2928 | 0 | } |
2929 | 0 | const std::string::size_type pos = scopeName.rfind(" :: "); |
2930 | 0 | scopeName = (pos == std::string::npos) ? std::string() : scopeName.substr(0,pos); |
2931 | 0 | } |
2932 | 0 | } |
2933 | 0 | } |
2934 | 0 | } |
2935 | 0 | } |
2936 | | |
2937 | | |
2938 | | void TemplateSimplifier::useDefaultArgumentValues() |
2939 | 0 | { |
2940 | 0 | for (TokenAndName &declaration : mTemplateDeclarations) |
2941 | 0 | useDefaultArgumentValues(declaration); |
2942 | |
|
2943 | 0 | for (TokenAndName &declaration : mTemplateForwardDeclarations) |
2944 | 0 | useDefaultArgumentValues(declaration); |
2945 | 0 | } |
2946 | | |
2947 | | void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration) |
2948 | 0 | { |
2949 | | // Ticket #5762: Skip specialization tokens |
2950 | 0 | if (declaration.isSpecialization() || declaration.isAlias() || declaration.isFriend()) |
2951 | 0 | return; |
2952 | | |
2953 | | // template parameters with default value has syntax such as: |
2954 | | // x = y |
2955 | | // this list will contain all the '=' tokens for such arguments |
2956 | 0 | struct Default { |
2957 | 0 | Token *eq; |
2958 | 0 | Token *end; |
2959 | 0 | }; |
2960 | 0 | std::list<Default> eq; |
2961 | | // and this set the position of parameters with a default value |
2962 | 0 | std::set<std::size_t> defaultedArgPos; |
2963 | | |
2964 | | // parameter number. 1,2,3,.. |
2965 | 0 | std::size_t templatepar = 1; |
2966 | | |
2967 | | // parameter depth |
2968 | 0 | std::size_t templateParmDepth = 0; |
2969 | | |
2970 | | // map type parameter name to index |
2971 | 0 | std::map<std::string, unsigned int> typeParameterNames; |
2972 | | |
2973 | | // Scan template declaration.. |
2974 | 0 | for (Token *tok = declaration.token()->next(); tok; tok = tok->next()) { |
2975 | 0 | if (match40(tok)) { |
2976 | 0 | Token* end = tok->next()->findClosingBracket(); |
2977 | 0 | if (end) |
2978 | 0 | tok = end; |
2979 | 0 | continue; |
2980 | 0 | } |
2981 | | |
2982 | 0 | if (tok->link() && match71(tok)) { // Ticket #6835 |
2983 | 0 | tok = tok->link(); |
2984 | 0 | continue; |
2985 | 0 | } |
2986 | | |
2987 | 0 | if (tok->str() == MatchCompiler::makeConstString("<") && |
2988 | 0 | (tok->strAt(1) == MatchCompiler::makeConstString(">") || (tok->previous()->isName() && |
2989 | 0 | typeParameterNames.find(tok->strAt(-1)) == typeParameterNames.end()))) |
2990 | 0 | ++templateParmDepth; |
2991 | | |
2992 | | // end of template parameters? |
2993 | 0 | if (tok->str() == MatchCompiler::makeConstString(">")) { |
2994 | 0 | if (templateParmDepth<2) { |
2995 | 0 | if (!eq.empty()) |
2996 | 0 | eq.back().end = tok; |
2997 | 0 | break; |
2998 | 0 | } |
2999 | 0 | --templateParmDepth; |
3000 | 0 | } |
3001 | | |
3002 | | // map type parameter name to index |
3003 | 0 | if (match72(tok)) |
3004 | 0 | typeParameterNames[tok->strAt(1)] = templatepar - 1; |
3005 | | |
3006 | | // next template parameter |
3007 | 0 | if (tok->str() == MatchCompiler::makeConstString(",") && (1 == templateParmDepth)) { // Ticket #5823: Properly count parameters |
3008 | 0 | if (!eq.empty()) |
3009 | 0 | eq.back().end = tok; |
3010 | 0 | ++templatepar; |
3011 | 0 | } |
3012 | | |
3013 | | // default parameter value? |
3014 | 0 | else if (match73(tok)) { |
3015 | 0 | if (defaultedArgPos.insert(templatepar).second) { |
3016 | 0 | eq.emplace_back(Default{tok, nullptr}); |
3017 | 0 | } else { |
3018 | | // Ticket #5605: Syntax error (two equal signs for the same parameter), bail out |
3019 | 0 | eq.clear(); |
3020 | 0 | break; |
3021 | 0 | } |
3022 | 0 | } |
3023 | 0 | } |
3024 | 0 | if (eq.empty()) |
3025 | 0 | return; |
3026 | | |
3027 | | // iterate through all template instantiations |
3028 | 0 | for (const TokenAndName &instantiation : mTemplateInstantiations) { |
3029 | 0 | if (declaration.fullName() != instantiation.fullName()) |
3030 | 0 | continue; |
3031 | | |
3032 | | // instantiation arguments.. |
3033 | 0 | std::vector<std::vector<const Token *>> instantiationArgs; |
3034 | 0 | std::size_t index = 0; |
3035 | 0 | const Token *end = instantiation.token()->next()->findClosingBracket(); |
3036 | 0 | if (!end) |
3037 | 0 | continue; |
3038 | 0 | if (end != instantiation.token()->tokAt(2)) |
3039 | 0 | instantiationArgs.resize(1); |
3040 | 0 | for (const Token *tok1 = instantiation.token()->tokAt(2); tok1 && tok1 != end; tok1 = tok1->next()) { |
3041 | 0 | if (tok1->link() && match71(tok1)) { |
3042 | 0 | const Token *endLink = tok1->link(); |
3043 | 0 | do { |
3044 | 0 | instantiationArgs[index].push_back(tok1); |
3045 | 0 | tok1 = tok1->next(); |
3046 | 0 | } while (tok1 && tok1 != endLink); |
3047 | 0 | instantiationArgs[index].push_back(tok1); |
3048 | 0 | } else if (tok1->str() == MatchCompiler::makeConstString("<") && |
3049 | 0 | (tok1->strAt(1) == MatchCompiler::makeConstString(">") || (tok1->previous()->isName() && |
3050 | 0 | typeParameterNames.find(tok1->strAt(-1)) == typeParameterNames.end()))) { |
3051 | 0 | const Token *endLink = tok1->findClosingBracket(); |
3052 | 0 | do { |
3053 | 0 | instantiationArgs[index].push_back(tok1); |
3054 | 0 | tok1 = tok1->next(); |
3055 | 0 | } while (tok1 && tok1 != endLink); |
3056 | 0 | instantiationArgs[index].push_back(tok1); |
3057 | 0 | } else if (tok1->str() == MatchCompiler::makeConstString(",")) { |
3058 | 0 | ++index; |
3059 | 0 | instantiationArgs.resize(index + 1); |
3060 | 0 | } else |
3061 | 0 | instantiationArgs[index].push_back(tok1); |
3062 | 0 | } |
3063 | | |
3064 | | // count the parameters.. |
3065 | 0 | Token *tok = instantiation.token()->next(); |
3066 | 0 | unsigned int usedpar = templateParameters(tok); |
3067 | 0 | Token *instantiationEnd = tok->findClosingBracket(); |
3068 | 0 | tok = instantiationEnd; |
3069 | |
|
3070 | 0 | if (tok && tok->str() == MatchCompiler::makeConstString(">")) { |
3071 | 0 | tok = tok->previous(); |
3072 | 0 | auto it = eq.cbegin(); |
3073 | 0 | for (std::size_t i = (templatepar - eq.size()); it != eq.cend() && i < usedpar; ++i) |
3074 | 0 | ++it; |
3075 | 0 | int count = 0; |
3076 | 0 | while (it != eq.cend()) { |
3077 | | // check for end |
3078 | 0 | if (!it->end) { |
3079 | 0 | if (mSettings.debugwarnings && mSettings.severity.isEnabled(Severity::debug)) { |
3080 | 0 | const std::list<const Token*> locationList(1, it->eq); |
3081 | 0 | const ErrorMessage errmsg(locationList, &mTokenizer.list, |
3082 | 0 | Severity::debug, |
3083 | 0 | "noparamend", |
3084 | 0 | "TemplateSimplifier couldn't find end of template parameter.", |
3085 | 0 | Certainty::normal); |
3086 | 0 | mErrorLogger.reportErr(errmsg); |
3087 | 0 | } |
3088 | 0 | break; |
3089 | 0 | } |
3090 | | |
3091 | 0 | if ((usedpar + count) && usedpar <= (instantiationArgs.size() + count)) { |
3092 | 0 | tok->insertToken(","); |
3093 | 0 | tok = tok->next(); |
3094 | 0 | } |
3095 | 0 | std::stack<Token *> links; |
3096 | 0 | for (const Token* from = it->eq->next(); from && from != it->end; from = from->next()) { |
3097 | 0 | auto entry = typeParameterNames.find(from->str()); |
3098 | 0 | if (entry != typeParameterNames.end() && entry->second < instantiationArgs.size()) { |
3099 | 0 | for (const Token *tok1 : instantiationArgs[entry->second]) { |
3100 | 0 | tok->insertToken(tok1->str(), tok1->originalName()); |
3101 | 0 | tok = tok->next(); |
3102 | |
|
3103 | 0 | if (match74(tok)) |
3104 | 0 | links.push(tok); |
3105 | 0 | else if (!links.empty() && match75(tok)) { |
3106 | 0 | Token::createMutualLinks(links.top(), tok); |
3107 | 0 | links.pop(); |
3108 | 0 | } |
3109 | 0 | } |
3110 | 0 | } else { |
3111 | 0 | tok->insertToken(from->str(), from->originalName()); |
3112 | 0 | tok = tok->next(); |
3113 | |
|
3114 | 0 | if (match74(tok)) |
3115 | 0 | links.push(tok); |
3116 | 0 | else if (!links.empty() && match75(tok)) { |
3117 | 0 | Token::createMutualLinks(links.top(), tok); |
3118 | 0 | links.pop(); |
3119 | 0 | } |
3120 | 0 | } |
3121 | 0 | } |
3122 | 0 | ++it; |
3123 | 0 | count++; |
3124 | 0 | usedpar++; |
3125 | 0 | } |
3126 | 0 | } |
3127 | |
|
3128 | 0 | simplifyTemplateArgs(instantiation.token()->next(), instantiationEnd); |
3129 | 0 | } |
3130 | |
|
3131 | 0 | for (const auto & entry : eq) { |
3132 | 0 | Token *const eqtok = entry.eq; |
3133 | 0 | Token *tok2; |
3134 | 0 | int indentlevel = 0; |
3135 | 0 | for (tok2 = eqtok->next(); tok2; tok2 = tok2->next()) { |
3136 | 0 | if (match76(tok2)) { // bail out #6607 |
3137 | 0 | tok2 = nullptr; |
3138 | 0 | break; |
3139 | 0 | } |
3140 | 0 | if (match77(tok2)) |
3141 | 0 | tok2 = tok2->link(); |
3142 | 0 | else if (match25(tok2) && (tok2->strAt(2) == MatchCompiler::makeConstString(">") || templateParameters(tok2->next()))) { |
3143 | 0 | const auto ti = std::find_if(mTemplateInstantiations.cbegin(), |
3144 | 0 | mTemplateInstantiations.cend(), |
3145 | 0 | FindToken(tok2)); |
3146 | 0 | if (ti != mTemplateInstantiations.end()) |
3147 | 0 | mTemplateInstantiations.erase(ti); |
3148 | 0 | ++indentlevel; |
3149 | 0 | } else if (indentlevel > 0 && tok2->str() == MatchCompiler::makeConstString(">")) |
3150 | 0 | --indentlevel; |
3151 | 0 | else if (indentlevel == 0 && match78(tok2)) |
3152 | 0 | break; |
3153 | 0 | if (indentlevel < 0) |
3154 | 0 | break; |
3155 | 0 | } |
3156 | | // something went wrong, don't call eraseTokens() |
3157 | | // with a nullptr "end" parameter (=all remaining tokens). |
3158 | 0 | if (!tok2) |
3159 | 0 | continue; |
3160 | | |
3161 | | // don't strip args from uninstantiated templates |
3162 | 0 | const auto ti2 = std::find_if(mTemplateInstantiations.cbegin(), |
3163 | 0 | mTemplateInstantiations.cend(), |
3164 | 0 | FindName(declaration.name())); |
3165 | |
|
3166 | 0 | if (ti2 == mTemplateInstantiations.end()) |
3167 | 0 | continue; |
3168 | | |
3169 | 0 | eraseTokens(eqtok, tok2); |
3170 | 0 | eqtok->deleteThis(); |
3171 | | |
3172 | | // update parameter end pointer |
3173 | 0 | declaration.paramEnd(declaration.token()->next()->findClosingBracket()); |
3174 | 0 | } |
3175 | 0 | } |
3176 | | |
3177 | | void TemplateSimplifier::simplifyTemplateAliases() |
3178 | 0 | { |
3179 | 0 | for (auto it1 = mTemplateDeclarations.cbegin(); it1 != mTemplateDeclarations.cend();) { |
3180 | 0 | const TokenAndName &aliasDeclaration = *it1; |
3181 | |
|
3182 | 0 | if (!aliasDeclaration.isAlias()) { |
3183 | 0 | ++it1; |
3184 | 0 | continue; |
3185 | 0 | } |
3186 | | |
3187 | | // alias parameters.. |
3188 | 0 | std::vector<const Token *> aliasParameters; |
3189 | 0 | getTemplateParametersInDeclaration(aliasDeclaration.token()->tokAt(2), aliasParameters); |
3190 | 0 | std::map<std::string, unsigned int> aliasParameterNames; |
3191 | 0 | for (unsigned int argnr = 0; argnr < aliasParameters.size(); ++argnr) |
3192 | 0 | aliasParameterNames[aliasParameters[argnr]->str()] = argnr; |
3193 | | |
3194 | | // Look for alias usages.. |
3195 | 0 | bool found = false; |
3196 | 0 | for (auto it2 = mTemplateInstantiations.cbegin(); it2 != mTemplateInstantiations.cend();) { |
3197 | 0 | const TokenAndName &aliasUsage = *it2; |
3198 | 0 | if (!aliasUsage.token() || aliasUsage.fullName() != aliasDeclaration.fullName()) { |
3199 | 0 | ++it2; |
3200 | 0 | continue; |
3201 | 0 | } |
3202 | | |
3203 | | // don't recurse |
3204 | 0 | if (aliasDeclaration.isAliasToken(aliasUsage.token())) { |
3205 | 0 | ++it2; |
3206 | 0 | continue; |
3207 | 0 | } |
3208 | | |
3209 | 0 | std::vector<std::pair<Token *, Token *>> args; |
3210 | 0 | Token *tok2 = aliasUsage.token()->tokAt(2); |
3211 | 0 | while (tok2) { |
3212 | 0 | Token * const start = tok2; |
3213 | 0 | while (tok2 && !match79(tok2)) { |
3214 | 0 | if (tok2->link() && match14(tok2)) |
3215 | 0 | tok2 = tok2->link(); |
3216 | 0 | else if (tok2->str() == MatchCompiler::makeConstString("<")) { |
3217 | 0 | tok2 = tok2->findClosingBracket(); |
3218 | 0 | if (!tok2) |
3219 | 0 | break; |
3220 | 0 | } |
3221 | 0 | tok2 = tok2->next(); |
3222 | 0 | } |
3223 | |
|
3224 | 0 | args.emplace_back(start, tok2); |
3225 | 0 | if (tok2 && tok2->str() == MatchCompiler::makeConstString(",")) { |
3226 | 0 | tok2 = tok2->next(); |
3227 | 0 | } else { |
3228 | 0 | break; |
3229 | 0 | } |
3230 | 0 | } |
3231 | 0 | if (!tok2 || tok2->str() != MatchCompiler::makeConstString(">") || |
3232 | 0 | (!aliasDeclaration.isVariadic() && (args.size() != aliasParameters.size())) || |
3233 | 0 | (aliasDeclaration.isVariadic() && (args.size() < aliasParameters.size()))) { |
3234 | 0 | ++it2; |
3235 | 0 | continue; |
3236 | 0 | } |
3237 | | |
3238 | 0 | mChanged = true; |
3239 | | |
3240 | | // copy template-id from declaration to after instantiation |
3241 | 0 | Token * dst = aliasUsage.token()->next()->findClosingBracket(); |
3242 | 0 | const Token* end = TokenList::copyTokens(dst, aliasDeclaration.aliasStartToken(), aliasDeclaration.aliasEndToken()->previous(), false)->next(); |
3243 | | |
3244 | | // replace parameters |
3245 | 0 | for (Token *tok1 = dst->next(); tok1 != end; tok1 = tok1->next()) { |
3246 | 0 | if (!tok1->isName()) |
3247 | 0 | continue; |
3248 | 0 | if (aliasParameterNames.find(tok1->str()) != aliasParameterNames.end()) { |
3249 | 0 | const unsigned int argnr = aliasParameterNames[tok1->str()]; |
3250 | 0 | const Token * const fromStart = args[argnr].first; |
3251 | 0 | const Token * const fromEnd = args[argnr].second->previous(); |
3252 | 0 | Token *temp = TokenList::copyTokens(tok1, fromStart, fromEnd, true); |
3253 | 0 | const bool tempOK(temp != tok1->next()); |
3254 | 0 | tok1->deleteThis(); |
3255 | 0 | if (tempOK) |
3256 | 0 | tok1 = temp; // skip over inserted parameters |
3257 | 0 | } else if (tok1->str() == MatchCompiler::makeConstString("typename")) |
3258 | 0 | tok1->deleteThis(); |
3259 | 0 | } |
3260 | | |
3261 | | // add new instantiations |
3262 | 0 | for (Token *tok1 = dst->next(); tok1 != end; tok1 = tok1->next()) { |
3263 | 0 | if (!tok1->isName()) |
3264 | 0 | continue; |
3265 | 0 | if (aliasParameterNames.find(tok2->str()) == aliasParameterNames.end()) { |
3266 | | // Create template instance.. |
3267 | 0 | if (match6(tok1)) { |
3268 | 0 | const auto it = std::find_if(mTemplateInstantiations.cbegin(), |
3269 | 0 | mTemplateInstantiations.cend(), |
3270 | 0 | FindToken(tok1)); |
3271 | 0 | if (it != mTemplateInstantiations.cend()) |
3272 | 0 | addInstantiation(tok2, it->scope()); |
3273 | 0 | } |
3274 | 0 | } |
3275 | 0 | } |
3276 | | |
3277 | | // erase the instantiation tokens |
3278 | 0 | eraseTokens(aliasUsage.token()->previous(), dst->next()); |
3279 | 0 | found = true; |
3280 | | |
3281 | | // erase this instantiation |
3282 | 0 | it2 = mTemplateInstantiations.erase(it2); |
3283 | 0 | } |
3284 | |
|
3285 | 0 | if (found) { |
3286 | 0 | auto *end = const_cast<Token *>(aliasDeclaration.aliasEndToken()); |
3287 | | |
3288 | | // remove declaration tokens |
3289 | 0 | if (aliasDeclaration.token()->previous()) |
3290 | 0 | eraseTokens(aliasDeclaration.token()->previous(), end->next() ? end->next() : end); |
3291 | 0 | else { |
3292 | 0 | eraseTokens(mTokenList.front(), end->next() ? end->next() : end); |
3293 | 0 | deleteToken(mTokenList.front()); |
3294 | 0 | } |
3295 | | |
3296 | | // remove declaration |
3297 | 0 | it1 = mTemplateDeclarations.erase(it1); |
3298 | 0 | } else |
3299 | 0 | ++it1; |
3300 | 0 | } |
3301 | 0 | } |
3302 | | |
3303 | | bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size_t numberOfArguments, bool variadic, const char patternAfter[]) |
3304 | 0 | { |
3305 | 0 | assert(instance->strAt(1) == MatchCompiler::makeConstString("<")); |
3306 | | |
3307 | 0 | auto n = templateParameters(instance->next()); |
3308 | 0 | if (variadic ? (n + 1 < numberOfArguments) : (numberOfArguments != n)) |
3309 | 0 | return false; |
3310 | | |
3311 | 0 | if (patternAfter) { |
3312 | 0 | const Token *tok = instance->next()->findClosingBracket(); |
3313 | 0 | if (!tok || !Token::Match(tok->next(), patternAfter)) |
3314 | 0 | return false; |
3315 | 0 | } |
3316 | | |
3317 | | // nothing mismatching was found.. |
3318 | 0 | return true; |
3319 | 0 | } |
3320 | | |
3321 | | // Utility function for TemplateSimplifier::getTemplateNamePosition, that works on template functions |
3322 | | bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos) |
3323 | 0 | { |
3324 | 0 | namepos = 1; |
3325 | 0 | while (tok && tok->next()) { |
3326 | 0 | if (match13(tok->next())) |
3327 | 0 | return false; |
3328 | | // skip decltype(...) |
3329 | 0 | if (match54(tok->next())) { |
3330 | 0 | const Token * end = tok->linkAt(2)->previous(); |
3331 | 0 | while (tok->next() && tok != end) { |
3332 | 0 | tok = tok->next(); |
3333 | 0 | namepos++; |
3334 | 0 | } |
3335 | 0 | } else if (match25(tok->next())) { |
3336 | 0 | const Token *closing = tok->tokAt(2)->findClosingBracket(); |
3337 | 0 | if (closing) { |
3338 | 0 | if (closing->strAt(1) == MatchCompiler::makeConstString("(") && TokenList::isFunctionHead(closing->next(), ";|{|:")) |
3339 | 0 | return true; |
3340 | 0 | while (tok->next() && tok->next() != closing) { |
3341 | 0 | tok = tok->next(); |
3342 | 0 | namepos++; |
3343 | 0 | } |
3344 | 0 | } |
3345 | 0 | } else if (match80(tok->next()) && TokenList::isFunctionHead(tok->tokAt(2), ";|{|:")) { |
3346 | 0 | return true; |
3347 | 0 | } |
3348 | 0 | tok = tok->next(); |
3349 | 0 | namepos++; |
3350 | 0 | } |
3351 | 0 | return false; |
3352 | 0 | } |
3353 | | |
3354 | | bool TemplateSimplifier::getTemplateNamePositionTemplateVariable(const Token *tok, int &namepos) |
3355 | 0 | { |
3356 | 0 | namepos = 1; |
3357 | 0 | while (tok && tok->next()) { |
3358 | 0 | if (match81(tok->next())) |
3359 | 0 | return false; |
3360 | | // skip decltype(...) |
3361 | 0 | if (match54(tok->next())) { |
3362 | 0 | const Token * end = tok->linkAt(2); |
3363 | 0 | while (tok->next() && tok != end) { |
3364 | 0 | tok = tok->next(); |
3365 | 0 | namepos++; |
3366 | 0 | } |
3367 | 0 | } else if (match25(tok->next())) { |
3368 | 0 | const Token *closing = tok->tokAt(2)->findClosingBracket(); |
3369 | 0 | if (closing) { |
3370 | 0 | if (match12(closing->next())) |
3371 | 0 | return true; |
3372 | 0 | while (tok->next() && tok->next() != closing) { |
3373 | 0 | tok = tok->next(); |
3374 | 0 | namepos++; |
3375 | 0 | } |
3376 | 0 | } |
3377 | 0 | } else if (match82(tok->next())) { |
3378 | 0 | return true; |
3379 | 0 | } |
3380 | 0 | tok = tok->next(); |
3381 | 0 | namepos++; |
3382 | 0 | } |
3383 | 0 | return false; |
3384 | 0 | } |
3385 | | |
3386 | | bool TemplateSimplifier::getTemplateNamePositionTemplateClass(const Token *tok, int &namepos) |
3387 | 0 | { |
3388 | 0 | if (match83(tok)) { |
3389 | 0 | namepos = tok->strAt(1) == MatchCompiler::makeConstString("friend") ? 3 : 2; |
3390 | 0 | tok = tok->tokAt(namepos); |
3391 | 0 | while (match84(tok) || |
3392 | 0 | (match25(tok) && match85(tok->next()->findClosingBracket()))) { |
3393 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("::")) { |
3394 | 0 | tok = tok->tokAt(2); |
3395 | 0 | namepos += 2; |
3396 | 0 | } else { |
3397 | 0 | const Token *end = tok->next()->findClosingBracket(); |
3398 | 0 | if (!end || !end->tokAt(2)) { |
3399 | | // syntax error |
3400 | 0 | namepos = -1; |
3401 | 0 | return true; |
3402 | 0 | } |
3403 | 0 | end = end->tokAt(2); |
3404 | 0 | do { |
3405 | 0 | tok = tok->next(); |
3406 | 0 | namepos += 1; |
3407 | 0 | } while (tok && tok != end); |
3408 | 0 | } |
3409 | 0 | } |
3410 | 0 | return true; |
3411 | 0 | } |
3412 | 0 | return false; |
3413 | 0 | } |
3414 | | |
3415 | | int TemplateSimplifier::getTemplateNamePosition(const Token *tok) |
3416 | 0 | { |
3417 | 0 | if (!tok || tok->str() != MatchCompiler::makeConstString(">")) |
3418 | 0 | syntaxError(tok); |
3419 | |
|
3420 | 0 | auto it = mTemplateNamePos.find(tok); |
3421 | 0 | if (!mSettings.debugtemplate && it != mTemplateNamePos.end()) { |
3422 | 0 | return it->second; |
3423 | 0 | } |
3424 | | // get the position of the template name |
3425 | 0 | int namepos = 0; |
3426 | 0 | if (getTemplateNamePositionTemplateClass(tok, namepos)) |
3427 | 0 | ; |
3428 | 0 | else if (match86(tok)) { |
3429 | | // types may not be defined in alias template declarations |
3430 | 0 | if (!match87(tok->tokAt(4))) |
3431 | 0 | namepos = 2; |
3432 | 0 | } else if (getTemplateNamePositionTemplateVariable(tok, namepos)) |
3433 | 0 | ; |
3434 | 0 | else if (!getTemplateNamePositionTemplateFunction(tok, namepos)) |
3435 | 0 | namepos = -1; // Name not found |
3436 | 0 | mTemplateNamePos[tok] = namepos; |
3437 | 0 | return namepos; |
3438 | 0 | } |
3439 | | |
3440 | | void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, const Token *tok) |
3441 | 0 | { |
3442 | | // find start of qualification |
3443 | 0 | const Token * tokStart = tok; |
3444 | 0 | int offset = 0; |
3445 | 0 | while (match16(tokStart->tokAt(-2))) { |
3446 | 0 | tokStart = tokStart->tokAt(-2); |
3447 | 0 | offset -= 2; |
3448 | 0 | } |
3449 | | // decide if namespace needs to be inserted in or appended to token list |
3450 | 0 | const bool insert = tokStart != tok; |
3451 | |
|
3452 | 0 | std::string::size_type start = 0; |
3453 | 0 | std::string::size_type end = 0; |
3454 | 0 | bool inTemplate = false; |
3455 | 0 | int level = 0; |
3456 | 0 | while ((end = templateDeclaration.scope().find(' ', start)) != std::string::npos) { |
3457 | 0 | std::string token = templateDeclaration.scope().substr(start, end - start); |
3458 | | // done if scopes overlap |
3459 | 0 | if (token == tokStart->str() && tok->strAt(-1) != MatchCompiler::makeConstString("::")) |
3460 | 0 | break; |
3461 | 0 | if (token == MatchCompiler::makeConstString("<")) { |
3462 | 0 | inTemplate = true; |
3463 | 0 | ++level; |
3464 | 0 | } |
3465 | 0 | if (inTemplate) { |
3466 | 0 | if (insert) |
3467 | 0 | mTokenList.back()->tokAt(offset)->str(mTokenList.back()->strAt(offset) + token); |
3468 | 0 | else |
3469 | 0 | mTokenList.back()->str(mTokenList.back()->str() + token); |
3470 | 0 | if (token == MatchCompiler::makeConstString(">")) { |
3471 | 0 | --level; |
3472 | 0 | if (level == 0) |
3473 | 0 | inTemplate = false; |
3474 | 0 | } |
3475 | 0 | } else { |
3476 | 0 | if (insert) |
3477 | 0 | mTokenList.back()->tokAt(offset)->insertToken(token, emptyString); |
3478 | 0 | else |
3479 | 0 | mTokenList.addtoken(token, tok->linenr(), tok->column(), tok->fileIndex()); |
3480 | 0 | } |
3481 | 0 | start = end + 1; |
3482 | 0 | } |
3483 | | // don't add if it already exists |
3484 | 0 | std::string token = templateDeclaration.scope().substr(start, end - start); |
3485 | 0 | if (token != tokStart->str() || tok->strAt(-1) != MatchCompiler::makeConstString("::")) { |
3486 | 0 | if (insert) { |
3487 | 0 | if (!inTemplate) |
3488 | 0 | mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope().substr(start), emptyString); |
3489 | 0 | else |
3490 | 0 | mTokenList.back()->tokAt(offset)->str(mTokenList.back()->strAt(offset) + templateDeclaration.scope().substr(start)); |
3491 | 0 | mTokenList.back()->tokAt(offset)->insertToken("::", emptyString); |
3492 | 0 | } else { |
3493 | 0 | if (!inTemplate) |
3494 | 0 | mTokenList.addtoken(templateDeclaration.scope().substr(start), tok->linenr(), tok->column(), tok->fileIndex()); |
3495 | 0 | else |
3496 | 0 | mTokenList.back()->str(mTokenList.back()->str() + templateDeclaration.scope().substr(start)); |
3497 | 0 | mTokenList.addtoken("::", tok->linenr(), tok->column(), tok->fileIndex()); |
3498 | 0 | } |
3499 | 0 | } |
3500 | 0 | } |
3501 | | |
3502 | | bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) |
3503 | 0 | { |
3504 | 0 | const std::string& scope = templateDeclaration.scope(); |
3505 | | |
3506 | | // get the length in tokens of the namespace |
3507 | 0 | std::string::size_type pos = 0; |
3508 | 0 | int offset = -2; |
3509 | |
|
3510 | 0 | while ((pos = scope.find("::", pos)) != std::string::npos) { |
3511 | 0 | offset -= 2; |
3512 | 0 | pos += 2; |
3513 | 0 | } |
3514 | |
|
3515 | 0 | return Token::simpleMatch(tok->tokAt(offset), scope.c_str(), scope.size()); |
3516 | 0 | } |
3517 | | |
3518 | | struct newInstantiation { |
3519 | 0 | newInstantiation(Token* t, std::string s) : token(t), scope(std::move(s)) {} |
3520 | | Token* token; |
3521 | | std::string scope; |
3522 | | }; |
3523 | | |
3524 | | void TemplateSimplifier::expandTemplate( |
3525 | | const TokenAndName &templateDeclaration, |
3526 | | const TokenAndName &templateInstantiation, |
3527 | | const std::vector<const Token *> &typeParametersInDeclaration, |
3528 | | const std::string &newName, |
3529 | | bool copy) |
3530 | 0 | { |
3531 | 0 | bool inTemplateDefinition = false; |
3532 | 0 | const Token *startOfTemplateDeclaration = nullptr; |
3533 | 0 | const Token *endOfTemplateDefinition = nullptr; |
3534 | 0 | const Token * const templateDeclarationNameToken = templateDeclaration.nameToken(); |
3535 | 0 | const Token * const templateDeclarationToken = templateDeclaration.paramEnd(); |
3536 | 0 | const bool isClass = templateDeclaration.isClass(); |
3537 | 0 | const bool isFunction = templateDeclaration.isFunction(); |
3538 | 0 | const bool isSpecialization = templateDeclaration.isSpecialization(); |
3539 | 0 | const bool isVariable = templateDeclaration.isVariable(); |
3540 | |
|
3541 | 0 | std::vector<newInstantiation> newInstantiations; |
3542 | | |
3543 | | // add forward declarations |
3544 | 0 | if (copy && isClass) { |
3545 | 0 | templateDeclaration.token()->insertTokenBefore(templateDeclarationToken->strAt(1)); |
3546 | 0 | templateDeclaration.token()->insertTokenBefore(newName); |
3547 | 0 | templateDeclaration.token()->insertTokenBefore(";"); |
3548 | 0 | } else if ((isFunction && (copy || isSpecialization)) || |
3549 | 0 | (isVariable && !isSpecialization) || |
3550 | 0 | (isClass && isSpecialization && mTemplateSpecializationMap.find(templateDeclaration.token()) != mTemplateSpecializationMap.end())) { |
3551 | 0 | Token * dst = templateDeclaration.token(); |
3552 | 0 | Token * dstStart = dst->previous(); |
3553 | 0 | bool isStatic = false; |
3554 | 0 | std::string scope; |
3555 | 0 | const Token * start; |
3556 | 0 | const Token * end; |
3557 | 0 | auto it = mTemplateForwardDeclarationsMap.find(dst); |
3558 | 0 | if (!isSpecialization && it != mTemplateForwardDeclarationsMap.end()) { |
3559 | 0 | dst = it->second; |
3560 | 0 | dstStart = dst->previous(); |
3561 | 0 | const Token * temp1 = dst->tokAt(1)->findClosingBracket(); |
3562 | 0 | const Token * temp2 = temp1->tokAt(getTemplateNamePosition(temp1)); |
3563 | 0 | start = temp1->next(); |
3564 | 0 | end = temp2->linkAt(1)->next(); |
3565 | 0 | } else { |
3566 | 0 | if (it != mTemplateForwardDeclarationsMap.end()) { |
3567 | 0 | const auto it1 = std::find_if(mTemplateForwardDeclarations.cbegin(), |
3568 | 0 | mTemplateForwardDeclarations.cend(), |
3569 | 0 | FindToken(it->second)); |
3570 | 0 | if (it1 != mTemplateForwardDeclarations.cend()) |
3571 | 0 | mMemberFunctionsToDelete.push_back(*it1); |
3572 | 0 | } |
3573 | |
|
3574 | 0 | auto it2 = mTemplateSpecializationMap.find(dst); |
3575 | 0 | if (it2 != mTemplateSpecializationMap.end()) { |
3576 | 0 | dst = it2->second; |
3577 | 0 | dstStart = dst->previous(); |
3578 | 0 | isStatic = dst->next()->findClosingBracket()->strAt(1) == MatchCompiler::makeConstString("static"); |
3579 | 0 | const Token * temp = templateDeclarationNameToken; |
3580 | 0 | while (match16(temp->tokAt(-2))) { |
3581 | 0 | scope.insert(0, temp->strAt(-2) + " :: "); |
3582 | 0 | temp = temp->tokAt(-2); |
3583 | 0 | } |
3584 | 0 | } |
3585 | 0 | start = templateDeclarationToken->next(); |
3586 | 0 | end = templateDeclarationNameToken->next(); |
3587 | 0 | if (end->str() == MatchCompiler::makeConstString("<")) |
3588 | 0 | end = end->findClosingBracket()->next(); |
3589 | 0 | if (end->str() == MatchCompiler::makeConstString("(")) |
3590 | 0 | end = end->link()->next(); |
3591 | 0 | else if (isVariable && end->str() == MatchCompiler::makeConstString("=")) { |
3592 | 0 | const Token *temp = end->next(); |
3593 | 0 | while (temp && temp->str() != MatchCompiler::makeConstString(";")) { |
3594 | 0 | if (temp->link() && match88(temp)) |
3595 | 0 | temp = temp->link(); |
3596 | 0 | temp = temp->next(); |
3597 | 0 | } |
3598 | 0 | end = temp; |
3599 | 0 | } |
3600 | 0 | } |
3601 | 0 | unsigned int typeindentlevel = 0; |
3602 | 0 | while (end && !(typeindentlevel == 0 && match89(end))) { |
3603 | 0 | if (match90(end)) |
3604 | 0 | ++typeindentlevel; |
3605 | 0 | else if (match91(end)) |
3606 | 0 | --typeindentlevel; |
3607 | 0 | end = end->next(); |
3608 | 0 | } |
3609 | |
|
3610 | 0 | if (isStatic) { |
3611 | 0 | dst->insertTokenBefore("static"); |
3612 | 0 | if (start) { |
3613 | 0 | dst->previous()->linenr(start->linenr()); |
3614 | 0 | dst->previous()->column(start->column()); |
3615 | 0 | } |
3616 | 0 | } |
3617 | |
|
3618 | 0 | std::map<const Token *, Token *> links; |
3619 | 0 | bool inAssignment = false; |
3620 | 0 | while (start && start != end) { |
3621 | 0 | if (isVariable && start->str() == MatchCompiler::makeConstString("=")) |
3622 | 0 | inAssignment = true; |
3623 | 0 | unsigned int itype = 0; |
3624 | 0 | while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != start->str()) |
3625 | 0 | ++itype; |
3626 | |
|
3627 | 0 | if (itype < typeParametersInDeclaration.size() && itype < mTypesUsedInTemplateInstantiation.size() && |
3628 | 0 | (!isVariable || !match92(typeParametersInDeclaration[itype]->previous()))) { |
3629 | 0 | typeindentlevel = 0; |
3630 | 0 | std::stack<Token *> brackets1; // holds "(" and "{" tokens |
3631 | 0 | bool pointerType = false; |
3632 | 0 | Token * const dst1 = dst->previous(); |
3633 | 0 | const bool isVariadicTemplateArg = templateDeclaration.isVariadic() && itype + 1 == typeParametersInDeclaration.size(); |
3634 | 0 | if (isVariadicTemplateArg && match93(start)) |
3635 | 0 | start = start->tokAt(2); |
3636 | 0 | const std::string endStr(isVariadicTemplateArg ? ">" : ",>"); |
3637 | 0 | for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); |
3638 | 0 | typetok && (typeindentlevel > 0 || endStr.find(typetok->str()[0]) == std::string::npos); |
3639 | 0 | typetok = typetok->next()) { |
3640 | 0 | if (typeindentlevel == 0 && typetok->str() == MatchCompiler::makeConstString("*")) |
3641 | 0 | pointerType = true; |
3642 | 0 | if (match45(typetok)) |
3643 | 0 | continue; |
3644 | 0 | if (match6(typetok) && (typetok->strAt(2) == MatchCompiler::makeConstString(">") || templateParameters(typetok->next()))) |
3645 | 0 | ++typeindentlevel; |
3646 | 0 | else if (typeindentlevel > 0 && typetok->str() == MatchCompiler::makeConstString(">")) |
3647 | 0 | --typeindentlevel; |
3648 | 0 | else if (typetok->str() == MatchCompiler::makeConstString("(")) |
3649 | 0 | ++typeindentlevel; |
3650 | 0 | else if (typetok->str() == MatchCompiler::makeConstString(")")) |
3651 | 0 | --typeindentlevel; |
3652 | 0 | dst->insertToken(typetok->str(), typetok->originalName(), typetok->getMacroName(), true); |
3653 | 0 | dst->previous()->linenr(start->linenr()); |
3654 | 0 | dst->previous()->column(start->column()); |
3655 | 0 | Token *previous = dst->previous(); |
3656 | 0 | previous->isTemplateArg(true); |
3657 | 0 | previous->isSigned(typetok->isSigned()); |
3658 | 0 | previous->isUnsigned(typetok->isUnsigned()); |
3659 | 0 | previous->isLong(typetok->isLong()); |
3660 | 0 | if (match71(previous)) { |
3661 | 0 | brackets1.push(previous); |
3662 | 0 | } else if (previous->str() == MatchCompiler::makeConstString("}")) { |
3663 | 0 | assert(brackets1.empty() == false); |
3664 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("{")); |
3665 | 0 | Token::createMutualLinks(brackets1.top(), previous); |
3666 | 0 | brackets1.pop(); |
3667 | 0 | } else if (previous->str() == MatchCompiler::makeConstString(")")) { |
3668 | 0 | assert(brackets1.empty() == false); |
3669 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("(")); |
3670 | 0 | Token::createMutualLinks(brackets1.top(), previous); |
3671 | 0 | brackets1.pop(); |
3672 | 0 | } else if (previous->str() == MatchCompiler::makeConstString("]")) { |
3673 | 0 | assert(brackets1.empty() == false); |
3674 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("[")); |
3675 | 0 | Token::createMutualLinks(brackets1.top(), previous); |
3676 | 0 | brackets1.pop(); |
3677 | 0 | } |
3678 | 0 | } |
3679 | 0 | if (pointerType && match94(dst1)) { |
3680 | 0 | dst->insertToken("const", dst1->originalName(), dst1->getMacroName(), true); |
3681 | 0 | dst->previous()->linenr(start->linenr()); |
3682 | 0 | dst->previous()->column(start->column()); |
3683 | 0 | dst1->deleteThis(); |
3684 | 0 | } |
3685 | 0 | } else { |
3686 | 0 | if (isSpecialization && !copy && !scope.empty() && Token::Match(start, (scope + templateDeclarationNameToken->str()).c_str())) { |
3687 | | // skip scope |
3688 | 0 | while (start->strAt(1) != templateDeclarationNameToken->str()) |
3689 | 0 | start = start->next(); |
3690 | 0 | } else if (start->str() == templateDeclarationNameToken->str() && |
3691 | 0 | !(templateDeclaration.isFunction() && templateDeclaration.scope().empty() && |
3692 | 0 | (start->strAt(-1) == MatchCompiler::makeConstString(".") || match95(start->tokAt(-2))))) { |
3693 | 0 | if (start->strAt(1) != MatchCompiler::makeConstString("<") || Token::Match(start, newName.c_str()) || !inAssignment) { |
3694 | 0 | dst->insertTokenBefore(newName); |
3695 | 0 | dst->previous()->linenr(start->linenr()); |
3696 | 0 | dst->previous()->column(start->column()); |
3697 | 0 | if (start->strAt(1) == MatchCompiler::makeConstString("<")) |
3698 | 0 | start = start->next()->findClosingBracket(); |
3699 | 0 | } else { |
3700 | 0 | dst->insertTokenBefore(start->str()); |
3701 | 0 | dst->previous()->linenr(start->linenr()); |
3702 | 0 | dst->previous()->column(start->column()); |
3703 | 0 | newInstantiations.emplace_back(dst->previous(), templateDeclaration.scope()); |
3704 | 0 | } |
3705 | 0 | } else { |
3706 | | // check if type is a template |
3707 | 0 | if (start->strAt(1) == MatchCompiler::makeConstString("<")) { |
3708 | | // get the instantiated name |
3709 | 0 | const Token * closing = start->next()->findClosingBracket(); |
3710 | 0 | if (closing) { |
3711 | 0 | std::string name; |
3712 | 0 | const Token * type = start; |
3713 | 0 | while (type && type != closing->next()) { |
3714 | 0 | if (!name.empty()) |
3715 | 0 | name += " "; |
3716 | 0 | name += type->str(); |
3717 | 0 | type = type->next(); |
3718 | 0 | } |
3719 | | // check if type is instantiated |
3720 | 0 | if (std::any_of(mTemplateInstantiations.cbegin(), mTemplateInstantiations.cend(), [&](const TokenAndName& inst) { |
3721 | 0 | return Token::simpleMatch(inst.token(), name.c_str(), name.size()); |
3722 | 0 | })) { |
3723 | | // use the instantiated name |
3724 | 0 | dst->insertTokenBefore(name); |
3725 | 0 | dst->previous()->linenr(start->linenr()); |
3726 | 0 | dst->previous()->column(start->column()); |
3727 | 0 | start = closing; |
3728 | 0 | } |
3729 | 0 | } |
3730 | | // just copy the token if it wasn't instantiated |
3731 | 0 | if (start != closing) { |
3732 | 0 | dst->insertToken(start->str(), start->originalName(), start->getMacroName(), true); |
3733 | 0 | dst->previous()->linenr(start->linenr()); |
3734 | 0 | dst->previous()->column(start->column()); |
3735 | 0 | dst->previous()->isSigned(start->isSigned()); |
3736 | 0 | dst->previous()->isUnsigned(start->isUnsigned()); |
3737 | 0 | dst->previous()->isLong(start->isLong()); |
3738 | 0 | } |
3739 | 0 | } else { |
3740 | 0 | dst->insertToken(start->str(), start->originalName(), start->getMacroName(), true); |
3741 | 0 | dst->previous()->linenr(start->linenr()); |
3742 | 0 | dst->previous()->column(start->column()); |
3743 | 0 | dst->previous()->isSigned(start->isSigned()); |
3744 | 0 | dst->previous()->isUnsigned(start->isUnsigned()); |
3745 | 0 | dst->previous()->isLong(start->isLong()); |
3746 | 0 | } |
3747 | 0 | } |
3748 | |
|
3749 | 0 | if (!start) |
3750 | 0 | continue; |
3751 | | |
3752 | 0 | if (start->link()) { |
3753 | 0 | if (match96(start)) { |
3754 | 0 | links[start->link()] = dst->previous(); |
3755 | 0 | } else if (match97(start)) { |
3756 | 0 | const auto link = utils::as_const(links).find(start); |
3757 | | // make sure link is valid |
3758 | 0 | if (link != links.cend()) { |
3759 | 0 | Token::createMutualLinks(link->second, dst->previous()); |
3760 | 0 | links.erase(start); |
3761 | 0 | } |
3762 | 0 | } |
3763 | 0 | } |
3764 | 0 | } |
3765 | | |
3766 | 0 | start = start->next(); |
3767 | 0 | } |
3768 | 0 | dst->insertTokenBefore(";"); |
3769 | 0 | dst->previous()->linenr(dst->tokAt(-2)->linenr()); |
3770 | 0 | dst->previous()->column(dst->tokAt(-2)->column() + 1); |
3771 | |
|
3772 | 0 | if (isVariable || isFunction) |
3773 | 0 | simplifyTemplateArgs(dstStart, dst); |
3774 | 0 | } |
3775 | | |
3776 | 0 | if (copy && (isClass || isFunction)) { |
3777 | | // check if this is an explicit instantiation |
3778 | 0 | Token * start = templateInstantiation.token(); |
3779 | 0 | while (start && !match98(start->previous())) |
3780 | 0 | start = start->previous(); |
3781 | 0 | if (match99(start)) { |
3782 | 0 | if (start->strAt(-1) == MatchCompiler::makeConstString("extern")) |
3783 | 0 | start = start->previous(); |
3784 | 0 | mExplicitInstantiationsToDelete.emplace_back(start, ""); |
3785 | 0 | } |
3786 | 0 | } |
3787 | |
|
3788 | 0 | for (Token *tok3 = mTokenList.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) { |
3789 | 0 | if (inTemplateDefinition) { |
3790 | 0 | if (!endOfTemplateDefinition) { |
3791 | 0 | if (isVariable) { |
3792 | 0 | Token *temp = tok3->findClosingBracket(); |
3793 | 0 | if (temp) { |
3794 | 0 | while (temp && temp->str() != MatchCompiler::makeConstString(";")) { |
3795 | 0 | if (temp->link() && match88(temp)) |
3796 | 0 | temp = temp->link(); |
3797 | 0 | temp = temp->next(); |
3798 | 0 | } |
3799 | 0 | endOfTemplateDefinition = temp; |
3800 | 0 | } |
3801 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString("{")) |
3802 | 0 | endOfTemplateDefinition = tok3->link(); |
3803 | 0 | } |
3804 | 0 | if (tok3 == endOfTemplateDefinition) { |
3805 | 0 | inTemplateDefinition = false; |
3806 | 0 | startOfTemplateDeclaration = nullptr; |
3807 | 0 | } |
3808 | 0 | } |
3809 | |
|
3810 | 0 | if (tok3->str()==MatchCompiler::makeConstString("template")) { |
3811 | 0 | if (tok3->next() && tok3->strAt(1)==MatchCompiler::makeConstString("<")) { |
3812 | 0 | std::vector<const Token *> localTypeParametersInDeclaration; |
3813 | 0 | getTemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration); |
3814 | 0 | inTemplateDefinition = localTypeParametersInDeclaration.size() == typeParametersInDeclaration.size(); // Partial specialization |
3815 | 0 | } else { |
3816 | 0 | inTemplateDefinition = false; // Only template instantiation |
3817 | 0 | } |
3818 | 0 | startOfTemplateDeclaration = tok3; |
3819 | 0 | } |
3820 | 0 | if (match14(tok3)) |
3821 | 0 | tok3 = tok3->link(); |
3822 | | |
3823 | | // Start of template.. |
3824 | 0 | if (tok3 == templateDeclarationToken) { |
3825 | 0 | tok3 = tok3->next(); |
3826 | 0 | if (tok3->str() == MatchCompiler::makeConstString("static")) |
3827 | 0 | tok3 = tok3->next(); |
3828 | 0 | } |
3829 | | |
3830 | | // member function implemented outside class definition |
3831 | 0 | else if (inTemplateDefinition && |
3832 | 0 | match6(tok3) && |
3833 | 0 | templateInstantiation.name() == tok3->str() && |
3834 | 0 | instantiateMatch(tok3, typeParametersInDeclaration.size(), templateDeclaration.isVariadic(), ":: ~| %name% (")) { |
3835 | | // there must be template.. |
3836 | 0 | bool istemplate = false; |
3837 | 0 | Token * tok5 = nullptr; // start of function return type |
3838 | 0 | for (Token *prev = tok3; prev && !match18(prev); prev = prev->previous()) { |
3839 | 0 | if (prev->str() == MatchCompiler::makeConstString("template")) { |
3840 | 0 | istemplate = true; |
3841 | 0 | tok5 = prev; |
3842 | 0 | break; |
3843 | 0 | } |
3844 | 0 | } |
3845 | 0 | if (!istemplate) |
3846 | 0 | continue; |
3847 | | |
3848 | 0 | const Token *tok4 = tok3->next()->findClosingBracket(); |
3849 | 0 | while (tok4 && tok4->str() != MatchCompiler::makeConstString("(")) |
3850 | 0 | tok4 = tok4->next(); |
3851 | 0 | if (!TokenList::isFunctionHead(tok4, ":{")) |
3852 | 0 | continue; |
3853 | | // find function return type start |
3854 | 0 | tok5 = tok5->next()->findClosingBracket(); |
3855 | 0 | if (tok5) |
3856 | 0 | tok5 = tok5->next(); |
3857 | | // copy return type |
3858 | 0 | std::stack<Token *> brackets2; // holds "(" and "{" tokens |
3859 | 0 | while (tok5 && tok5 != tok3) { |
3860 | | // replace name if found |
3861 | 0 | if (match6(tok5) && tok5->str() == templateInstantiation.name()) { |
3862 | 0 | if (copy) { |
3863 | 0 | if (!templateDeclaration.scope().empty() && tok5->strAt(-1) != MatchCompiler::makeConstString("::")) |
3864 | 0 | addNamespace(templateDeclaration, tok5); |
3865 | 0 | mTokenList.addtoken(newName, tok5->linenr(), tok5->column(), tok5->fileIndex()); |
3866 | 0 | tok5 = tok5->next()->findClosingBracket(); |
3867 | 0 | } else { |
3868 | 0 | tok5->str(newName); |
3869 | 0 | eraseTokens(tok5, tok5->next()->findClosingBracket()->next()); |
3870 | 0 | } |
3871 | 0 | } else if (copy) { |
3872 | 0 | bool added = false; |
3873 | 0 | if (tok5->isName() && !match100(tok5) && !tok5->isStandardType()) { |
3874 | | // search for this token in the type vector |
3875 | 0 | unsigned int itype = 0; |
3876 | 0 | while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != tok5->str()) |
3877 | 0 | ++itype; |
3878 | | |
3879 | | // replace type with given type.. |
3880 | 0 | if (itype < typeParametersInDeclaration.size() && itype < mTypesUsedInTemplateInstantiation.size()) { |
3881 | 0 | std::stack<Token *> brackets1; // holds "(" and "{" tokens |
3882 | 0 | for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); |
3883 | 0 | typetok && !match78(typetok); |
3884 | 0 | typetok = typetok->next()) { |
3885 | 0 | if (!match45(typetok)) { |
3886 | 0 | mTokenList.addtoken(typetok, tok5); |
3887 | 0 | Token *back = mTokenList.back(); |
3888 | 0 | if (match71(back)) { |
3889 | 0 | brackets1.push(back); |
3890 | 0 | } else if (back->str() == MatchCompiler::makeConstString("}")) { |
3891 | 0 | assert(brackets1.empty() == false); |
3892 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("{")); |
3893 | 0 | Token::createMutualLinks(brackets1.top(), back); |
3894 | 0 | brackets1.pop(); |
3895 | 0 | } else if (back->str() == MatchCompiler::makeConstString(")")) { |
3896 | 0 | assert(brackets1.empty() == false); |
3897 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("(")); |
3898 | 0 | Token::createMutualLinks(brackets1.top(), back); |
3899 | 0 | brackets1.pop(); |
3900 | 0 | } else if (back->str() == MatchCompiler::makeConstString("]")) { |
3901 | 0 | assert(brackets1.empty() == false); |
3902 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("[")); |
3903 | 0 | Token::createMutualLinks(brackets1.top(), back); |
3904 | 0 | brackets1.pop(); |
3905 | 0 | } |
3906 | 0 | back->isTemplateArg(true); |
3907 | 0 | back->isUnsigned(typetok->isUnsigned()); |
3908 | 0 | back->isSigned(typetok->isSigned()); |
3909 | 0 | back->isLong(typetok->isLong()); |
3910 | 0 | added = true; |
3911 | 0 | break; |
3912 | 0 | } |
3913 | 0 | } |
3914 | 0 | } |
3915 | 0 | } |
3916 | 0 | if (!added) { |
3917 | 0 | mTokenList.addtoken(tok5); |
3918 | 0 | Token *back = mTokenList.back(); |
3919 | 0 | if (match71(back)) { |
3920 | 0 | brackets2.push(back); |
3921 | 0 | } else if (back->str() == MatchCompiler::makeConstString("}")) { |
3922 | 0 | assert(brackets2.empty() == false); |
3923 | 0 | assert(brackets2.top()->str() == MatchCompiler::makeConstString("{")); |
3924 | 0 | Token::createMutualLinks(brackets2.top(), back); |
3925 | 0 | brackets2.pop(); |
3926 | 0 | } else if (back->str() == MatchCompiler::makeConstString(")")) { |
3927 | 0 | assert(brackets2.empty() == false); |
3928 | 0 | assert(brackets2.top()->str() == MatchCompiler::makeConstString("(")); |
3929 | 0 | Token::createMutualLinks(brackets2.top(), back); |
3930 | 0 | brackets2.pop(); |
3931 | 0 | } else if (back->str() == MatchCompiler::makeConstString("]")) { |
3932 | 0 | assert(brackets2.empty() == false); |
3933 | 0 | assert(brackets2.top()->str() == MatchCompiler::makeConstString("[")); |
3934 | 0 | Token::createMutualLinks(brackets2.top(), back); |
3935 | 0 | brackets2.pop(); |
3936 | 0 | } |
3937 | 0 | } |
3938 | 0 | } |
3939 | | |
3940 | 0 | tok5 = tok5->next(); |
3941 | 0 | } |
3942 | 0 | if (copy) { |
3943 | 0 | if (!templateDeclaration.scope().empty() && tok3->strAt(-1) != MatchCompiler::makeConstString("::")) |
3944 | 0 | addNamespace(templateDeclaration, tok3); |
3945 | 0 | mTokenList.addtoken(newName, tok3->linenr(), tok3->column(), tok3->fileIndex()); |
3946 | 0 | } |
3947 | |
|
3948 | 0 | while (tok3 && tok3->str() != MatchCompiler::makeConstString("::")) |
3949 | 0 | tok3 = tok3->next(); |
3950 | |
|
3951 | 0 | const auto it = std::find_if(mTemplateDeclarations.cbegin(), |
3952 | 0 | mTemplateDeclarations.cend(), |
3953 | 0 | FindToken(startOfTemplateDeclaration)); |
3954 | 0 | if (it != mTemplateDeclarations.cend()) |
3955 | 0 | mMemberFunctionsToDelete.push_back(*it); |
3956 | 0 | } |
3957 | | |
3958 | | // not part of template.. go on to next token |
3959 | 0 | else |
3960 | 0 | continue; |
3961 | | |
3962 | 0 | std::stack<Token *> brackets; // holds "(", "[" and "{" tokens |
3963 | | |
3964 | | // FIXME use full name matching somehow |
3965 | 0 | const std::string lastName = (templateInstantiation.name().find(' ') != std::string::npos) ? templateInstantiation.name().substr(templateInstantiation.name().rfind(' ')+1) : templateInstantiation.name(); |
3966 | |
|
3967 | 0 | std::stack<const Token *> templates; |
3968 | 0 | int scopeCount = 0; |
3969 | 0 | for (; tok3; tok3 = tok3->next()) { |
3970 | 0 | if (tok3->str() == MatchCompiler::makeConstString("{")) |
3971 | 0 | ++scopeCount; |
3972 | 0 | else if (tok3->str() == MatchCompiler::makeConstString("}")) |
3973 | 0 | --scopeCount; |
3974 | 0 | if (scopeCount < 0) |
3975 | 0 | break; |
3976 | 0 | if (tok3->isName() && !match100(tok3) && !tok3->isStandardType()) { |
3977 | | // search for this token in the type vector |
3978 | 0 | unsigned int itype = 0; |
3979 | 0 | while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != tok3->str()) |
3980 | 0 | ++itype; |
3981 | | |
3982 | | // replace type with given type.. |
3983 | 0 | if (itype < typeParametersInDeclaration.size() && itype < mTypesUsedInTemplateInstantiation.size()) { |
3984 | 0 | unsigned int typeindentlevel = 0; |
3985 | 0 | std::stack<Token *> brackets1; // holds "(" and "{" tokens |
3986 | 0 | Token * const beforeTypeToken = mTokenList.back(); |
3987 | 0 | bool pointerType = false; |
3988 | 0 | const bool isVariadicTemplateArg = templateDeclaration.isVariadic() && itype + 1 == typeParametersInDeclaration.size(); |
3989 | 0 | if (isVariadicTemplateArg && mTypesUsedInTemplateInstantiation.size() > 1 && !match45(tok3->next())) |
3990 | 0 | continue; |
3991 | 0 | if (isVariadicTemplateArg && match93(tok3)) |
3992 | 0 | tok3 = tok3->tokAt(2); |
3993 | 0 | const std::string endStr(isVariadicTemplateArg ? ">" : ",>"); |
3994 | 0 | for (Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); |
3995 | 0 | typetok && (typeindentlevel > 0 || endStr.find(typetok->str()[0]) == std::string::npos); |
3996 | 0 | typetok = typetok->next()) { |
3997 | 0 | if (typeindentlevel == 0 && typetok->str() == MatchCompiler::makeConstString("*")) |
3998 | 0 | pointerType = true; |
3999 | 0 | if (match45(typetok)) |
4000 | 0 | continue; |
4001 | 0 | if (match6(typetok) && |
4002 | 0 | (typetok->strAt(2) == MatchCompiler::makeConstString(">") || templateParameters(typetok->next()))) { |
4003 | 0 | brackets1.push(typetok->next()); |
4004 | 0 | ++typeindentlevel; |
4005 | 0 | } else if (typeindentlevel > 0 && typetok->str() == MatchCompiler::makeConstString(">") && brackets1.top()->str() == MatchCompiler::makeConstString("<")) { |
4006 | 0 | --typeindentlevel; |
4007 | 0 | brackets1.pop(); |
4008 | 0 | } else if (match101(typetok)) { |
4009 | 0 | brackets1.push(typetok->next()); |
4010 | 0 | ++typeindentlevel; |
4011 | 0 | } else if (typetok->str() == MatchCompiler::makeConstString("(")) |
4012 | 0 | ++typeindentlevel; |
4013 | 0 | else if (typetok->str() == MatchCompiler::makeConstString(")")) |
4014 | 0 | --typeindentlevel; |
4015 | 0 | Token *back; |
4016 | 0 | if (copy) { |
4017 | 0 | mTokenList.addtoken(typetok, tok3); |
4018 | 0 | back = mTokenList.back(); |
4019 | 0 | } else |
4020 | 0 | back = typetok; |
4021 | 0 | if (match71(back)) |
4022 | 0 | brackets1.push(back); |
4023 | 0 | else if (back->str() == MatchCompiler::makeConstString("}")) { |
4024 | 0 | assert(brackets1.empty() == false); |
4025 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("{")); |
4026 | 0 | if (copy) |
4027 | 0 | Token::createMutualLinks(brackets1.top(), back); |
4028 | 0 | brackets1.pop(); |
4029 | 0 | } else if (back->str() == MatchCompiler::makeConstString(")")) { |
4030 | 0 | assert(brackets1.empty() == false); |
4031 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("(")); |
4032 | 0 | if (copy) |
4033 | 0 | Token::createMutualLinks(brackets1.top(), back); |
4034 | 0 | brackets1.pop(); |
4035 | 0 | } else if (back->str() == MatchCompiler::makeConstString("]")) { |
4036 | 0 | assert(brackets1.empty() == false); |
4037 | 0 | assert(brackets1.top()->str() == MatchCompiler::makeConstString("[")); |
4038 | 0 | if (copy) |
4039 | 0 | Token::createMutualLinks(brackets1.top(), back); |
4040 | 0 | brackets1.pop(); |
4041 | 0 | } |
4042 | 0 | if (copy) |
4043 | 0 | back->isTemplateArg(true); |
4044 | 0 | } |
4045 | 0 | if (pointerType && match94(beforeTypeToken)) { |
4046 | 0 | mTokenList.addtoken(beforeTypeToken); |
4047 | 0 | beforeTypeToken->deleteThis(); |
4048 | 0 | } |
4049 | 0 | continue; |
4050 | 0 | } |
4051 | 0 | } |
4052 | | |
4053 | | // replace name.. |
4054 | 0 | if (tok3->str() == lastName) { |
4055 | 0 | if (match102(tok3->next())) { |
4056 | 0 | Token *closingBracket = tok3->next()->findClosingBracket(); |
4057 | 0 | if (closingBracket) { |
4058 | | // replace multi token name with single token name |
4059 | 0 | if (tok3 == templateDeclarationNameToken || |
4060 | 0 | Token::Match(tok3, newName.c_str())) { |
4061 | 0 | if (copy) { |
4062 | 0 | mTokenList.addtoken(newName, tok3); |
4063 | 0 | tok3 = closingBracket; |
4064 | 0 | } else { |
4065 | 0 | tok3->str(newName); |
4066 | 0 | eraseTokens(tok3, closingBracket->next()); |
4067 | 0 | } |
4068 | 0 | continue; |
4069 | 0 | } |
4070 | 0 | if (!templateDeclaration.scope().empty() && |
4071 | 0 | !alreadyHasNamespace(templateDeclaration, tok3) && |
4072 | 0 | !match103(closingBracket->next())) { |
4073 | 0 | if (copy) |
4074 | 0 | addNamespace(templateDeclaration, tok3); |
4075 | 0 | } |
4076 | 0 | } |
4077 | 0 | } else { |
4078 | | // don't modify friend |
4079 | 0 | if (match104(tok3->tokAt(-3))) { |
4080 | 0 | if (copy) |
4081 | 0 | mTokenList.addtoken(tok3); |
4082 | 0 | } else if (copy) { |
4083 | | // add namespace if necessary |
4084 | 0 | if (!templateDeclaration.scope().empty() && |
4085 | 0 | (isClass ? tok3->strAt(1) != MatchCompiler::makeConstString("(") : true)) { |
4086 | 0 | addNamespace(templateDeclaration, tok3); |
4087 | 0 | } |
4088 | 0 | mTokenList.addtoken(newName, tok3); |
4089 | 0 | } else if (!match105(tok3->next())) |
4090 | 0 | tok3->str(newName); |
4091 | 0 | continue; |
4092 | 0 | } |
4093 | 0 | } |
4094 | | |
4095 | | // copy |
4096 | 0 | if (copy) |
4097 | 0 | mTokenList.addtoken(tok3); |
4098 | | |
4099 | | // look for template definitions |
4100 | 0 | if (match40(tok3)) { |
4101 | 0 | Token * tok2 = findTemplateDeclarationEnd(tok3); |
4102 | 0 | if (tok2) |
4103 | 0 | templates.push(tok2); |
4104 | 0 | } else if (!templates.empty() && templates.top() == tok3) |
4105 | 0 | templates.pop(); |
4106 | |
|
4107 | 0 | if (match25(tok3) && |
4108 | 0 | !match106(tok3) && |
4109 | 0 | match107(tok3->next()->findClosingBracket())) { |
4110 | 0 | const Token *closingBracket = tok3->next()->findClosingBracket(); |
4111 | 0 | if (match108(closingBracket->next())) { |
4112 | 0 | int num = 0; |
4113 | 0 | const Token *par = tok3->next(); |
4114 | 0 | while (num < typeParametersInDeclaration.size() && par != closingBracket) { |
4115 | 0 | const std::string pattern("[<,] " + typeParametersInDeclaration[num]->str() + " [,>]"); |
4116 | 0 | if (!Token::Match(par, pattern.c_str())) |
4117 | 0 | break; |
4118 | 0 | ++num; |
4119 | 0 | par = par->tokAt(2); |
4120 | 0 | } |
4121 | 0 | if (num < typeParametersInDeclaration.size() || par != closingBracket) |
4122 | 0 | continue; |
4123 | 0 | } |
4124 | | |
4125 | | // don't add instantiations in template definitions |
4126 | 0 | if (!templates.empty()) |
4127 | 0 | continue; |
4128 | | |
4129 | 0 | std::string scope; |
4130 | 0 | const Token *prev = tok3; |
4131 | 0 | for (; match16(prev->tokAt(-2)); prev = prev->tokAt(-2)) { |
4132 | 0 | if (scope.empty()) |
4133 | 0 | scope = prev->strAt(-2); |
4134 | 0 | else |
4135 | 0 | scope = prev->strAt(-2) + " :: " + scope; |
4136 | 0 | } |
4137 | | |
4138 | | // check for global scope |
4139 | 0 | if (prev->strAt(-1) != MatchCompiler::makeConstString("::")) { |
4140 | | // adjust for current scope |
4141 | 0 | std::string token_scope = tok3->scopeInfo()->name; |
4142 | 0 | const std::string::size_type end = token_scope.find_last_of(" :: "); |
4143 | 0 | if (end != std::string::npos) { |
4144 | 0 | token_scope.resize(end); |
4145 | 0 | if (scope.empty()) |
4146 | 0 | scope = std::move(token_scope); |
4147 | 0 | else |
4148 | 0 | scope = token_scope + " :: " + scope; |
4149 | 0 | } |
4150 | 0 | } |
4151 | |
|
4152 | 0 | if (copy) |
4153 | 0 | newInstantiations.emplace_back(mTokenList.back(), std::move(scope)); |
4154 | 0 | else if (!inTemplateDefinition) |
4155 | 0 | newInstantiations.emplace_back(tok3, std::move(scope)); |
4156 | 0 | } |
4157 | | |
4158 | | // link() newly tokens manually |
4159 | 0 | else if (copy) { |
4160 | 0 | if (tok3->str() == MatchCompiler::makeConstString("{")) { |
4161 | 0 | brackets.push(mTokenList.back()); |
4162 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString("(")) { |
4163 | 0 | brackets.push(mTokenList.back()); |
4164 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString("[")) { |
4165 | 0 | brackets.push(mTokenList.back()); |
4166 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString("}")) { |
4167 | 0 | assert(brackets.empty() == false); |
4168 | 0 | assert(brackets.top()->str() == MatchCompiler::makeConstString("{")); |
4169 | 0 | Token::createMutualLinks(brackets.top(), mTokenList.back()); |
4170 | 0 | brackets.pop(); |
4171 | 0 | if (brackets.empty() && !match109(tok3)) { |
4172 | 0 | inTemplateDefinition = false; |
4173 | 0 | if (isClass && tok3->strAt(1) == MatchCompiler::makeConstString(";")) { |
4174 | 0 | const Token* tokSemicolon = tok3->next(); |
4175 | 0 | mTokenList.addtoken(tokSemicolon, tokSemicolon->linenr(), tokSemicolon->column(), tokSemicolon->fileIndex()); |
4176 | 0 | } |
4177 | 0 | break; |
4178 | 0 | } |
4179 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString(")")) { |
4180 | 0 | assert(brackets.empty() == false); |
4181 | 0 | assert(brackets.top()->str() == MatchCompiler::makeConstString("(")); |
4182 | 0 | Token::createMutualLinks(brackets.top(), mTokenList.back()); |
4183 | 0 | brackets.pop(); |
4184 | 0 | } else if (tok3->str() == MatchCompiler::makeConstString("]")) { |
4185 | 0 | assert(brackets.empty() == false); |
4186 | 0 | assert(brackets.top()->str() == MatchCompiler::makeConstString("[")); |
4187 | 0 | Token::createMutualLinks(brackets.top(), mTokenList.back()); |
4188 | 0 | brackets.pop(); |
4189 | 0 | } |
4190 | 0 | } |
4191 | 0 | } |
4192 | | |
4193 | 0 | assert(brackets.empty()); |
4194 | 0 | } |
4195 | | |
4196 | | // add new instantiations |
4197 | 0 | for (const auto & inst : newInstantiations) { |
4198 | 0 | if (!inst.token) |
4199 | 0 | continue; |
4200 | 0 | simplifyTemplateArgs(inst.token->tokAt(2), inst.token->next()->findClosingBracket(), &newInstantiations); |
4201 | | // only add recursive instantiation if its arguments are a constant expression |
4202 | 0 | if (templateDeclaration.name() != inst.token->str() || |
4203 | 0 | (inst.token->tokAt(2)->isNumber() || inst.token->tokAt(2)->isStandardType())) |
4204 | 0 | mTemplateInstantiations.emplace_back(inst.token, inst.scope); |
4205 | 0 | } |
4206 | 0 | } |
4207 | | |
4208 | | static bool isLowerThanLogicalAnd(const Token *lower) |
4209 | 0 | { |
4210 | 0 | return lower->isAssignmentOp() || match110(lower); |
4211 | 0 | } |
4212 | | static bool isLowerThanOr(const Token* lower) |
4213 | 0 | { |
4214 | 0 | return isLowerThanLogicalAnd(lower) || lower->str() == MatchCompiler::makeConstString("&&"); |
4215 | 0 | } |
4216 | | static bool isLowerThanXor(const Token* lower) |
4217 | 0 | { |
4218 | 0 | return isLowerThanOr(lower) || lower->str() == MatchCompiler::makeConstString("|"); |
4219 | 0 | } |
4220 | | static bool isLowerThanAnd(const Token* lower) |
4221 | 0 | { |
4222 | 0 | return isLowerThanXor(lower) || lower->str() == MatchCompiler::makeConstString("^"); |
4223 | 0 | } |
4224 | | static bool isLowerThanShift(const Token* lower) |
4225 | 0 | { |
4226 | 0 | return isLowerThanAnd(lower) || lower->str() == MatchCompiler::makeConstString("&"); |
4227 | 0 | } |
4228 | | static bool isLowerThanPlusMinus(const Token* lower) |
4229 | 0 | { |
4230 | 0 | return isLowerThanShift(lower) || match111(lower); |
4231 | 0 | } |
4232 | | static bool isLowerThanMulDiv(const Token* lower) |
4233 | 0 | { |
4234 | 0 | return isLowerThanPlusMinus(lower) || match112(lower); |
4235 | 0 | } |
4236 | | static bool isLowerEqualThanMulDiv(const Token* lower) |
4237 | 0 | { |
4238 | 0 | return isLowerThanMulDiv(lower) || match113(lower); |
4239 | 0 | } |
4240 | | |
4241 | | |
4242 | | bool TemplateSimplifier::simplifyNumericCalculations(Token *tok, bool isTemplate) |
4243 | 0 | { |
4244 | 0 | bool ret = false; |
4245 | | // (1-2) |
4246 | 0 | while (tok->tokAt(3) && tok->isNumber() && tok->tokAt(2)->isNumber()) { // %any% %num% %any% %num% %any% |
4247 | 0 | const Token *before = tok->previous(); |
4248 | 0 | if (!before) |
4249 | 0 | break; |
4250 | 0 | const Token* op = tok->next(); |
4251 | 0 | const Token* after = tok->tokAt(3); |
4252 | 0 | const std::string &num1 = op->strAt(-1); |
4253 | 0 | const std::string &num2 = op->strAt(1); |
4254 | 0 | if (match114(before) && (num2 != MatchCompiler::makeConstString("0")) && num1 == MathLib::multiply(num2, MathLib::divide(num1, num2))) { |
4255 | | // Division where result is a whole number |
4256 | 0 | } else if (!((op->str() == MatchCompiler::makeConstString("*") && (isLowerThanMulDiv(before) || before->str() == MatchCompiler::makeConstString("*")) && isLowerEqualThanMulDiv(after)) || // associative |
4257 | 0 | (match115(op) && isLowerThanMulDiv(before) && isLowerEqualThanMulDiv(after)) || // NOT associative |
4258 | 0 | (match116(op) && isLowerThanMulDiv(before) && isLowerThanMulDiv(after)) || // Only partially (+) associative, but handled later |
4259 | 0 | (match117(op) && isLowerThanShift(before) && isLowerThanPlusMinus(after)) || // NOT associative |
4260 | 0 | (op->str() == MatchCompiler::makeConstString("&") && isLowerThanShift(before) && isLowerThanShift(after)) || // associative |
4261 | 0 | (op->str() == MatchCompiler::makeConstString("^") && isLowerThanAnd(before) && isLowerThanAnd(after)) || // associative |
4262 | 0 | (op->str() == MatchCompiler::makeConstString("|") && isLowerThanXor(before) && isLowerThanXor(after)) || // associative |
4263 | 0 | (op->str() == MatchCompiler::makeConstString("&&") && isLowerThanOr(before) && isLowerThanOr(after)) || |
4264 | 0 | (op->str() == MatchCompiler::makeConstString("||") && isLowerThanLogicalAnd(before) && isLowerThanLogicalAnd(after)))) |
4265 | 0 | break; |
4266 | | |
4267 | | // Don't simplify "%num% / 0" |
4268 | 0 | if (match118(op)) { |
4269 | 0 | if (isTemplate) |
4270 | 0 | throw InternalError(op, "Instantiation error: Divide by zero in template instantiation.", InternalError::INSTANTIATION); |
4271 | 0 | return ret; |
4272 | 0 | } |
4273 | | |
4274 | | // Integer operations |
4275 | 0 | if (match119(op)) { |
4276 | | // Don't simplify if operand is negative, shifting with negative |
4277 | | // operand is UB. Bitmasking with negative operand is implementation |
4278 | | // defined behaviour. |
4279 | 0 | if (MathLib::isNegative(num1) || MathLib::isNegative(num2)) |
4280 | 0 | break; |
4281 | | |
4282 | 0 | const MathLib::value v1(num1); |
4283 | 0 | const MathLib::value v2(num2); |
4284 | |
|
4285 | 0 | if (!v1.isInt() || !v2.isInt()) |
4286 | 0 | break; |
4287 | | |
4288 | 0 | switch (op->str()[0]) { |
4289 | 0 | case '<': |
4290 | 0 | tok->str((v1 << v2).str()); |
4291 | 0 | break; |
4292 | 0 | case '>': |
4293 | 0 | tok->str((v1 >> v2).str()); |
4294 | 0 | break; |
4295 | 0 | case '&': |
4296 | 0 | tok->str((v1 & v2).str()); |
4297 | 0 | break; |
4298 | 0 | case '|': |
4299 | 0 | tok->str((v1 | v2).str()); |
4300 | 0 | break; |
4301 | 0 | case '^': |
4302 | 0 | tok->str((v1 ^ v2).str()); |
4303 | 0 | break; |
4304 | 0 | } |
4305 | 0 | } |
4306 | | |
4307 | | // Logical operations |
4308 | 0 | else if (match120(op)) { |
4309 | 0 | const bool op1 = !MathLib::isNullValue(num1); |
4310 | 0 | const bool op2 = !MathLib::isNullValue(num2); |
4311 | 0 | const bool result = (op->str() == MatchCompiler::makeConstString("||")) ? (op1 || op2) : (op1 && op2); |
4312 | 0 | tok->str(result ? "1" : "0"); |
4313 | 0 | } |
4314 | | |
4315 | 0 | else if (match121(tok->previous())) |
4316 | 0 | tok->str(MathLib::add(num1, num2)); |
4317 | 0 | else if (match122(tok->previous())) |
4318 | 0 | tok->str(MathLib::subtract(num1, num2)); |
4319 | 0 | else { |
4320 | 0 | try { |
4321 | 0 | tok->str(MathLib::calculate(num1, num2, op->str()[0])); |
4322 | 0 | } catch (InternalError &e) { |
4323 | 0 | e.token = tok; |
4324 | 0 | throw; |
4325 | 0 | } |
4326 | 0 | } |
4327 | | |
4328 | 0 | tok->deleteNext(2); |
4329 | |
|
4330 | 0 | ret = true; |
4331 | 0 | } |
4332 | | |
4333 | 0 | return ret; |
4334 | 0 | } |
4335 | | |
4336 | | static Token *skipTernaryOp(Token *tok, const Token *backToken) |
4337 | 0 | { |
4338 | 0 | unsigned int colonLevel = 1; |
4339 | 0 | while (nullptr != (tok = tok->next())) { |
4340 | 0 | if (tok->str() == MatchCompiler::makeConstString("?")) { |
4341 | 0 | ++colonLevel; |
4342 | 0 | } else if (tok->str() == MatchCompiler::makeConstString(":")) { |
4343 | 0 | --colonLevel; |
4344 | 0 | if (colonLevel == 0) { |
4345 | 0 | tok = tok->next(); |
4346 | 0 | break; |
4347 | 0 | } |
4348 | 0 | } |
4349 | 0 | if (tok->link() && tok->str() == MatchCompiler::makeConstString("(")) |
4350 | 0 | tok = tok->link(); |
4351 | 0 | else if (match123(tok->next()) || tok->next() == backToken) |
4352 | 0 | break; |
4353 | 0 | } |
4354 | 0 | if (colonLevel > 0) // Ticket #5214: Make sure the ':' matches the proper '?' |
4355 | 0 | return nullptr; |
4356 | 0 | return tok; |
4357 | 0 | } |
4358 | | |
4359 | 0 | static void invalidateInst(const Token* beg, const Token* end, std::vector<newInstantiation>* newInst) { |
4360 | 0 | if (!newInst) |
4361 | 0 | return; |
4362 | 0 | for (auto& inst : *newInst) { |
4363 | 0 | for (const Token* tok = beg; tok != end; tok = tok->next()) |
4364 | 0 | if (inst.token == tok) { |
4365 | 0 | inst.token = nullptr; |
4366 | 0 | break; |
4367 | 0 | } |
4368 | 0 | } |
4369 | 0 | } |
4370 | | |
4371 | | void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end, std::vector<newInstantiation>* newInst) |
4372 | 0 | { |
4373 | | // start could be erased so use the token before start if available |
4374 | 0 | Token * first = (start && start->previous()) ? start->previous() : mTokenList.front(); |
4375 | 0 | bool again = true; |
4376 | |
|
4377 | 0 | while (again) { |
4378 | 0 | again = false; |
4379 | |
|
4380 | 0 | for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) { |
4381 | 0 | if (tok->str() == MatchCompiler::makeConstString("sizeof")) { |
4382 | | // sizeof('x') |
4383 | 0 | if (match124(tok->next())) { |
4384 | 0 | tok->deleteNext(); |
4385 | 0 | tok->deleteThis(); |
4386 | 0 | tok->deleteNext(); |
4387 | 0 | tok->str(std::to_string(1)); |
4388 | 0 | again = true; |
4389 | 0 | } |
4390 | | |
4391 | | // sizeof ("text") |
4392 | 0 | else if (match125(tok->next())) { |
4393 | 0 | tok->deleteNext(); |
4394 | 0 | tok->deleteThis(); |
4395 | 0 | tok->deleteNext(); |
4396 | 0 | tok->str(std::to_string(Token::getStrLength(tok) + 1)); |
4397 | 0 | again = true; |
4398 | 0 | } |
4399 | | |
4400 | 0 | else if (match126(tok->next())) { |
4401 | 0 | tok->str(std::to_string(mTokenizer.sizeOfType(tok->tokAt(3)))); |
4402 | 0 | tok->deleteNext(4); |
4403 | 0 | again = true; |
4404 | 0 | } else if (match127(tok->next())) { |
4405 | 0 | tok->str(std::to_string(mTokenizer.sizeOfType(tok->tokAt(2)))); |
4406 | 0 | tok->deleteNext(3); |
4407 | 0 | again = true; |
4408 | 0 | } else if (match128(tok->next())) { |
4409 | 0 | const unsigned int size = mTokenizer.sizeOfType(tok->tokAt(2)); |
4410 | 0 | if (size > 0) { |
4411 | 0 | tok->str(std::to_string(size)); |
4412 | 0 | tok->deleteNext(3); |
4413 | 0 | again = true; |
4414 | 0 | } |
4415 | 0 | } else if (tok->strAt(1) == MatchCompiler::makeConstString("(")) { |
4416 | 0 | tok = tok->linkAt(1); |
4417 | 0 | } |
4418 | 0 | } else if (match129(tok) && |
4419 | 0 | MathLib::isInt(tok->str()) && |
4420 | 0 | MathLib::isInt(tok->strAt(2))) { |
4421 | 0 | if ((match130(tok->previous()) || tok == start) && |
4422 | 0 | (match131(tok->tokAt(3)) || tok->tokAt(3) == end)) { |
4423 | 0 | const MathLib::bigint op1(MathLib::toBigNumber(tok)); |
4424 | 0 | const std::string &cmp(tok->strAt(1)); |
4425 | 0 | const MathLib::bigint op2(MathLib::toBigNumber(tok->tokAt(2))); |
4426 | |
|
4427 | 0 | std::string result; |
4428 | |
|
4429 | 0 | if (cmp == MatchCompiler::makeConstString("==")) |
4430 | 0 | result = bool_to_string(op1 == op2); |
4431 | 0 | else if (cmp == MatchCompiler::makeConstString("!=")) |
4432 | 0 | result = bool_to_string(op1 != op2); |
4433 | 0 | else if (cmp == MatchCompiler::makeConstString("<=")) |
4434 | 0 | result = bool_to_string(op1 <= op2); |
4435 | 0 | else if (cmp == MatchCompiler::makeConstString(">=")) |
4436 | 0 | result = bool_to_string(op1 >= op2); |
4437 | 0 | else if (cmp == MatchCompiler::makeConstString("<")) |
4438 | 0 | result = bool_to_string(op1 < op2); |
4439 | 0 | else |
4440 | 0 | result = bool_to_string(op1 > op2); |
4441 | |
|
4442 | 0 | tok->str(result); |
4443 | 0 | tok->deleteNext(2); |
4444 | 0 | again = true; |
4445 | 0 | tok = tok->previous(); |
4446 | 0 | } |
4447 | 0 | } |
4448 | 0 | } |
4449 | |
|
4450 | 0 | if (simplifyCalculations(first->next(), end)) |
4451 | 0 | again = true; |
4452 | |
|
4453 | 0 | for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) { |
4454 | 0 | if (tok->str() == MatchCompiler::makeConstString("?") && |
4455 | 0 | ((tok->previous()->isNumber() || tok->previous()->isBoolean()) || |
4456 | 0 | match132(tok->tokAt(-3)))) { |
4457 | 0 | const int offset = (tok->strAt(-1) == MatchCompiler::makeConstString(")")) ? 2 : 1; |
4458 | | |
4459 | | // Find the token ":" then go to the next token |
4460 | 0 | Token *colon = skipTernaryOp(tok, end); |
4461 | 0 | if (!colon || colon->strAt(-1) != MatchCompiler::makeConstString(":") || !colon->next()) |
4462 | 0 | continue; |
4463 | | |
4464 | | //handle the GNU extension: "x ? : y" <-> "x ? x : y" |
4465 | 0 | if (colon->previous() == tok->next()) |
4466 | 0 | tok->insertToken(tok->strAt(-offset)); |
4467 | | |
4468 | | // go back before the condition, if possible |
4469 | 0 | tok = tok->tokAt(-2); |
4470 | 0 | if (offset == 2) { |
4471 | | // go further back before the "(" |
4472 | 0 | tok = tok->tokAt(-2); |
4473 | | //simplify the parentheses |
4474 | 0 | tok->deleteNext(); |
4475 | 0 | tok->next()->deleteNext(); |
4476 | 0 | } |
4477 | |
|
4478 | 0 | if (match133(tok->next())) { |
4479 | 0 | invalidateInst(tok->next(), colon, newInst); |
4480 | | // Use code after colon, remove code before it. |
4481 | 0 | Token::eraseTokens(tok, colon); |
4482 | |
|
4483 | 0 | tok = tok->next(); |
4484 | 0 | again = true; |
4485 | 0 | } |
4486 | | |
4487 | | // The condition is true. Delete the operator after the ":".. |
4488 | 0 | else { |
4489 | | // delete the condition token and the "?" |
4490 | 0 | tok->deleteNext(2); |
4491 | |
|
4492 | 0 | unsigned int ternaryOplevel = 0; |
4493 | 0 | for (const Token *endTok = colon; endTok; endTok = endTok->next()) { |
4494 | 0 | if (match74(endTok)) |
4495 | 0 | endTok = endTok->link(); |
4496 | 0 | else if (endTok->str() == MatchCompiler::makeConstString("<") && (endTok->strAt(1) == MatchCompiler::makeConstString(">") || templateParameters(endTok))) |
4497 | 0 | endTok = endTok->findClosingBracket(); |
4498 | 0 | else if (endTok->str() == MatchCompiler::makeConstString("?")) |
4499 | 0 | ++ternaryOplevel; |
4500 | 0 | else if (match134(endTok)) { |
4501 | 0 | if (endTok->str() == MatchCompiler::makeConstString(":") && ternaryOplevel) |
4502 | 0 | --ternaryOplevel; |
4503 | 0 | else if (endTok->str() == MatchCompiler::makeConstString(">") && !end) |
4504 | 0 | ; |
4505 | 0 | else { |
4506 | 0 | invalidateInst(colon->tokAt(-1), endTok, newInst); |
4507 | 0 | Token::eraseTokens(colon->tokAt(-2), endTok); |
4508 | 0 | again = true; |
4509 | 0 | break; |
4510 | 0 | } |
4511 | 0 | } |
4512 | 0 | } |
4513 | 0 | } |
4514 | 0 | } |
4515 | 0 | } |
4516 | |
|
4517 | 0 | for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) { |
4518 | 0 | if (match135(tok) && |
4519 | 0 | (tok->previous() && !tok->previous()->isName())) { |
4520 | 0 | tok->deleteThis(); |
4521 | 0 | tok->deleteNext(); |
4522 | 0 | again = true; |
4523 | 0 | } |
4524 | 0 | } |
4525 | 0 | } |
4526 | 0 | } |
4527 | | |
4528 | | static bool validTokenStart(bool bounded, const Token *tok, const Token *frontToken, int offset) |
4529 | 0 | { |
4530 | 0 | if (!bounded) |
4531 | 0 | return true; |
4532 | | |
4533 | 0 | if (frontToken) |
4534 | 0 | frontToken = frontToken->previous(); |
4535 | |
|
4536 | 0 | while (tok && offset <= 0) { |
4537 | 0 | if (tok == frontToken) |
4538 | 0 | return false; |
4539 | 0 | ++offset; |
4540 | 0 | tok = tok->previous(); |
4541 | 0 | } |
4542 | | |
4543 | 0 | return tok && offset > 0; |
4544 | 0 | } |
4545 | | |
4546 | | static bool validTokenEnd(bool bounded, const Token *tok, const Token *backToken, int offset) |
4547 | 0 | { |
4548 | 0 | if (!bounded) |
4549 | 0 | return true; |
4550 | | |
4551 | 0 | while (tok && offset >= 0) { |
4552 | 0 | if (tok == backToken) |
4553 | 0 | return false; |
4554 | 0 | --offset; |
4555 | 0 | tok = tok->next(); |
4556 | 0 | } |
4557 | | |
4558 | 0 | return tok && offset < 0; |
4559 | 0 | } |
4560 | | |
4561 | | // TODO: This is not the correct class for simplifyCalculations(), so it |
4562 | | // should be moved away. |
4563 | | bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *backToken, bool isTemplate) |
4564 | 0 | { |
4565 | 0 | bool ret = false; |
4566 | 0 | const bool bounded = frontToken || backToken; |
4567 | 0 | if (!frontToken) { |
4568 | 0 | frontToken = mTokenList.front(); |
4569 | 0 | } |
4570 | 0 | for (Token *tok = frontToken; tok && tok != backToken; tok = tok->next()) { |
4571 | | // Remove parentheses around variable.. |
4572 | | // keep parentheses here: dynamic_cast<Fred *>(p); |
4573 | | // keep parentheses here: A operator * (int); |
4574 | | // keep parentheses here: int ( * ( * f ) ( ... ) ) (int) ; |
4575 | | // keep parentheses here: int ( * * ( * compilerHookVector ) (void) ) ( ) ; |
4576 | | // keep parentheses here: operator new [] (size_t); |
4577 | | // keep parentheses here: Functor()(a ... ) |
4578 | | // keep parentheses here: ) ( var ) ; |
4579 | 0 | if (validTokenEnd(bounded, tok, backToken, 4) && |
4580 | 0 | (match136(tok->next()) || |
4581 | 0 | (match137(tok->next()) && |
4582 | 0 | (tok->tokAt(2)->varId()>0 || |
4583 | 0 | !match138(tok->tokAt(4))))) && |
4584 | 0 | !tok->isName() && |
4585 | 0 | tok->str() != MatchCompiler::makeConstString(">") && |
4586 | 0 | tok->str() != MatchCompiler::makeConstString(")") && |
4587 | 0 | tok->str() != MatchCompiler::makeConstString("]")) { |
4588 | 0 | tok->deleteNext(); |
4589 | 0 | tok = tok->next(); |
4590 | 0 | tok->deleteNext(); |
4591 | 0 | ret = true; |
4592 | 0 | } |
4593 | |
|
4594 | 0 | if (validTokenEnd(bounded, tok, backToken, 3) && |
4595 | 0 | match139(tok->previous())) { |
4596 | 0 | tok->str(MathLib::toString(MathLib::toBigNumber(tok))); |
4597 | 0 | } |
4598 | |
|
4599 | 0 | if (validTokenEnd(bounded, tok, backToken, 5) && |
4600 | 0 | match140(tok)) { |
4601 | 0 | tok->deleteThis(); |
4602 | 0 | tok->deleteThis(); |
4603 | 0 | tok->deleteNext(); |
4604 | 0 | tok->deleteNext(); |
4605 | 0 | tok->deleteNext(); |
4606 | 0 | ret = true; |
4607 | 0 | } |
4608 | |
|
4609 | 0 | if (validTokenEnd(bounded, tok, backToken, 3) && |
4610 | 0 | match141(tok)) { |
4611 | 0 | tok->deleteThis(); |
4612 | 0 | tok->deleteThis(); |
4613 | 0 | if (tok->isBoolean()) |
4614 | 0 | tok->str("bool"); |
4615 | 0 | else if (MathLib::isFloat(tok->str())) { |
4616 | | // MathLib::getSuffix doesn't work for floating point numbers |
4617 | 0 | const char suffix = tok->str().back(); |
4618 | 0 | if (suffix == 'f' || suffix == 'F') |
4619 | 0 | tok->str("float"); |
4620 | 0 | else if (suffix == 'l' || suffix == 'L') { |
4621 | 0 | tok->str("double"); |
4622 | 0 | tok->isLong(true); |
4623 | 0 | } else |
4624 | 0 | tok->str("double"); |
4625 | 0 | } else if (MathLib::isInt(tok->str())) { |
4626 | 0 | std::string suffix = MathLib::getSuffix(tok->str()); |
4627 | 0 | if (suffix.find("LL") != std::string::npos) { |
4628 | 0 | tok->str("long"); |
4629 | 0 | tok->isLong(true); |
4630 | 0 | } else if (suffix.find('L') != std::string::npos) |
4631 | 0 | tok->str("long"); |
4632 | 0 | else |
4633 | 0 | tok->str("int"); |
4634 | 0 | tok->isUnsigned(suffix.find('U') != std::string::npos); |
4635 | 0 | } |
4636 | 0 | tok->deleteNext(); |
4637 | 0 | ret = true; |
4638 | 0 | } |
4639 | |
|
4640 | 0 | if (validTokenEnd(bounded, tok, backToken, 2) && |
4641 | 0 | (match142(tok) || |
4642 | 0 | match143(tok))) { |
4643 | 0 | tok->str("0"); // FIXME add type suffix |
4644 | 0 | tok->isSigned(false); |
4645 | 0 | tok->isUnsigned(false); |
4646 | 0 | tok->isLong(false); |
4647 | 0 | tok->deleteNext(); |
4648 | 0 | tok->deleteNext(); |
4649 | 0 | ret = true; |
4650 | 0 | } |
4651 | |
|
4652 | 0 | if (tok && tok->isNumber()) { |
4653 | 0 | if (validTokenEnd(bounded, tok, backToken, 2) && |
4654 | 0 | simplifyNumericCalculations(tok, isTemplate)) { |
4655 | 0 | ret = true; |
4656 | 0 | Token *prev = tok->tokAt(-2); |
4657 | 0 | while (validTokenStart(bounded, tok, frontToken, -2) && |
4658 | 0 | prev && simplifyNumericCalculations(prev, isTemplate)) { |
4659 | 0 | tok = prev; |
4660 | 0 | prev = prev->tokAt(-2); |
4661 | 0 | } |
4662 | 0 | } |
4663 | | |
4664 | | // Remove redundant conditions (0&&x) (1||x) |
4665 | 0 | if (validTokenStart(bounded, tok, frontToken, -1) && |
4666 | 0 | validTokenEnd(bounded, tok, backToken, 1) && |
4667 | 0 | (match144(tok->previous()) || |
4668 | 0 | match145(tok->previous()))) { |
4669 | 0 | unsigned int par = 0; |
4670 | 0 | const Token *tok2 = tok; |
4671 | 0 | const bool andAnd = (tok->strAt(1) == MatchCompiler::makeConstString("&&")); |
4672 | 0 | for (; tok2; tok2 = tok2->next()) { |
4673 | 0 | if (tok2->str() == MatchCompiler::makeConstString("(") || tok2->str() == MatchCompiler::makeConstString("[")) |
4674 | 0 | ++par; |
4675 | 0 | else if (tok2->str() == MatchCompiler::makeConstString(")") || tok2->str() == MatchCompiler::makeConstString("]")) { |
4676 | 0 | if (par == 0) |
4677 | 0 | break; |
4678 | 0 | --par; |
4679 | 0 | } else if (par == 0 && isLowerThanLogicalAnd(tok2) && (andAnd || tok2->str() != MatchCompiler::makeConstString("||"))) |
4680 | 0 | break; |
4681 | 0 | } |
4682 | 0 | if (tok2) { |
4683 | 0 | eraseTokens(tok, tok2); |
4684 | 0 | ret = true; |
4685 | 0 | } |
4686 | 0 | continue; |
4687 | 0 | } |
4688 | | |
4689 | 0 | if (tok->str() == MatchCompiler::makeConstString("0") && validTokenStart(bounded, tok, frontToken, -1)) { |
4690 | 0 | if (validTokenEnd(bounded, tok, backToken, 1) && |
4691 | 0 | ((match146(tok->previous()) && isLowerThanMulDiv(tok->next())) || |
4692 | 0 | (match147(tok->previous()) && isLowerThanXor(tok->next())))) { |
4693 | 0 | tok = tok->previous(); |
4694 | 0 | if (match148(tok->tokAt(-4)) && |
4695 | 0 | tok->strAt(-3) == tok->strAt(-1)) { |
4696 | 0 | tok = tok->tokAt(-4); |
4697 | 0 | tok->deleteNext(5); |
4698 | 0 | } else { |
4699 | 0 | tok = tok->previous(); |
4700 | 0 | tok->deleteNext(2); |
4701 | 0 | } |
4702 | 0 | ret = true; |
4703 | 0 | } else if (validTokenEnd(bounded, tok, backToken, 1) && |
4704 | 0 | (match149(tok->previous()) || |
4705 | 0 | match150(tok->previous()))) { |
4706 | 0 | tok = tok->previous(); |
4707 | 0 | tok->deleteNext(2); |
4708 | 0 | ret = true; |
4709 | 0 | } else if ((((match151(tok->previous()) || |
4710 | 0 | match152(tok->previous())) && |
4711 | 0 | validTokenEnd(bounded, tok, backToken, 3)) || |
4712 | 0 | (((match153(tok->previous()) || |
4713 | 0 | match154(tok->previous())) && |
4714 | 0 | validTokenEnd(bounded, tok, backToken, 2))))) { |
4715 | 0 | tok->deleteNext(); |
4716 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("(")) |
4717 | 0 | eraseTokens(tok, tok->linkAt(1)); |
4718 | 0 | tok->deleteNext(); |
4719 | 0 | ret = true; |
4720 | 0 | } else if (validTokenEnd(bounded, tok, backToken, 4) && |
4721 | 0 | (match155(tok->previous()) || |
4722 | 0 | match156(tok->previous()))) { |
4723 | 0 | tok->deleteNext(); |
4724 | 0 | tok->deleteNext(); |
4725 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("(")) |
4726 | 0 | eraseTokens(tok, tok->linkAt(1)); |
4727 | 0 | tok->deleteNext(); |
4728 | 0 | ret = true; |
4729 | 0 | } |
4730 | 0 | } |
4731 | |
|
4732 | 0 | if (tok->str() == MatchCompiler::makeConstString("1") && validTokenStart(bounded, tok, frontToken, -1)) { |
4733 | 0 | if (validTokenEnd(bounded, tok, backToken, 3) && |
4734 | 0 | (match157(tok->previous()) || |
4735 | 0 | match158(tok->previous()))) { |
4736 | 0 | tok->deleteNext(); |
4737 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("(")) |
4738 | 0 | eraseTokens(tok, tok->linkAt(1)); |
4739 | 0 | tok->deleteNext(); |
4740 | 0 | ret = true; |
4741 | 0 | } else if (validTokenEnd(bounded, tok, backToken, 4) && |
4742 | 0 | (match159(tok->previous()) || |
4743 | 0 | match160(tok->previous()))) { |
4744 | 0 | tok->deleteNext(); |
4745 | 0 | tok->deleteNext(); |
4746 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("(")) |
4747 | 0 | eraseTokens(tok, tok->linkAt(1)); |
4748 | 0 | tok->deleteNext(); |
4749 | 0 | ret = true; |
4750 | 0 | } |
4751 | 0 | } |
4752 | |
|
4753 | 0 | if ((match161(tok->tokAt(-2)) && |
4754 | 0 | validTokenStart(bounded, tok, frontToken, -2)) || |
4755 | 0 | (match162(tok->previous()) && |
4756 | 0 | validTokenStart(bounded, tok, frontToken, -1))) { |
4757 | 0 | tok = tok->previous(); |
4758 | 0 | if (tok->str() == MatchCompiler::makeConstString("*")) |
4759 | 0 | tok = tok->previous(); |
4760 | 0 | tok->deleteNext(2); |
4761 | 0 | ret = true; |
4762 | 0 | } |
4763 | | |
4764 | | // Remove parentheses around number.. |
4765 | 0 | if (validTokenStart(bounded, tok, frontToken, -2) && |
4766 | 0 | match163(tok->tokAt(-2)) && |
4767 | 0 | tok->strAt(-2) != MatchCompiler::makeConstString(">")) { |
4768 | 0 | tok = tok->previous(); |
4769 | 0 | tok->deleteThis(); |
4770 | 0 | tok->deleteNext(); |
4771 | 0 | ret = true; |
4772 | 0 | } |
4773 | |
|
4774 | 0 | if (validTokenStart(bounded, tok, frontToken, -1) && |
4775 | 0 | validTokenEnd(bounded, tok, backToken, 1) && |
4776 | 0 | (match164(tok->previous()) || |
4777 | 0 | match165(tok->previous()))) { |
4778 | 0 | tok = tok->previous(); |
4779 | 0 | if (match166(tok)) |
4780 | 0 | tok = tok->previous(); |
4781 | 0 | tok->deleteNext(2); |
4782 | 0 | ret = true; |
4783 | 0 | } |
4784 | |
|
4785 | 0 | if (validTokenEnd(bounded, tok, backToken, 2) && |
4786 | 0 | match129(tok) && |
4787 | 0 | MathLib::isInt(tok->str()) && |
4788 | 0 | MathLib::isInt(tok->strAt(2))) { |
4789 | 0 | if (validTokenStart(bounded, tok, frontToken, -1) && |
4790 | 0 | match167(tok->previous()) && |
4791 | 0 | match131(tok->tokAt(3))) { |
4792 | 0 | const MathLib::bigint op1(MathLib::toBigNumber(tok)); |
4793 | 0 | const std::string &cmp(tok->strAt(1)); |
4794 | 0 | const MathLib::bigint op2(MathLib::toBigNumber(tok->tokAt(2))); |
4795 | |
|
4796 | 0 | std::string result; |
4797 | |
|
4798 | 0 | if (cmp == MatchCompiler::makeConstString("==")) |
4799 | 0 | result = (op1 == op2) ? "1" : "0"; |
4800 | 0 | else if (cmp == MatchCompiler::makeConstString("!=")) |
4801 | 0 | result = (op1 != op2) ? "1" : "0"; |
4802 | 0 | else if (cmp == MatchCompiler::makeConstString("<=")) |
4803 | 0 | result = (op1 <= op2) ? "1" : "0"; |
4804 | 0 | else if (cmp == MatchCompiler::makeConstString(">=")) |
4805 | 0 | result = (op1 >= op2) ? "1" : "0"; |
4806 | 0 | else if (cmp == MatchCompiler::makeConstString("<")) |
4807 | 0 | result = (op1 < op2) ? "1" : "0"; |
4808 | 0 | else |
4809 | 0 | result = (op1 > op2) ? "1" : "0"; |
4810 | |
|
4811 | 0 | tok->str(result); |
4812 | 0 | tok->deleteNext(2); |
4813 | 0 | ret = true; |
4814 | 0 | tok = tok->previous(); |
4815 | 0 | } |
4816 | 0 | } |
4817 | 0 | } |
4818 | 0 | } |
4819 | 0 | return ret; |
4820 | 0 | } |
4821 | | |
4822 | | void TemplateSimplifier::getTemplateParametersInDeclaration( |
4823 | | const Token * tok, |
4824 | | std::vector<const Token *> & typeParametersInDeclaration) |
4825 | 0 | { |
4826 | 0 | assert(tok->strAt(-1) == MatchCompiler::makeConstString("<")); |
4827 | | |
4828 | 0 | typeParametersInDeclaration.clear(); |
4829 | 0 | const Token *end = tok->previous()->findClosingBracket(); |
4830 | 0 | bool inDefaultValue = false; |
4831 | 0 | for (; tok && tok!= end; tok = tok->next()) { |
4832 | 0 | if (match40(tok)) { |
4833 | 0 | const Token *closing = tok->next()->findClosingBracket(); |
4834 | 0 | if (closing) |
4835 | 0 | tok = closing->next(); |
4836 | 0 | } else if (tok->link() && match71(tok)) |
4837 | 0 | tok = tok->link(); |
4838 | 0 | else if (match168(tok)) { |
4839 | 0 | if (!inDefaultValue) { |
4840 | 0 | typeParametersInDeclaration.push_back(tok); |
4841 | 0 | if (tok->strAt(1) == MatchCompiler::makeConstString("=")) |
4842 | 0 | inDefaultValue = true; |
4843 | 0 | } |
4844 | 0 | } else if (inDefaultValue) { |
4845 | 0 | if (tok->str() == MatchCompiler::makeConstString(",")) |
4846 | 0 | inDefaultValue = false; |
4847 | 0 | else if (tok->str() == MatchCompiler::makeConstString("<")) { |
4848 | 0 | const Token *closing = tok->findClosingBracket(); |
4849 | 0 | if (closing) |
4850 | 0 | tok = closing; |
4851 | 0 | } |
4852 | 0 | } |
4853 | 0 | } |
4854 | 0 | } |
4855 | | |
4856 | | bool TemplateSimplifier::matchSpecialization( |
4857 | | const Token *templateDeclarationNameToken, |
4858 | | const Token *templateInstantiationNameToken, |
4859 | | const std::list<const Token *> & specializations) |
4860 | 0 | { |
4861 | | // Is there a matching specialization? |
4862 | 0 | for (auto it = specializations.cbegin(); it != specializations.cend(); ++it) { |
4863 | 0 | if (!match6(*it)) |
4864 | 0 | continue; |
4865 | 0 | const Token *startToken = (*it); |
4866 | 0 | while (startToken->previous() && !match18(startToken->previous())) |
4867 | 0 | startToken = startToken->previous(); |
4868 | 0 | if (!match40(startToken)) |
4869 | 0 | continue; |
4870 | | // cppcheck-suppress shadowFunction - TODO: fix this |
4871 | 0 | std::vector<const Token *> templateParameters; |
4872 | 0 | getTemplateParametersInDeclaration(startToken->tokAt(2), templateParameters); |
4873 | |
|
4874 | 0 | const Token *instToken = templateInstantiationNameToken->tokAt(2); |
4875 | 0 | const Token *declToken = (*it)->tokAt(2); |
4876 | 0 | const Token * const endToken = (*it)->next()->findClosingBracket(); |
4877 | 0 | if (!endToken) |
4878 | 0 | continue; |
4879 | 0 | while (declToken != endToken) { |
4880 | 0 | if (declToken->str() != instToken->str() || |
4881 | 0 | declToken->isSigned() != instToken->isSigned() || |
4882 | 0 | declToken->isUnsigned() != instToken->isUnsigned() || |
4883 | 0 | declToken->isLong() != instToken->isLong()) { |
4884 | 0 | int nr = 0; |
4885 | 0 | while (nr < templateParameters.size() && templateParameters[nr]->str() != declToken->str()) |
4886 | 0 | ++nr; |
4887 | |
|
4888 | 0 | if (nr == templateParameters.size()) |
4889 | 0 | break; |
4890 | 0 | } |
4891 | 0 | declToken = declToken->next(); |
4892 | 0 | instToken = instToken->next(); |
4893 | 0 | } |
4894 | |
|
4895 | 0 | if (declToken && instToken && declToken == endToken && instToken->str() == MatchCompiler::makeConstString(">")) { |
4896 | | // specialization matches. |
4897 | 0 | return templateDeclarationNameToken == *it; |
4898 | 0 | } |
4899 | 0 | } |
4900 | | |
4901 | | // No specialization matches. Return true if the declaration is not a specialization. |
4902 | 0 | return match169(templateDeclarationNameToken) && |
4903 | 0 | (templateDeclarationNameToken->str().find('<') == std::string::npos); |
4904 | 0 | } |
4905 | | |
4906 | | std::string TemplateSimplifier::getNewName( |
4907 | | Token *tok2, |
4908 | | std::list<std::string> &typeStringsUsedInTemplateInstantiation) |
4909 | 0 | { |
4910 | 0 | std::string typeForNewName; |
4911 | 0 | unsigned int indentlevel = 0; |
4912 | 0 | const Token * endToken = tok2->next()->findClosingBracket(); |
4913 | 0 | for (Token *tok3 = tok2->tokAt(2); tok3 != endToken && (indentlevel > 0 || tok3->str() != MatchCompiler::makeConstString(">")); tok3 = tok3->next()) { |
4914 | | // #2721 - unhandled [ => bail out |
4915 | 0 | if (tok3->str() == MatchCompiler::makeConstString("[") && !match170(tok3->next())) { |
4916 | 0 | typeForNewName.clear(); |
4917 | 0 | break; |
4918 | 0 | } |
4919 | 0 | if (!tok3->next()) { |
4920 | 0 | typeForNewName.clear(); |
4921 | 0 | break; |
4922 | 0 | } |
4923 | 0 | if (match171(tok3->tokAt(-2)) && (tok3->strAt(1) == MatchCompiler::makeConstString(">") || templateParameters(tok3))) |
4924 | 0 | ++indentlevel; |
4925 | 0 | else if (indentlevel > 0 && match172(tok3)) |
4926 | 0 | --indentlevel; |
4927 | 0 | else if (indentlevel == 0 && match173(tok3->previous())) { |
4928 | 0 | mTypesUsedInTemplateInstantiation.emplace_back(tok3, ""); |
4929 | 0 | } |
4930 | 0 | if (match14(tok3)) |
4931 | 0 | ++indentlevel; |
4932 | 0 | else if (match174(tok3)) |
4933 | 0 | --indentlevel; |
4934 | 0 | const bool constconst = tok3->str() == MatchCompiler::makeConstString("const") && tok3->strAt(1) == MatchCompiler::makeConstString("const"); |
4935 | 0 | if (!constconst) { |
4936 | 0 | if (tok3->isUnsigned()) |
4937 | 0 | typeStringsUsedInTemplateInstantiation.emplace_back("unsigned"); |
4938 | 0 | else if (tok3->isSigned()) |
4939 | 0 | typeStringsUsedInTemplateInstantiation.emplace_back("signed"); |
4940 | 0 | if (tok3->isLong()) |
4941 | 0 | typeStringsUsedInTemplateInstantiation.emplace_back("long"); |
4942 | 0 | typeStringsUsedInTemplateInstantiation.push_back(tok3->str()); |
4943 | 0 | } |
4944 | | // add additional type information |
4945 | 0 | if (!constconst && !match175(tok3)) { |
4946 | 0 | if (!typeForNewName.empty()) |
4947 | 0 | typeForNewName += ' '; |
4948 | 0 | if (tok3->isUnsigned()) |
4949 | 0 | typeForNewName += "unsigned "; |
4950 | 0 | else if (tok3->isSigned()) |
4951 | 0 | typeForNewName += "signed "; |
4952 | 0 | if (tok3->isLong()) { |
4953 | 0 | typeForNewName += "long "; |
4954 | 0 | } |
4955 | 0 | typeForNewName += tok3->str(); |
4956 | 0 | } |
4957 | 0 | } |
4958 | |
|
4959 | 0 | return typeForNewName; |
4960 | 0 | } |
4961 | | |
4962 | | bool TemplateSimplifier::simplifyTemplateInstantiations( |
4963 | | const TokenAndName &templateDeclaration, |
4964 | | const std::list<const Token *> &specializations, |
4965 | | const std::time_t maxtime, |
4966 | | std::set<std::string> &expandedtemplates) |
4967 | 0 | { |
4968 | | // this variable is not used at the moment. The intention was to |
4969 | | // allow continuous instantiations until all templates has been expanded |
4970 | | //bool done = false; |
4971 | | |
4972 | | // Contains tokens such as "T" |
4973 | 0 | std::vector<const Token *> typeParametersInDeclaration; |
4974 | 0 | getTemplateParametersInDeclaration(templateDeclaration.token()->tokAt(2), typeParametersInDeclaration); |
4975 | 0 | const bool printDebug = mSettings.debugwarnings; |
4976 | 0 | const bool specialized = templateDeclaration.isSpecialization(); |
4977 | 0 | const bool isfunc = templateDeclaration.isFunction(); |
4978 | 0 | const bool isVar = templateDeclaration.isVariable(); |
4979 | | |
4980 | | // locate template usage.. |
4981 | 0 | std::string::size_type numberOfTemplateInstantiations = mTemplateInstantiations.size(); |
4982 | 0 | unsigned int recursiveCount = 0; |
4983 | |
|
4984 | 0 | bool instantiated = false; |
4985 | |
|
4986 | 0 | for (const TokenAndName &instantiation : mTemplateInstantiations) { |
4987 | | // skip deleted instantiations |
4988 | 0 | if (!instantiation.token()) |
4989 | 0 | continue; |
4990 | 0 | if (numberOfTemplateInstantiations != mTemplateInstantiations.size()) { |
4991 | 0 | numberOfTemplateInstantiations = mTemplateInstantiations.size(); |
4992 | 0 | ++recursiveCount; |
4993 | 0 | if (recursiveCount > mSettings.maxTemplateRecursion) { |
4994 | 0 | if (mSettings.severity.isEnabled(Severity::information)) { |
4995 | 0 | std::list<std::string> typeStringsUsedInTemplateInstantiation; |
4996 | 0 | const std::string typeForNewName = templateDeclaration.name() + "<" + getNewName(instantiation.token(), typeStringsUsedInTemplateInstantiation) + ">"; |
4997 | |
|
4998 | 0 | const std::list<const Token *> callstack(1, instantiation.token()); |
4999 | 0 | const ErrorMessage errmsg(callstack, |
5000 | 0 | &mTokenizer.list, |
5001 | 0 | Severity::information, |
5002 | 0 | "templateRecursion", |
5003 | 0 | "TemplateSimplifier: max template recursion (" |
5004 | 0 | + std::to_string(mSettings.maxTemplateRecursion) |
5005 | 0 | + ") reached for template '"+typeForNewName+"'. You might want to limit Cppcheck recursion.", |
5006 | 0 | Certainty::normal); |
5007 | 0 | mErrorLogger.reportErr(errmsg); |
5008 | 0 | } |
5009 | | |
5010 | | // bail out.. |
5011 | 0 | break; |
5012 | 0 | } |
5013 | 0 | } |
5014 | | |
5015 | | // already simplified |
5016 | 0 | if (!match6(instantiation.token())) |
5017 | 0 | continue; |
5018 | | |
5019 | 0 | if (!((instantiation.fullName() == templateDeclaration.fullName()) || |
5020 | 0 | (instantiation.name() == templateDeclaration.name() && |
5021 | 0 | instantiation.fullName() == templateDeclaration.scope()))) { |
5022 | | // FIXME: fallback to not matching scopes until type deduction works |
5023 | | |
5024 | | // names must match |
5025 | 0 | if (instantiation.name() != templateDeclaration.name()) |
5026 | 0 | continue; |
5027 | | |
5028 | | // scopes must match when present |
5029 | 0 | if (!instantiation.scope().empty() && !templateDeclaration.scope().empty()) |
5030 | 0 | continue; |
5031 | 0 | } |
5032 | | |
5033 | | // make sure constructors and destructors don't match each other |
5034 | 0 | if (templateDeclaration.nameToken()->strAt(-1) == MatchCompiler::makeConstString("~") && instantiation.token()->strAt(-1) != MatchCompiler::makeConstString("~")) |
5035 | 0 | continue; |
5036 | | |
5037 | | // template families should match |
5038 | 0 | if (!instantiation.isFunction() && templateDeclaration.isFunction()) { |
5039 | | // there are exceptions |
5040 | 0 | if (!match54(instantiation.token()->tokAt(-2))) |
5041 | 0 | continue; |
5042 | 0 | } |
5043 | | |
5044 | 0 | if (templateDeclaration.isFunction() && instantiation.isFunction()) { |
5045 | 0 | std::vector<const Token*> declFuncArgs; |
5046 | 0 | getFunctionArguments(templateDeclaration.nameToken(), declFuncArgs); |
5047 | 0 | std::vector<const Token*> instFuncParams; |
5048 | 0 | getFunctionArguments(instantiation.token(), instFuncParams); |
5049 | |
|
5050 | 0 | if (declFuncArgs.size() != instFuncParams.size()) { |
5051 | | // check for default arguments |
5052 | 0 | const Token* tok = templateDeclaration.nameToken()->tokAt(2); |
5053 | 0 | const Token* end = templateDeclaration.nameToken()->linkAt(1); |
5054 | 0 | size_t count = 0; |
5055 | 0 | for (; tok != end; tok = tok->next()) { |
5056 | 0 | if (tok->str() == MatchCompiler::makeConstString("=")) |
5057 | 0 | count++; |
5058 | 0 | } |
5059 | |
|
5060 | 0 | if (instFuncParams.size() < (declFuncArgs.size() - count) || instFuncParams.size() > declFuncArgs.size()) |
5061 | 0 | continue; |
5062 | 0 | } |
5063 | 0 | } |
5064 | | |
5065 | | // A global function can't be called through a pointer. |
5066 | 0 | if (templateDeclaration.isFunction() && templateDeclaration.scope().empty() && |
5067 | 0 | (instantiation.token()->strAt(-1) == MatchCompiler::makeConstString(".") || |
5068 | 0 | match95(instantiation.token()->tokAt(-2)))) |
5069 | 0 | continue; |
5070 | | |
5071 | 0 | if (!matchSpecialization(templateDeclaration.nameToken(), instantiation.token(), specializations)) |
5072 | 0 | continue; |
5073 | | |
5074 | 0 | Token * const tok2 = instantiation.token(); |
5075 | 0 | if (!mTokenList.getFiles().empty()) |
5076 | 0 | mErrorLogger.reportProgress(mTokenList.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue()); |
5077 | |
|
5078 | 0 | if (maxtime > 0 && std::time(nullptr) > maxtime) { |
5079 | 0 | if (mSettings.debugwarnings) { |
5080 | 0 | ErrorMessage::FileLocation loc(mTokenList.getFiles()[0], 0, 0); |
5081 | 0 | ErrorMessage errmsg({std::move(loc)}, |
5082 | 0 | "", |
5083 | 0 | Severity::debug, |
5084 | 0 | "Template instantiation maximum time exceeded", |
5085 | 0 | "templateMaxTime", |
5086 | 0 | Certainty::normal); |
5087 | 0 | mErrorLogger.reportErr(errmsg); |
5088 | 0 | } |
5089 | 0 | return false; |
5090 | 0 | } |
5091 | | |
5092 | 0 | assert(mTokenList.validateToken(tok2)); // that assertion fails on examples from #6021 |
5093 | | |
5094 | 0 | const Token *startToken = tok2; |
5095 | 0 | while (match176(startToken->tokAt(-2))) { |
5096 | 0 | if (startToken->strAt(-2) == MatchCompiler::makeConstString(">")) { |
5097 | 0 | const Token * tok3 = startToken->tokAt(-2)->findOpeningBracket(); |
5098 | 0 | if (tok3) |
5099 | 0 | startToken = tok3->previous(); |
5100 | 0 | else |
5101 | 0 | break; |
5102 | 0 | } else |
5103 | 0 | startToken = startToken->tokAt(-2); |
5104 | 0 | } |
5105 | |
|
5106 | 0 | if (match177(startToken->previous())) { |
5107 | 0 | const char* patternAfter = isfunc ? "(" : isVar ? ";|%op%|(" : "*|&|::| %name%"; |
5108 | 0 | if (!isfunc && !isVar) |
5109 | 0 | if (const Token* end = startToken->next()->findClosingBracket()) |
5110 | 0 | if (match178(end)) |
5111 | 0 | patternAfter = "(|{"; |
5112 | 0 | if (!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), templateDeclaration.isVariadic(), patternAfter)) |
5113 | 0 | continue; |
5114 | 0 | } |
5115 | | |
5116 | | // New type.. |
5117 | 0 | mTypesUsedInTemplateInstantiation.clear(); |
5118 | 0 | std::list<std::string> typeStringsUsedInTemplateInstantiation; |
5119 | 0 | std::string typeForNewName = getNewName(tok2, typeStringsUsedInTemplateInstantiation); |
5120 | |
|
5121 | 0 | if ((typeForNewName.empty() && !templateDeclaration.isVariadic()) || |
5122 | 0 | (!typeParametersInDeclaration.empty() && !instantiateMatch(tok2, typeParametersInDeclaration.size(), templateDeclaration.isVariadic(), nullptr))) { |
5123 | 0 | if (printDebug) { |
5124 | 0 | std::list<const Token *> callstack(1, tok2); |
5125 | 0 | mErrorLogger.reportErr(ErrorMessage(callstack, &mTokenList, Severity::debug, "templateInstantiation", |
5126 | 0 | "Failed to instantiate template \"" + instantiation.name() + "\". The checking continues anyway.", Certainty::normal)); |
5127 | 0 | } |
5128 | 0 | if (typeForNewName.empty()) |
5129 | 0 | continue; |
5130 | 0 | break; |
5131 | 0 | } |
5132 | | |
5133 | | // New classname/funcname.. |
5134 | 0 | const std::string newName(templateDeclaration.name() + " < " + typeForNewName + " >"); |
5135 | 0 | const std::string newFullName(templateDeclaration.scope() + (templateDeclaration.scope().empty() ? "" : " :: ") + newName); |
5136 | |
|
5137 | 0 | if (expandedtemplates.insert(newFullName).second) { |
5138 | 0 | expandTemplate(templateDeclaration, instantiation, typeParametersInDeclaration, newName, !specialized && !isVar); |
5139 | 0 | instantiated = true; |
5140 | 0 | mChanged = true; |
5141 | 0 | } |
5142 | | |
5143 | | // Replace all these template usages.. |
5144 | 0 | replaceTemplateUsage(instantiation, typeStringsUsedInTemplateInstantiation, newName); |
5145 | 0 | } |
5146 | | |
5147 | | // process uninstantiated templates |
5148 | | // TODO: remove the specialized check and handle all uninstantiated templates someday. |
5149 | 0 | if (!instantiated && specialized) { |
5150 | 0 | auto * tok2 = const_cast<Token *>(templateDeclaration.nameToken()); |
5151 | 0 | if (!mTokenList.getFiles().empty()) |
5152 | 0 | mErrorLogger.reportProgress(mTokenList.getFiles()[0], "TemplateSimplifier::simplifyTemplateInstantiations()", tok2->progressValue()); |
5153 | |
|
5154 | 0 | if (maxtime > 0 && std::time(nullptr) > maxtime) { |
5155 | 0 | if (mSettings.debugwarnings) { |
5156 | 0 | ErrorMessage::FileLocation loc(mTokenList.getFiles()[0], 0, 0); |
5157 | 0 | ErrorMessage errmsg({std::move(loc)}, |
5158 | 0 | "", |
5159 | 0 | Severity::debug, |
5160 | 0 | "Template instantiation maximum time exceeded", |
5161 | 0 | "templateMaxTime", |
5162 | 0 | Certainty::normal); |
5163 | 0 | mErrorLogger.reportErr(errmsg); |
5164 | 0 | } |
5165 | 0 | return false; |
5166 | 0 | } |
5167 | | |
5168 | 0 | assert(mTokenList.validateToken(tok2)); // that assertion fails on examples from #6021 |
5169 | | |
5170 | 0 | Token *startToken = tok2; |
5171 | 0 | while (match176(startToken->tokAt(-2))) { |
5172 | 0 | if (startToken->strAt(-2) == MatchCompiler::makeConstString(">")) { |
5173 | 0 | Token * tok3 = startToken->tokAt(-2)->findOpeningBracket(); |
5174 | 0 | if (tok3) |
5175 | 0 | startToken = tok3->previous(); |
5176 | 0 | else |
5177 | 0 | break; |
5178 | 0 | } else |
5179 | 0 | startToken = startToken->tokAt(-2); |
5180 | 0 | } |
5181 | | |
5182 | | // TODO: re-enable when specialized check is removed |
5183 | | // if (Token::Match(startToken->previous(), ";|{|}|=|const") && |
5184 | | // (!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : isVar ? ";|%op%|(" : "*|&|::| %name%"))) |
5185 | | // return false; |
5186 | | |
5187 | | // already simplified |
5188 | 0 | if (!match6(tok2)) |
5189 | 0 | return false; |
5190 | | |
5191 | 0 | if (!matchSpecialization(templateDeclaration.nameToken(), tok2, specializations)) |
5192 | 0 | return false; |
5193 | | |
5194 | | // New type.. |
5195 | 0 | mTypesUsedInTemplateInstantiation.clear(); |
5196 | 0 | std::list<std::string> typeStringsUsedInTemplateInstantiation; |
5197 | 0 | std::string typeForNewName = getNewName(tok2, typeStringsUsedInTemplateInstantiation); |
5198 | |
|
5199 | 0 | if (typeForNewName.empty()) { |
5200 | 0 | if (printDebug) { |
5201 | 0 | std::list<const Token *> callstack(1, tok2); |
5202 | 0 | mErrorLogger.reportErr(ErrorMessage(callstack, &mTokenList, Severity::debug, "templateInstantiation", |
5203 | 0 | "Failed to instantiate template \"" + templateDeclaration.name() + "\". The checking continues anyway.", Certainty::normal)); |
5204 | 0 | } |
5205 | 0 | return false; |
5206 | 0 | } |
5207 | | |
5208 | | // New classname/funcname.. |
5209 | 0 | const std::string newName(templateDeclaration.name() + " < " + typeForNewName + " >"); |
5210 | 0 | const std::string newFullName(templateDeclaration.scope() + (templateDeclaration.scope().empty() ? "" : " :: ") + newName); |
5211 | |
|
5212 | 0 | if (expandedtemplates.insert(newFullName).second) { |
5213 | 0 | expandTemplate(templateDeclaration, templateDeclaration, typeParametersInDeclaration, newName, !specialized && !isVar); |
5214 | 0 | instantiated = true; |
5215 | 0 | mChanged = true; |
5216 | 0 | } |
5217 | | |
5218 | | // Replace all these template usages.. |
5219 | 0 | replaceTemplateUsage(templateDeclaration, typeStringsUsedInTemplateInstantiation, newName); |
5220 | 0 | } |
5221 | | |
5222 | | // Template has been instantiated .. then remove the template declaration |
5223 | 0 | return instantiated; |
5224 | 0 | } |
5225 | | |
5226 | | static bool matchTemplateParameters(const Token *nameTok, const std::list<std::string> &strings) |
5227 | 0 | { |
5228 | 0 | const Token *tok = nameTok->tokAt(2); |
5229 | 0 | const Token *end = nameTok->next()->findClosingBracket(); |
5230 | 0 | if (!end) |
5231 | 0 | return false; |
5232 | 0 | auto it = strings.cbegin(); |
5233 | 0 | while (tok && tok != end && it != strings.cend()) { |
5234 | 0 | if (tok->isUnsigned()) { |
5235 | 0 | if (*it != MatchCompiler::makeConstString("unsigned")) |
5236 | 0 | return false; |
5237 | | |
5238 | 0 | ++it; |
5239 | 0 | if (it == strings.cend()) |
5240 | 0 | return false; |
5241 | 0 | } else if (tok->isSigned()) { |
5242 | 0 | if (*it != MatchCompiler::makeConstString("signed")) |
5243 | 0 | return false; |
5244 | | |
5245 | 0 | ++it; |
5246 | 0 | if (it == strings.cend()) |
5247 | 0 | return false; |
5248 | 0 | } |
5249 | 0 | if (tok->isLong()) { |
5250 | 0 | if (*it != MatchCompiler::makeConstString("long")) |
5251 | 0 | return false; |
5252 | | |
5253 | 0 | ++it; |
5254 | 0 | if (it == strings.cend()) |
5255 | 0 | return false; |
5256 | 0 | } |
5257 | 0 | if (*it != tok->str()) |
5258 | 0 | return false; |
5259 | 0 | tok = tok->next(); |
5260 | 0 | ++it; |
5261 | 0 | } |
5262 | 0 | return it == strings.cend() && tok && tok->str() == MatchCompiler::makeConstString(">"); |
5263 | 0 | } |
5264 | | |
5265 | | void TemplateSimplifier::replaceTemplateUsage( |
5266 | | const TokenAndName &instantiation, |
5267 | | const std::list<std::string> &typeStringsUsedInTemplateInstantiation, |
5268 | | const std::string &newName) |
5269 | 0 | { |
5270 | 0 | std::list<std::pair<Token *, Token *>> removeTokens; |
5271 | 0 | for (Token *nameTok = mTokenList.front(); nameTok; nameTok = nameTok->next()) { |
5272 | 0 | if (!match6(nameTok) || |
5273 | 0 | match179(nameTok)) |
5274 | 0 | continue; |
5275 | | |
5276 | 0 | std::set<TemplateSimplifier::TokenAndName*>* pointers = nameTok->templateSimplifierPointers(); |
5277 | | |
5278 | | // check if instantiation matches token instantiation from pointer |
5279 | 0 | if (pointers && !pointers->empty()) { |
5280 | | // check full name |
5281 | 0 | if (instantiation.fullName() != (*pointers->begin())->fullName()) { |
5282 | | // FIXME: fallback to just matching name |
5283 | 0 | if (nameTok->str() != instantiation.name()) |
5284 | 0 | continue; |
5285 | 0 | } |
5286 | 0 | } |
5287 | | // no pointer available look at tokens directly |
5288 | 0 | else { |
5289 | | // FIXME: fallback to just matching name |
5290 | 0 | if (nameTok->str() != instantiation.name()) |
5291 | 0 | continue; |
5292 | 0 | } |
5293 | | |
5294 | 0 | if (!matchTemplateParameters(nameTok, typeStringsUsedInTemplateInstantiation)) |
5295 | 0 | continue; |
5296 | | |
5297 | 0 | Token *tok2 = nameTok->next()->findClosingBracket(); |
5298 | |
|
5299 | 0 | if (!tok2) |
5300 | 0 | break; |
5301 | | |
5302 | 0 | const Token * const nameTok1 = nameTok; |
5303 | 0 | nameTok->str(newName); |
5304 | | |
5305 | | // matching template usage => replace tokens.. |
5306 | | // Foo < int > => Foo<int> |
5307 | 0 | for (const Token *tok = nameTok1->next(); tok != tok2; tok = tok->next()) { |
5308 | 0 | if (tok->isName() && tok->templateSimplifierPointers() && !tok->templateSimplifierPointers()->empty()) { |
5309 | 0 | for (auto ti = mTemplateInstantiations.cbegin(); ti != mTemplateInstantiations.cend();) { |
5310 | 0 | if (ti->token() == tok) { |
5311 | 0 | mTemplateInstantiations.erase(ti); |
5312 | 0 | break; |
5313 | 0 | } |
5314 | 0 | ++ti; |
5315 | 0 | } |
5316 | 0 | } |
5317 | 0 | } |
5318 | | // Fix crash in #9007 |
5319 | 0 | if (match180(nameTok->previous())) |
5320 | 0 | mTemplateNamePos.erase(nameTok->previous()); |
5321 | 0 | removeTokens.emplace_back(nameTok, tok2->next()); |
5322 | |
|
5323 | 0 | nameTok = tok2; |
5324 | 0 | } |
5325 | 0 | while (!removeTokens.empty()) { |
5326 | 0 | eraseTokens(removeTokens.back().first, removeTokens.back().second); |
5327 | 0 | removeTokens.pop_back(); |
5328 | 0 | } |
5329 | 0 | } |
5330 | | |
5331 | | static bool specMatch( |
5332 | | const TemplateSimplifier::TokenAndName &spec, |
5333 | | const TemplateSimplifier::TokenAndName &decl) |
5334 | 0 | { |
5335 | | // make sure decl is really a declaration |
5336 | 0 | if (decl.isPartialSpecialization() || decl.isSpecialization() || decl.isAlias() || decl.isFriend()) |
5337 | 0 | return false; |
5338 | | |
5339 | 0 | if (!spec.isSameFamily(decl)) |
5340 | 0 | return false; |
5341 | | |
5342 | | // make sure the scopes and names match |
5343 | 0 | if (spec.fullName() == decl.fullName()) { |
5344 | 0 | if (spec.isFunction()) { |
5345 | 0 | std::vector<const Token*> specArgs; |
5346 | 0 | std::vector<const Token*> declArgs; |
5347 | 0 | getFunctionArguments(spec.nameToken(), specArgs); |
5348 | 0 | getFunctionArguments(decl.nameToken(), declArgs); |
5349 | |
|
5350 | 0 | if (specArgs.size() == declArgs.size()) { |
5351 | | // @todo make sure function parameters also match |
5352 | 0 | return true; |
5353 | 0 | } |
5354 | 0 | } else |
5355 | 0 | return true; |
5356 | 0 | } |
5357 | | |
5358 | 0 | return false; |
5359 | 0 | } |
5360 | | |
5361 | | void TemplateSimplifier::getSpecializations() |
5362 | 0 | { |
5363 | | // try to locate a matching declaration for each user defined specialization |
5364 | 0 | for (const auto& spec : mTemplateDeclarations) { |
5365 | 0 | if (spec.isSpecialization()) { |
5366 | 0 | auto it = std::find_if(mTemplateDeclarations.cbegin(), mTemplateDeclarations.cend(), [&](const TokenAndName& decl) { |
5367 | 0 | return specMatch(spec, decl); |
5368 | 0 | }); |
5369 | 0 | if (it != mTemplateDeclarations.cend()) |
5370 | 0 | mTemplateSpecializationMap[spec.token()] = it->token(); |
5371 | 0 | else { |
5372 | 0 | it = std::find_if(mTemplateForwardDeclarations.cbegin(), mTemplateForwardDeclarations.cend(), [&](const TokenAndName& decl) { |
5373 | 0 | return specMatch(spec, decl); |
5374 | 0 | }); |
5375 | 0 | if (it != mTemplateForwardDeclarations.cend()) |
5376 | 0 | mTemplateSpecializationMap[spec.token()] = it->token(); |
5377 | 0 | } |
5378 | 0 | } |
5379 | 0 | } |
5380 | 0 | } |
5381 | | |
5382 | | void TemplateSimplifier::getPartialSpecializations() |
5383 | 0 | { |
5384 | | // try to locate a matching declaration for each user defined partial specialization |
5385 | 0 | for (const auto& spec : mTemplateDeclarations) { |
5386 | 0 | if (spec.isPartialSpecialization()) { |
5387 | 0 | auto it = std::find_if(mTemplateDeclarations.cbegin(), mTemplateDeclarations.cend(), [&](const TokenAndName& decl) { |
5388 | 0 | return specMatch(spec, decl); |
5389 | 0 | }); |
5390 | 0 | if (it != mTemplateDeclarations.cend()) |
5391 | 0 | mTemplatePartialSpecializationMap[spec.token()] = it->token(); |
5392 | 0 | else { |
5393 | 0 | it = std::find_if(mTemplateForwardDeclarations.cbegin(), mTemplateForwardDeclarations.cend(), [&](const TokenAndName& decl) { |
5394 | 0 | return specMatch(spec, decl); |
5395 | 0 | }); |
5396 | 0 | if (it != mTemplateForwardDeclarations.cend()) |
5397 | 0 | mTemplatePartialSpecializationMap[spec.token()] = it->token(); |
5398 | 0 | } |
5399 | 0 | } |
5400 | 0 | } |
5401 | 0 | } |
5402 | | |
5403 | | void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues() |
5404 | 0 | { |
5405 | | // try to locate a matching declaration for each forward declaration |
5406 | 0 | for (const auto & forwardDecl : mTemplateForwardDeclarations) { |
5407 | 0 | std::vector<const Token *> params1; |
5408 | |
|
5409 | 0 | getTemplateParametersInDeclaration(forwardDecl.token()->tokAt(2), params1); |
5410 | |
|
5411 | 0 | for (auto & decl : mTemplateDeclarations) { |
5412 | | // skip partializations, type aliases and friends |
5413 | 0 | if (decl.isPartialSpecialization() || decl.isAlias() || decl.isFriend()) |
5414 | 0 | continue; |
5415 | | |
5416 | 0 | std::vector<const Token *> params2; |
5417 | |
|
5418 | 0 | getTemplateParametersInDeclaration(decl.token()->tokAt(2), params2); |
5419 | | |
5420 | | // make sure the number of arguments match |
5421 | 0 | if (params1.size() == params2.size()) { |
5422 | | // make sure the scopes and names match |
5423 | 0 | if (forwardDecl.fullName() == decl.fullName()) { |
5424 | | // save forward declaration for lookup later |
5425 | 0 | if ((decl.nameToken()->strAt(1) == MatchCompiler::makeConstString("(") && forwardDecl.nameToken()->strAt(1) == MatchCompiler::makeConstString("(")) || |
5426 | 0 | (decl.nameToken()->strAt(1) == MatchCompiler::makeConstString("{") && forwardDecl.nameToken()->strAt(1) == MatchCompiler::makeConstString(";"))) { |
5427 | 0 | mTemplateForwardDeclarationsMap[decl.token()] = forwardDecl.token(); |
5428 | 0 | } |
5429 | |
|
5430 | 0 | for (size_t k = 0; k < params1.size(); k++) { |
5431 | | // copy default value to declaration if not present |
5432 | 0 | if (params1[k]->strAt(1) == MatchCompiler::makeConstString("=") && params2[k]->strAt(1) != MatchCompiler::makeConstString("=")) { |
5433 | 0 | int level = 0; |
5434 | 0 | const Token *end = params1[k]->next(); |
5435 | 0 | while (end && !(level == 0 && match78(end))) { |
5436 | 0 | if (match181(end)) |
5437 | 0 | level++; |
5438 | 0 | else if (match182(end)) |
5439 | 0 | level--; |
5440 | 0 | end = end->next(); |
5441 | 0 | } |
5442 | 0 | if (end) |
5443 | 0 | TokenList::copyTokens(const_cast<Token *>(params2[k]), params1[k]->next(), end->previous()); |
5444 | 0 | } |
5445 | 0 | } |
5446 | | |
5447 | | // update parameter end pointer |
5448 | 0 | decl.paramEnd(decl.token()->next()->findClosingBracket()); |
5449 | 0 | } |
5450 | 0 | } |
5451 | 0 | } |
5452 | 0 | } |
5453 | 0 | } |
5454 | | |
5455 | | void TemplateSimplifier::printOut(const TokenAndName &tokenAndName, const std::string &indent) const |
5456 | 0 | { |
5457 | 0 | std::cout << indent << "token: "; |
5458 | 0 | if (tokenAndName.token()) |
5459 | 0 | std::cout << "\"" << tokenAndName.token()->str() << "\" " << mTokenList.fileLine(tokenAndName.token()); |
5460 | 0 | else |
5461 | 0 | std::cout << "nullptr"; |
5462 | 0 | std::cout << std::endl; |
5463 | 0 | std::cout << indent << "scope: \"" << tokenAndName.scope() << "\"" << std::endl; |
5464 | 0 | std::cout << indent << "name: \"" << tokenAndName.name() << "\"" << std::endl; |
5465 | 0 | std::cout << indent << "fullName: \"" << tokenAndName.fullName() << "\"" << std::endl; |
5466 | 0 | std::cout << indent << "nameToken: "; |
5467 | 0 | if (tokenAndName.nameToken()) |
5468 | 0 | std::cout << "\"" << tokenAndName.nameToken()->str() << "\" " << mTokenList.fileLine(tokenAndName.nameToken()); |
5469 | 0 | else |
5470 | 0 | std::cout << "nullptr"; |
5471 | 0 | std::cout << std::endl; |
5472 | 0 | std::cout << indent << "paramEnd: "; |
5473 | 0 | if (tokenAndName.paramEnd()) |
5474 | 0 | std::cout << "\"" << tokenAndName.paramEnd()->str() << "\" " << mTokenList.fileLine(tokenAndName.paramEnd()); |
5475 | 0 | else |
5476 | 0 | std::cout << "nullptr"; |
5477 | 0 | std::cout << std::endl; |
5478 | 0 | std::cout << indent << "flags: "; |
5479 | 0 | if (tokenAndName.isClass()) |
5480 | 0 | std::cout << " isClass"; |
5481 | 0 | if (tokenAndName.isFunction()) |
5482 | 0 | std::cout << " isFunction"; |
5483 | 0 | if (tokenAndName.isVariable()) |
5484 | 0 | std::cout << " isVariable"; |
5485 | 0 | if (tokenAndName.isAlias()) |
5486 | 0 | std::cout << " isAlias"; |
5487 | 0 | if (tokenAndName.isSpecialization()) |
5488 | 0 | std::cout << " isSpecialization"; |
5489 | 0 | if (tokenAndName.isPartialSpecialization()) |
5490 | 0 | std::cout << " isPartialSpecialization"; |
5491 | 0 | if (tokenAndName.isForwardDeclaration()) |
5492 | 0 | std::cout << " isForwardDeclaration"; |
5493 | 0 | if (tokenAndName.isVariadic()) |
5494 | 0 | std::cout << " isVariadic"; |
5495 | 0 | if (tokenAndName.isFriend()) |
5496 | 0 | std::cout << " isFriend"; |
5497 | 0 | std::cout << std::endl; |
5498 | 0 | if (tokenAndName.token() && !tokenAndName.paramEnd() && tokenAndName.token()->strAt(1) == MatchCompiler::makeConstString("<")) { |
5499 | 0 | const Token *end = tokenAndName.token()->next()->findClosingBracket(); |
5500 | 0 | if (end) { |
5501 | 0 | const Token *start = tokenAndName.token()->next(); |
5502 | 0 | std::cout << indent << "type: "; |
5503 | 0 | while (start && start != end) { |
5504 | 0 | if (start->isUnsigned()) |
5505 | 0 | std::cout << "unsigned"; |
5506 | 0 | else if (start->isSigned()) |
5507 | 0 | std::cout << "signed"; |
5508 | 0 | if (start->isLong()) |
5509 | 0 | std::cout << "long"; |
5510 | 0 | std::cout << start->str(); |
5511 | 0 | start = start->next(); |
5512 | 0 | } |
5513 | 0 | std::cout << end->str() << std::endl; |
5514 | 0 | } |
5515 | 0 | } else if (tokenAndName.isAlias() && tokenAndName.paramEnd()) { |
5516 | 0 | if (tokenAndName.aliasStartToken()) { |
5517 | 0 | std::cout << indent << "aliasStartToken: \"" << tokenAndName.aliasStartToken()->str() << "\" " |
5518 | 0 | << mTokenList.fileLine(tokenAndName.aliasStartToken()) << std::endl; |
5519 | 0 | } |
5520 | 0 | if (tokenAndName.aliasEndToken()) { |
5521 | 0 | std::cout << indent << "aliasEndToken: \"" << tokenAndName.aliasEndToken()->str() << "\" " |
5522 | 0 | << mTokenList.fileLine(tokenAndName.aliasEndToken()) << std::endl; |
5523 | 0 | } |
5524 | 0 | } |
5525 | 0 | } |
5526 | | |
5527 | | void TemplateSimplifier::printOut(const std::string & text) const |
5528 | 0 | { |
5529 | 0 | std::cout << std::endl; |
5530 | 0 | std::cout << text << std::endl; |
5531 | 0 | std::cout << std::endl; |
5532 | 0 | std::cout << "mTemplateDeclarations: " << mTemplateDeclarations.size() << std::endl; |
5533 | 0 | int count = 0; |
5534 | 0 | for (const auto & decl : mTemplateDeclarations) { |
5535 | 0 | std::cout << "mTemplateDeclarations[" << count++ << "]:" << std::endl; |
5536 | 0 | printOut(decl); |
5537 | 0 | } |
5538 | 0 | std::cout << "mTemplateForwardDeclarations: " << mTemplateForwardDeclarations.size() << std::endl; |
5539 | 0 | count = 0; |
5540 | 0 | for (const auto & decl : mTemplateForwardDeclarations) { |
5541 | 0 | std::cout << "mTemplateForwardDeclarations[" << count++ << "]:" << std::endl; |
5542 | 0 | printOut(decl); |
5543 | 0 | } |
5544 | 0 | std::cout << "mTemplateForwardDeclarationsMap: " << mTemplateForwardDeclarationsMap.size() << std::endl; |
5545 | 0 | unsigned int mapIndex = 0; |
5546 | 0 | for (const auto & mapItem : mTemplateForwardDeclarationsMap) { |
5547 | 0 | unsigned int declIndex = 0; |
5548 | 0 | for (const auto & decl : mTemplateDeclarations) { |
5549 | 0 | if (mapItem.first == decl.token()) { |
5550 | 0 | unsigned int forwardIndex = 0; |
5551 | 0 | for (const auto & forwardDecl : mTemplateForwardDeclarations) { |
5552 | 0 | if (mapItem.second == forwardDecl.token()) { |
5553 | 0 | std::cout << "mTemplateForwardDeclarationsMap[" << mapIndex << "]:" << std::endl; |
5554 | 0 | std::cout << " mTemplateDeclarations[" << declIndex |
5555 | 0 | << "] => mTemplateForwardDeclarations[" << forwardIndex << "]" << std::endl; |
5556 | 0 | break; |
5557 | 0 | } |
5558 | 0 | forwardIndex++; |
5559 | 0 | } |
5560 | 0 | break; |
5561 | 0 | } |
5562 | 0 | declIndex++; |
5563 | 0 | } |
5564 | 0 | mapIndex++; |
5565 | 0 | } |
5566 | 0 | std::cout << "mTemplateSpecializationMap: " << mTemplateSpecializationMap.size() << std::endl; |
5567 | 0 | for (const auto & mapItem : mTemplateSpecializationMap) { |
5568 | 0 | unsigned int decl1Index = 0; |
5569 | 0 | for (const auto & decl1 : mTemplateDeclarations) { |
5570 | 0 | if (decl1.isSpecialization() && mapItem.first == decl1.token()) { |
5571 | 0 | bool found = false; |
5572 | 0 | unsigned int decl2Index = 0; |
5573 | 0 | for (const auto & decl2 : mTemplateDeclarations) { |
5574 | 0 | if (mapItem.second == decl2.token()) { |
5575 | 0 | std::cout << "mTemplateSpecializationMap[" << mapIndex << "]:" << std::endl; |
5576 | 0 | std::cout << " mTemplateDeclarations[" << decl1Index |
5577 | 0 | << "] => mTemplateDeclarations[" << decl2Index << "]" << std::endl; |
5578 | 0 | found = true; |
5579 | 0 | break; |
5580 | 0 | } |
5581 | 0 | decl2Index++; |
5582 | 0 | } |
5583 | 0 | if (!found) { |
5584 | 0 | decl2Index = 0; |
5585 | 0 | for (const auto & decl2 : mTemplateForwardDeclarations) { |
5586 | 0 | if (mapItem.second == decl2.token()) { |
5587 | 0 | std::cout << "mTemplateSpecializationMap[" << mapIndex << "]:" << std::endl; |
5588 | 0 | std::cout << " mTemplateDeclarations[" << decl1Index |
5589 | 0 | << "] => mTemplateForwardDeclarations[" << decl2Index << "]" << std::endl; |
5590 | 0 | break; |
5591 | 0 | } |
5592 | 0 | decl2Index++; |
5593 | 0 | } |
5594 | 0 | } |
5595 | 0 | break; |
5596 | 0 | } |
5597 | 0 | decl1Index++; |
5598 | 0 | } |
5599 | 0 | mapIndex++; |
5600 | 0 | } |
5601 | 0 | std::cout << "mTemplatePartialSpecializationMap: " << mTemplatePartialSpecializationMap.size() << std::endl; |
5602 | 0 | for (const auto & mapItem : mTemplatePartialSpecializationMap) { |
5603 | 0 | unsigned int decl1Index = 0; |
5604 | 0 | for (const auto & decl1 : mTemplateDeclarations) { |
5605 | 0 | if (mapItem.first == decl1.token()) { |
5606 | 0 | bool found = false; |
5607 | 0 | unsigned int decl2Index = 0; |
5608 | 0 | for (const auto & decl2 : mTemplateDeclarations) { |
5609 | 0 | if (mapItem.second == decl2.token()) { |
5610 | 0 | std::cout << "mTemplatePartialSpecializationMap[" << mapIndex << "]:" << std::endl; |
5611 | 0 | std::cout << " mTemplateDeclarations[" << decl1Index |
5612 | 0 | << "] => mTemplateDeclarations[" << decl2Index << "]" << std::endl; |
5613 | 0 | found = true; |
5614 | 0 | break; |
5615 | 0 | } |
5616 | 0 | decl2Index++; |
5617 | 0 | } |
5618 | 0 | if (!found) { |
5619 | 0 | decl2Index = 0; |
5620 | 0 | for (const auto & decl2 : mTemplateForwardDeclarations) { |
5621 | 0 | if (mapItem.second == decl2.token()) { |
5622 | 0 | std::cout << "mTemplatePartialSpecializationMap[" << mapIndex << "]:" << std::endl; |
5623 | 0 | std::cout << " mTemplateDeclarations[" << decl1Index |
5624 | 0 | << "] => mTemplateForwardDeclarations[" << decl2Index << "]" << std::endl; |
5625 | 0 | break; |
5626 | 0 | } |
5627 | 0 | decl2Index++; |
5628 | 0 | } |
5629 | 0 | } |
5630 | 0 | break; |
5631 | 0 | } |
5632 | 0 | decl1Index++; |
5633 | 0 | } |
5634 | 0 | mapIndex++; |
5635 | 0 | } |
5636 | 0 | std::cout << "mTemplateInstantiations: " << mTemplateInstantiations.size() << std::endl; |
5637 | 0 | count = 0; |
5638 | 0 | for (const auto & decl : mTemplateInstantiations) { |
5639 | 0 | std::cout << "mTemplateInstantiations[" << count++ << "]:" << std::endl; |
5640 | 0 | printOut(decl); |
5641 | 0 | } |
5642 | 0 | } |
5643 | | |
5644 | | void TemplateSimplifier::simplifyTemplates(const std::time_t maxtime) |
5645 | 790 | { |
5646 | | // convert "sizeof ..." to "sizeof..." |
5647 | 57.6k | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
5648 | 56.8k | if (match183(tok)) { |
5649 | 0 | tok->str("sizeof..."); |
5650 | 0 | tok->deleteNext(); |
5651 | 0 | } |
5652 | 56.8k | } |
5653 | | |
5654 | | // Remove "typename" unless used in template arguments or using type alias.. |
5655 | 57.6k | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
5656 | 56.8k | if (match184(tok) && !match185(tok->tokAt(-3))) |
5657 | 0 | tok->deleteThis(); |
5658 | | |
5659 | 56.8k | if (match40(tok)) { |
5660 | 0 | tok = tok->next()->findClosingBracket(); |
5661 | 0 | if (!tok) |
5662 | 0 | break; |
5663 | 0 | } |
5664 | 56.8k | } |
5665 | | |
5666 | 790 | if (mSettings.standards.cpp >= Standards::CPP20) { |
5667 | | // Remove concepts/requires |
5668 | | // TODO concepts are not removed yet |
5669 | 57.6k | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
5670 | 56.8k | if (!match186(tok)) |
5671 | 56.8k | continue; |
5672 | 0 | const Token* end = skipRequires(tok->next()); |
5673 | 0 | if (end) |
5674 | 0 | Token::eraseTokens(tok, end); |
5675 | 0 | } |
5676 | | |
5677 | | // explicit(bool) |
5678 | 57.6k | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
5679 | 56.8k | if (match187(tok)) { |
5680 | 0 | const bool isFalse = match188(tok->tokAt(2)); |
5681 | 0 | Token::eraseTokens(tok, tok->linkAt(1)->next()); |
5682 | 0 | if (isFalse) |
5683 | 0 | tok->deleteThis(); |
5684 | 0 | } |
5685 | 56.8k | } |
5686 | 790 | } |
5687 | | |
5688 | 790 | mTokenizer.calculateScopes(); |
5689 | | |
5690 | 790 | unsigned int passCount = 0; |
5691 | 790 | constexpr unsigned int passCountMax = 10; |
5692 | 790 | for (; passCount < passCountMax; ++passCount) { |
5693 | 790 | if (passCount) { |
5694 | | // it may take more than one pass to simplify type aliases |
5695 | 0 | bool usingChanged = false; |
5696 | 0 | while (mTokenizer.simplifyUsing()) |
5697 | 0 | usingChanged = true; |
5698 | |
|
5699 | 0 | if (!usingChanged && !mChanged) |
5700 | 0 | break; |
5701 | | |
5702 | 0 | mChanged = usingChanged; |
5703 | 0 | mTemplateDeclarations.clear(); |
5704 | 0 | mTemplateForwardDeclarations.clear(); |
5705 | 0 | mTemplateForwardDeclarationsMap.clear(); |
5706 | 0 | mTemplateSpecializationMap.clear(); |
5707 | 0 | mTemplatePartialSpecializationMap.clear(); |
5708 | 0 | mTemplateInstantiations.clear(); |
5709 | 0 | mInstantiatedTemplates.clear(); |
5710 | 0 | mExplicitInstantiationsToDelete.clear(); |
5711 | 0 | mTemplateNamePos.clear(); |
5712 | 0 | } |
5713 | | |
5714 | 790 | getTemplateDeclarations(); |
5715 | | |
5716 | 790 | if (passCount == 0) { |
5717 | 790 | mDump.clear(); |
5718 | 790 | for (const TokenAndName& t: mTemplateDeclarations) |
5719 | 0 | mDump += t.dump(mTokenizer.list.getFiles()); |
5720 | 790 | for (const TokenAndName& t: mTemplateForwardDeclarations) |
5721 | 0 | mDump += t.dump(mTokenizer.list.getFiles()); |
5722 | 790 | if (!mDump.empty()) |
5723 | 0 | mDump = " <TemplateSimplifier>\n" + mDump + " </TemplateSimplifier>\n"; |
5724 | 790 | } |
5725 | | |
5726 | | // Make sure there is something to simplify. |
5727 | 790 | if (mTemplateDeclarations.empty() && mTemplateForwardDeclarations.empty()) |
5728 | 790 | return; |
5729 | | |
5730 | 0 | if (mSettings.debugtemplate && mSettings.debugnormal) { |
5731 | 0 | std::string title("Template Simplifier pass " + std::to_string(passCount + 1)); |
5732 | 0 | mTokenList.front()->printOut(std::cout, false, title.c_str(), mTokenList.getFiles()); |
5733 | 0 | } |
5734 | | |
5735 | | // Copy default argument values from forward declaration to declaration |
5736 | 0 | fixForwardDeclaredDefaultArgumentValues(); |
5737 | | |
5738 | | // Locate user defined specializations. |
5739 | 0 | getSpecializations(); |
5740 | | |
5741 | | // Locate user defined partial specializations. |
5742 | 0 | getPartialSpecializations(); |
5743 | | |
5744 | | // Locate possible instantiations of templates.. |
5745 | 0 | getTemplateInstantiations(); |
5746 | | |
5747 | | // Template arguments with default values |
5748 | 0 | useDefaultArgumentValues(); |
5749 | |
|
5750 | 0 | simplifyTemplateAliases(); |
5751 | |
|
5752 | 0 | if (mSettings.debugtemplate) |
5753 | 0 | printOut("### Template Simplifier pass " + std::to_string(passCount + 1) + " ###"); |
5754 | | |
5755 | | // Keep track of the order the names appear so sort can preserve that order |
5756 | 0 | std::unordered_map<std::string, int> nameOrdinal; |
5757 | 0 | int ordinal = 0; |
5758 | 0 | for (const auto& decl : mTemplateDeclarations) { |
5759 | 0 | nameOrdinal.emplace(decl.fullName(), ordinal++); |
5760 | 0 | } |
5761 | |
|
5762 | 0 | auto score = [&](const Token* arg) { |
5763 | 0 | int i = 0; |
5764 | 0 | for (const Token* tok = arg; tok; tok = tok->next()) { |
5765 | 0 | if (tok->str() == MatchCompiler::makeConstString(",")) |
5766 | 0 | return i; |
5767 | 0 | if (tok->link() && match77(tok)) |
5768 | 0 | tok = tok->link(); |
5769 | 0 | else if (tok->str() == MatchCompiler::makeConstString("<")) { |
5770 | 0 | const Token* temp = tok->findClosingBracket(); |
5771 | 0 | if (temp) |
5772 | 0 | tok = temp; |
5773 | 0 | } else if (match189(tok)) |
5774 | 0 | return i; |
5775 | 0 | else if (match94(tok)) |
5776 | 0 | i--; |
5777 | 0 | } |
5778 | 0 | return 0; |
5779 | 0 | }; |
5780 | | // Sort so const parameters come first in the list |
5781 | 0 | mTemplateDeclarations.sort([&](const TokenAndName& x, const TokenAndName& y) { |
5782 | 0 | if (x.fullName() != y.fullName()) |
5783 | 0 | return nameOrdinal.at(x.fullName()) < nameOrdinal.at(y.fullName()); |
5784 | 0 | if (x.isFunction() && y.isFunction()) { |
5785 | 0 | std::vector<const Token*> xargs; |
5786 | 0 | getFunctionArguments(x.nameToken(), xargs); |
5787 | 0 | std::vector<const Token*> yargs; |
5788 | 0 | getFunctionArguments(y.nameToken(), yargs); |
5789 | 0 | if (xargs.size() != yargs.size()) |
5790 | 0 | return xargs.size() < yargs.size(); |
5791 | 0 | if (isConstMethod(x.nameToken()) != isConstMethod(y.nameToken())) |
5792 | 0 | return isConstMethod(x.nameToken()); |
5793 | 0 | return std::lexicographical_compare(xargs.begin(), |
5794 | 0 | xargs.end(), |
5795 | 0 | yargs.begin(), |
5796 | 0 | yargs.end(), |
5797 | 0 | [&](const Token* xarg, const Token* yarg) { |
5798 | 0 | if (xarg != yarg) |
5799 | 0 | return score(xarg) < score(yarg); |
5800 | 0 | return false; |
5801 | 0 | }); |
5802 | 0 | } |
5803 | 0 | return false; |
5804 | 0 | }); |
5805 | |
|
5806 | 0 | std::set<std::string> expandedtemplates; |
5807 | |
|
5808 | 0 | for (auto iter1 = mTemplateDeclarations.crbegin(); iter1 != mTemplateDeclarations.crend(); ++iter1) { |
5809 | 0 | if (iter1->isAlias() || iter1->isFriend()) |
5810 | 0 | continue; |
5811 | | |
5812 | | // get specializations.. |
5813 | 0 | std::list<const Token *> specializations; |
5814 | 0 | for (auto iter2 = mTemplateDeclarations.cbegin(); iter2 != mTemplateDeclarations.cend(); ++iter2) { |
5815 | 0 | if (iter2->isAlias() || iter2->isFriend()) |
5816 | 0 | continue; |
5817 | | |
5818 | 0 | if (iter1->fullName() == iter2->fullName()) |
5819 | 0 | specializations.push_back(iter2->nameToken()); |
5820 | 0 | } |
5821 | |
|
5822 | 0 | const bool instantiated = simplifyTemplateInstantiations( |
5823 | 0 | *iter1, |
5824 | 0 | specializations, |
5825 | 0 | maxtime, |
5826 | 0 | expandedtemplates); |
5827 | 0 | if (instantiated) { |
5828 | 0 | mInstantiatedTemplates.push_back(*iter1); |
5829 | 0 | mTemplateNamePos.clear(); // positions might be invalid after instantiations |
5830 | 0 | } |
5831 | 0 | } |
5832 | |
|
5833 | 0 | for (auto it = mInstantiatedTemplates.cbegin(); it != mInstantiatedTemplates.cend(); ++it) { |
5834 | 0 | auto decl = std::find_if(mTemplateDeclarations.begin(), mTemplateDeclarations.end(), [&it](const TokenAndName& decl) { |
5835 | 0 | return decl.token() == it->token(); |
5836 | 0 | }); |
5837 | 0 | if (decl != mTemplateDeclarations.end()) { |
5838 | 0 | if (it->isSpecialization()) { |
5839 | | // delete the "template < >" |
5840 | 0 | Token * tok = it->token(); |
5841 | 0 | tok->deleteNext(2); |
5842 | 0 | tok->deleteThis(); |
5843 | 0 | } else { |
5844 | | // remove forward declaration if found |
5845 | 0 | auto it1 = mTemplateForwardDeclarationsMap.find(it->token()); |
5846 | 0 | if (it1 != mTemplateForwardDeclarationsMap.end()) |
5847 | 0 | removeTemplate(it1->second, &mTemplateForwardDeclarationsMap); |
5848 | 0 | removeTemplate(it->token(), &mTemplateForwardDeclarationsMap); |
5849 | 0 | } |
5850 | 0 | mTemplateDeclarations.erase(decl); |
5851 | 0 | } |
5852 | 0 | } |
5853 | | |
5854 | | // remove out of line member functions |
5855 | 0 | while (!mMemberFunctionsToDelete.empty()) { |
5856 | 0 | const auto it = std::find_if(mTemplateDeclarations.begin(), |
5857 | 0 | mTemplateDeclarations.end(), |
5858 | 0 | FindToken(mMemberFunctionsToDelete.cbegin()->token())); |
5859 | | // multiple functions can share the same declaration so make sure it hasn't already been deleted |
5860 | 0 | if (it != mTemplateDeclarations.end()) { |
5861 | 0 | removeTemplate(it->token()); |
5862 | 0 | mTemplateDeclarations.erase(it); |
5863 | 0 | } else { |
5864 | 0 | const auto it1 = std::find_if(mTemplateForwardDeclarations.begin(), |
5865 | 0 | mTemplateForwardDeclarations.end(), |
5866 | 0 | FindToken(mMemberFunctionsToDelete.cbegin()->token())); |
5867 | | // multiple functions can share the same declaration so make sure it hasn't already been deleted |
5868 | 0 | if (it1 != mTemplateForwardDeclarations.end()) { |
5869 | 0 | removeTemplate(it1->token()); |
5870 | 0 | mTemplateForwardDeclarations.erase(it1); |
5871 | 0 | } |
5872 | 0 | } |
5873 | 0 | mMemberFunctionsToDelete.erase(mMemberFunctionsToDelete.begin()); |
5874 | 0 | } |
5875 | | |
5876 | | // remove explicit instantiations |
5877 | 0 | for (const TokenAndName& j : mExplicitInstantiationsToDelete) { |
5878 | 0 | Token * start = j.token(); |
5879 | 0 | if (start) { |
5880 | 0 | Token * end = start->next(); |
5881 | 0 | while (end && end->str() != MatchCompiler::makeConstString(";")) |
5882 | 0 | end = end->next(); |
5883 | 0 | if (start->previous()) |
5884 | 0 | start = start->previous(); |
5885 | 0 | if (end && end->next()) |
5886 | 0 | end = end->next(); |
5887 | 0 | eraseTokens(start, end); |
5888 | 0 | } |
5889 | 0 | } |
5890 | 0 | } |
5891 | | |
5892 | 0 | if (passCount == passCountMax) { |
5893 | 0 | if (mSettings.debugwarnings) { |
5894 | 0 | const std::list<const Token*> locationList(1, mTokenList.front()); |
5895 | 0 | const ErrorMessage errmsg(locationList, &mTokenizer.list, |
5896 | 0 | Severity::debug, |
5897 | 0 | "debug", |
5898 | 0 | "TemplateSimplifier: pass count limit hit before simplifications were finished.", |
5899 | 0 | Certainty::normal); |
5900 | 0 | mErrorLogger.reportErr(errmsg); |
5901 | 0 | } |
5902 | 0 | } |
5903 | | |
5904 | | // Tweak uninstantiated C++17 fold expressions (... && args) |
5905 | 0 | if (mSettings.standards.cpp >= Standards::CPP17) { |
5906 | 0 | bool simplify = false; |
5907 | 0 | for (Token *tok = mTokenList.front(); tok; tok = tok->next()) { |
5908 | 0 | if (tok->str() == MatchCompiler::makeConstString("template")) |
5909 | 0 | simplify = false; |
5910 | 0 | if (tok->str() == MatchCompiler::makeConstString("{")) |
5911 | 0 | simplify = true; |
5912 | 0 | if (!simplify || tok->str() != MatchCompiler::makeConstString("(")) |
5913 | 0 | continue; |
5914 | 0 | const Token *op = nullptr; |
5915 | 0 | const Token *args = nullptr; |
5916 | 0 | if (match190(tok)) { |
5917 | 0 | op = tok->tokAt(2); |
5918 | 0 | args = tok->link()->previous(); |
5919 | 0 | } else if (match191(tok)) { |
5920 | 0 | op = tok->tokAt(2); |
5921 | 0 | args = tok->link()->previous()->isName() ? nullptr : tok->next(); |
5922 | 0 | } else if (match192(tok->link()->tokAt(-3))) { |
5923 | 0 | op = tok->link()->tokAt(-2); |
5924 | 0 | args = tok->next(); |
5925 | 0 | } else if (match193(tok->link()->tokAt(-3))) { |
5926 | 0 | op = tok->link()->tokAt(-2); |
5927 | 0 | args = tok->next()->isName() ? nullptr : tok->link()->previous(); |
5928 | 0 | } else { |
5929 | 0 | continue; |
5930 | 0 | } |
5931 | | |
5932 | 0 | const std::string strop = op->str(); |
5933 | 0 | const std::string strargs = (args && args->isName()) ? args->str() : ""; |
5934 | |
|
5935 | 0 | Token::eraseTokens(tok, tok->link()); |
5936 | 0 | tok->insertToken(")"); |
5937 | 0 | if (!strargs.empty()) { |
5938 | 0 | tok->insertToken("..."); |
5939 | 0 | tok->insertToken(strargs); |
5940 | 0 | } |
5941 | 0 | tok->insertToken("("); |
5942 | 0 | Token::createMutualLinks(tok->next(), tok->link()->previous()); |
5943 | 0 | tok->insertToken("__cppcheck_fold_" + strop + "__"); |
5944 | 0 | } |
5945 | 0 | } |
5946 | 0 | } |
5947 | | |
5948 | | void TemplateSimplifier::syntaxError(const Token *tok) |
5949 | 0 | { |
5950 | 0 | throw InternalError(tok, "syntax error", InternalError::SYNTAX); |
5951 | 0 | } |