Coverage Report

Created: 2025-02-17 06:38

/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 *> &params)
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
}