1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2021 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "config.h"
20 #include "library.h"
21 #include "platform.h"
22 #include "settings.h"
23 #include "symboldatabase.h"
24 #include "testsuite.h"
25 #include "testutils.h"
26 #include "token.h"
27 #include "tokenize.h"
28 #include "tokenlist.h"
29 
30 #include <cstdint>
31 #include <cstring>
32 #include <limits>
33 #include <list>
34 #include <map>
35 #include <set>
36 #include <sstream>
37 #include <stdexcept>
38 #include <string>
39 #include <tinyxml2.h>
40 #include <vector>
41 
42 struct InternalError;
43 
44 #define GET_SYMBOL_DB_STD(code) \
45     Tokenizer tokenizer(&settings1, this); \
46     LOAD_LIB_2(settings1.library, "std.cfg"); \
47     const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.cpp"); \
48     ASSERT(db); \
49     do {} while (false)
50 
51 #define GET_SYMBOL_DB(code) \
52     Tokenizer tokenizer(&settings1, this); \
53     const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.cpp"); \
54     ASSERT(db); \
55     do {} while (false)
56 
57 #define GET_SYMBOL_DB_C(code) \
58     Tokenizer tokenizer(&settings1, this); \
59     const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.c"); \
60     do {} while (false)
61 
62 class TestSymbolDatabase : public TestFixture {
63 public:
TestSymbolDatabase()64     TestSymbolDatabase()
65         : TestFixture("TestSymbolDatabase")
66         ,nullScope(nullptr, nullptr, nullptr)
67         ,vartok(nullptr)
68         ,typetok(nullptr) {}
69 
70 private:
71     const Scope nullScope;
72     const Token* vartok;
73     const Token* typetok;
74     Settings settings1;
75     Settings settings2;
76 
reset()77     void reset() {
78         vartok = nullptr;
79         typetok = nullptr;
80     }
81 
getSymbolDB_inner(Tokenizer & tokenizer,const char * code,const char * filename)82     const static SymbolDatabase* getSymbolDB_inner(Tokenizer& tokenizer, const char* code, const char* filename) {
83         errout.str("");
84         std::istringstream istr(code);
85         tokenizer.tokenize(istr, filename);
86         return tokenizer.getSymbolDatabase();
87     }
88 
findFunctionScopeByToken(const SymbolDatabase * db,const Token * tok)89     static const Scope *findFunctionScopeByToken(const SymbolDatabase * db, const Token *tok) {
90         std::list<Scope>::const_iterator scope;
91 
92         for (scope = db->scopeList.begin(); scope != db->scopeList.end(); ++scope) {
93             if (scope->type == Scope::eFunction) {
94                 if (scope->classDef == tok)
95                     return &(*scope);
96             }
97         }
98         return nullptr;
99     }
100 
findFunctionByName(const char str[],const Scope * startScope)101     static const Function *findFunctionByName(const char str[], const Scope* startScope) {
102         const Scope* currScope = startScope;
103         while (currScope && currScope->isExecutable()) {
104             if (currScope->functionOf)
105                 currScope = currScope->functionOf;
106             else
107                 currScope = currScope->nestedIn;
108         }
109         while (currScope) {
110             for (const Function & i : currScope->functionList) {
111                 if (i.tokenDef->str() == str)
112                     return &i;
113             }
114             currScope = currScope->nestedIn;
115         }
116         return nullptr;
117     }
118 
run()119     void run() OVERRIDE {
120         LOAD_LIB_2(settings1.library, "std.cfg");
121         settings2.platform(Settings::Unspecified);
122 
123         // If there are unused templates, keep those
124         settings1.checkUnusedTemplates = true;
125         settings2.checkUnusedTemplates = true;
126 
127         TEST_CASE(array);
128         TEST_CASE(stlarray1);
129         TEST_CASE(stlarray2);
130 
131         TEST_CASE(test_isVariableDeclarationCanHandleNull);
132         TEST_CASE(test_isVariableDeclarationIdentifiesSimpleDeclaration);
133         TEST_CASE(test_isVariableDeclarationIdentifiesInitialization);
134         TEST_CASE(test_isVariableDeclarationIdentifiesCpp11Initialization);
135         TEST_CASE(test_isVariableDeclarationIdentifiesScopedDeclaration);
136         TEST_CASE(test_isVariableDeclarationIdentifiesStdDeclaration);
137         TEST_CASE(test_isVariableDeclarationIdentifiesScopedStdDeclaration);
138         TEST_CASE(test_isVariableDeclarationIdentifiesManyScopes);
139         TEST_CASE(test_isVariableDeclarationIdentifiesPointers);
140         TEST_CASE(test_isVariableDeclarationDoesNotIdentifyConstness);
141         TEST_CASE(test_isVariableDeclarationIdentifiesFirstOfManyVariables);
142         TEST_CASE(test_isVariableDeclarationIdentifiesScopedPointerDeclaration);
143         TEST_CASE(test_isVariableDeclarationIdentifiesDeclarationWithIndirection);
144         TEST_CASE(test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection);
145         TEST_CASE(test_isVariableDeclarationIdentifiesArray);
146         TEST_CASE(test_isVariableDeclarationIdentifiesPointerArray);
147         TEST_CASE(test_isVariableDeclarationIdentifiesOfArrayPointers);
148         TEST_CASE(isVariableDeclarationIdentifiesTemplatedPointerVariable);
149         TEST_CASE(isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable);
150         TEST_CASE(isVariableDeclarationIdentifiesTemplatedArrayVariable);
151         TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariable);
152         TEST_CASE(isVariableDeclarationIdentifiesTemplatedVariableIterator);
153         TEST_CASE(isVariableDeclarationIdentifiesNestedTemplateVariable);
154         TEST_CASE(isVariableDeclarationIdentifiesReference);
155         TEST_CASE(isVariableDeclarationDoesNotIdentifyTemplateClass);
156         TEST_CASE(isVariableDeclarationDoesNotIdentifyCppCast);
157         TEST_CASE(isVariableDeclarationPointerConst);
158         TEST_CASE(isVariableDeclarationRValueRef);
159         TEST_CASE(isVariableDeclarationDoesNotIdentifyCase);
160         TEST_CASE(isVariableDeclarationIf);
161         TEST_CASE(isVariableStlType);
162         TEST_CASE(isVariablePointerToConstPointer);
163         TEST_CASE(isVariablePointerToVolatilePointer);
164         TEST_CASE(isVariablePointerToConstVolatilePointer);
165         TEST_CASE(isVariableMultiplePointersAndQualifiers);
166         TEST_CASE(variableVolatile);
167         TEST_CASE(variableConstexpr);
168         TEST_CASE(isVariableDecltype);
169 
170         TEST_CASE(VariableValueType1);
171         TEST_CASE(VariableValueType2);
172         TEST_CASE(VariableValueType3);
173         TEST_CASE(VariableValueType4); // smart pointer type
174         TEST_CASE(VariableValueType5); // smart pointer type
175         TEST_CASE(VariableValueTypeReferences);
176 
177         TEST_CASE(findVariableType1);
178         TEST_CASE(findVariableType2);
179         TEST_CASE(findVariableType3);
180         TEST_CASE(findVariableTypeExternC);
181 
182         TEST_CASE(rangeBasedFor);
183 
184         TEST_CASE(arrayMemberVar1);
185         TEST_CASE(arrayMemberVar2);
186         TEST_CASE(arrayMemberVar3);
187         TEST_CASE(staticMemberVar);
188         TEST_CASE(getVariableFromVarIdBoundsCheck);
189 
190         TEST_CASE(hasRegularFunction);
191         TEST_CASE(hasRegularFunction_trailingReturnType);
192         TEST_CASE(hasInlineClassFunction);
193         TEST_CASE(hasInlineClassFunction_trailingReturnType);
194         TEST_CASE(hasMissingInlineClassFunction);
195         TEST_CASE(hasClassFunction);
196         TEST_CASE(hasClassFunction_trailingReturnType);
197 
198         TEST_CASE(hasRegularFunctionReturningFunctionPointer);
199         TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
200         TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer);
201         TEST_CASE(hasInlineClassOperatorTemplate);
202         TEST_CASE(hasClassFunctionReturningFunctionPointer);
203         TEST_CASE(methodWithRedundantScope);
204         TEST_CASE(complexFunctionArrayPtr);
205         TEST_CASE(pointerToMemberFunction);
206         TEST_CASE(hasSubClassConstructor);
207         TEST_CASE(testConstructors);
208         TEST_CASE(functionDeclarationTemplate);
209         TEST_CASE(functionDeclarations);
210         TEST_CASE(functionDeclarations2);
211         TEST_CASE(constexprFunction);
212         TEST_CASE(constructorInitialization);
213         TEST_CASE(memberFunctionOfUnknownClassMacro1);
214         TEST_CASE(memberFunctionOfUnknownClassMacro2);
215         TEST_CASE(memberFunctionOfUnknownClassMacro3);
216         TEST_CASE(functionLinkage);
217 
218         TEST_CASE(classWithFriend);
219 
220         TEST_CASE(parseFunctionCorrect);
221         TEST_CASE(parseFunctionDeclarationCorrect);
222         TEST_CASE(Cpp11InitInInitList);
223 
224         TEST_CASE(hasGlobalVariables1);
225         TEST_CASE(hasGlobalVariables2);
226         TEST_CASE(hasGlobalVariables3);
227 
228         TEST_CASE(checkTypeStartEndToken1);
229         TEST_CASE(checkTypeStartEndToken2); // handling for unknown macro: 'void f() MACRO {..'
230         TEST_CASE(checkTypeStartEndToken3); // no variable name: void f(const char){}
231 
232         TEST_CASE(functionArgs1);
233         TEST_CASE(functionArgs2);
234         TEST_CASE(functionArgs4);
235         TEST_CASE(functionArgs5); // #7650
236         TEST_CASE(functionArgs6); // #7651
237         TEST_CASE(functionArgs7); // #7652
238         TEST_CASE(functionArgs8); // #7653
239         TEST_CASE(functionArgs9); // #7657
240         TEST_CASE(functionArgs10);
241         TEST_CASE(functionArgs11);
242         TEST_CASE(functionArgs12); // #7661
243         TEST_CASE(functionArgs13); // #7697
244         TEST_CASE(functionArgs14); // #9055
245         TEST_CASE(functionArgs15); // #7159
246         TEST_CASE(functionArgs16); // #9591
247         TEST_CASE(functionArgs17);
248         TEST_CASE(functionArgs18); // #10376
249 
250         TEST_CASE(functionImplicitlyVirtual);
251 
252         TEST_CASE(functionIsInlineKeyword);
253 
254         TEST_CASE(functionStatic);
255 
256         TEST_CASE(functionReturnsReference); // Function::returnsReference
257 
258         TEST_CASE(namespaces1);
259         TEST_CASE(namespaces2);
260         TEST_CASE(namespaces3);  // #3854 - unknown macro
261         TEST_CASE(namespaces4);
262 
263         TEST_CASE(tryCatch1);
264 
265         TEST_CASE(symboldatabase1);
266         TEST_CASE(symboldatabase2);
267         TEST_CASE(symboldatabase3); // ticket #2000
268         TEST_CASE(symboldatabase4);
269         TEST_CASE(symboldatabase5); // ticket #2178
270         TEST_CASE(symboldatabase6); // ticket #2221
271         TEST_CASE(symboldatabase7); // ticket #2230
272         TEST_CASE(symboldatabase8); // ticket #2252
273         TEST_CASE(symboldatabase9); // ticket #2525
274         TEST_CASE(symboldatabase10); // ticket #2537
275         TEST_CASE(symboldatabase11); // ticket #2539
276         TEST_CASE(symboldatabase12); // ticket #2547
277         TEST_CASE(symboldatabase13); // ticket #2577
278         TEST_CASE(symboldatabase14); // ticket #2589
279         TEST_CASE(symboldatabase17); // ticket #2657
280         TEST_CASE(symboldatabase19); // ticket #2991 (segmentation fault)
281         TEST_CASE(symboldatabase20); // ticket #3013 (segmentation fault)
282         TEST_CASE(symboldatabase21);
283         TEST_CASE(symboldatabase22); // ticket #3437 (segmentation fault)
284         TEST_CASE(symboldatabase23); // ticket #3435
285         TEST_CASE(symboldatabase24); // ticket #3508 (constructor, destructor)
286         TEST_CASE(symboldatabase25); // ticket #3561 (throw C++)
287         TEST_CASE(symboldatabase26); // ticket #3561 (throw C)
288         TEST_CASE(symboldatabase27); // ticket #3543 (segmentation fault)
289         TEST_CASE(symboldatabase28);
290         TEST_CASE(symboldatabase29); // ticket #4442 (segmentation fault)
291         TEST_CASE(symboldatabase30);
292         TEST_CASE(symboldatabase31);
293         TEST_CASE(symboldatabase32);
294         TEST_CASE(symboldatabase33); // ticket #4682 (false negatives)
295         TEST_CASE(symboldatabase34); // ticket #4694 (segmentation fault)
296         TEST_CASE(symboldatabase35); // ticket #4806 (segmentation fault)
297         TEST_CASE(symboldatabase36); // ticket #4892 (segmentation fault)
298         TEST_CASE(symboldatabase37);
299         TEST_CASE(symboldatabase38); // ticket #5125 (infinite recursion)
300         TEST_CASE(symboldatabase40); // ticket #5153
301         TEST_CASE(symboldatabase41); // ticket #5197 (unknown macro)
302         TEST_CASE(symboldatabase42); // only put variables in variable list
303         TEST_CASE(symboldatabase43); // #4738
304         TEST_CASE(symboldatabase44);
305         TEST_CASE(symboldatabase45); // #6125
306         TEST_CASE(symboldatabase46); // #6171 (anonymous namespace)
307         TEST_CASE(symboldatabase47); // #6308
308         TEST_CASE(symboldatabase48); // #6417
309         TEST_CASE(symboldatabase49); // #6424
310         TEST_CASE(symboldatabase50); // #6432
311         TEST_CASE(symboldatabase51); // #6538
312         TEST_CASE(symboldatabase52); // #6581
313         TEST_CASE(symboldatabase53); // #7124 (library podtype)
314         TEST_CASE(symboldatabase54); // #7257
315         TEST_CASE(symboldatabase55); // #7767 (return unknown macro)
316         TEST_CASE(symboldatabase56); // #7909
317         TEST_CASE(symboldatabase57);
318         TEST_CASE(symboldatabase58); // #6985 (using namespace type lookup)
319         TEST_CASE(symboldatabase59);
320         TEST_CASE(symboldatabase60);
321         TEST_CASE(symboldatabase61);
322         TEST_CASE(symboldatabase62);
323         TEST_CASE(symboldatabase63);
324         TEST_CASE(symboldatabase64);
325         TEST_CASE(symboldatabase65);
326         TEST_CASE(symboldatabase66); // #8540
327         TEST_CASE(symboldatabase67); // #8538
328         TEST_CASE(symboldatabase68); // #8560
329         TEST_CASE(symboldatabase69);
330         TEST_CASE(symboldatabase70);
331         TEST_CASE(symboldatabase71);
332         TEST_CASE(symboldatabase72); // #8600
333         TEST_CASE(symboldatabase74); // #8838 - final
334         TEST_CASE(symboldatabase75);
335         TEST_CASE(symboldatabase76); // #9056
336         TEST_CASE(symboldatabase77); // #8663
337         TEST_CASE(symboldatabase78); // #9147
338         TEST_CASE(symboldatabase79); // #9392
339         TEST_CASE(symboldatabase80); // #9389
340         TEST_CASE(symboldatabase81); // #9411
341         TEST_CASE(symboldatabase82);
342         TEST_CASE(symboldatabase83); // #9431
343         TEST_CASE(symboldatabase84);
344         TEST_CASE(symboldatabase85);
345         TEST_CASE(symboldatabase86);
346         TEST_CASE(symboldatabase87); // #9922 'extern const char ( * x [ 256 ] ) ;'
347         TEST_CASE(symboldatabase88); // #10040 (using namespace)
348         TEST_CASE(symboldatabase89); // valuetype name
349         TEST_CASE(symboldatabase90);
350         TEST_CASE(symboldatabase91);
351         TEST_CASE(symboldatabase92); // daca crash
352         TEST_CASE(symboldatabase93); // alignas attribute
353         TEST_CASE(symboldatabase94); // structured bindings
354         TEST_CASE(symboldatabase95); // #10295
355 
356         TEST_CASE(createSymbolDatabaseFindAllScopes1);
357         TEST_CASE(createSymbolDatabaseFindAllScopes2);
358         TEST_CASE(createSymbolDatabaseFindAllScopes3);
359 
360         TEST_CASE(enum1);
361         TEST_CASE(enum2);
362         TEST_CASE(enum3);
363         TEST_CASE(enum4);
364         TEST_CASE(enum5);
365         TEST_CASE(enum6);
366         TEST_CASE(enum7);
367         TEST_CASE(enum8);
368         TEST_CASE(enum9);
369 
370         TEST_CASE(sizeOfType);
371 
372         TEST_CASE(isImplicitlyVirtual);
373         TEST_CASE(isPure);
374 
375         TEST_CASE(isFunction1); // UNKNOWN_MACRO(a,b) { .. }
376         TEST_CASE(isFunction2);
377 
378         TEST_CASE(findFunction1);
379         TEST_CASE(findFunction2); // mismatch: parameter passed by address => reference argument
380         TEST_CASE(findFunction3);
381         TEST_CASE(findFunction4);
382         TEST_CASE(findFunction5); // #6230
383         TEST_CASE(findFunction6);
384         TEST_CASE(findFunction7); // #6700
385         TEST_CASE(findFunction8);
386         TEST_CASE(findFunction9);
387         TEST_CASE(findFunction10); // #7673
388         TEST_CASE(findFunction11);
389         TEST_CASE(findFunction12);
390         TEST_CASE(findFunction13);
391         TEST_CASE(findFunction14);
392         TEST_CASE(findFunction15);
393         TEST_CASE(findFunction16);
394         TEST_CASE(findFunction17);
395         TEST_CASE(findFunction18);
396         TEST_CASE(findFunction19);
397         TEST_CASE(findFunction20); // #8280
398         TEST_CASE(findFunction21);
399         TEST_CASE(findFunction22);
400         TEST_CASE(findFunction23);
401         TEST_CASE(findFunction24); // smart pointer
402         TEST_CASE(findFunction25); // std::vector<std::shared_ptr<Fred>>
403         TEST_CASE(findFunction26); // #8668 - pointer parameter in function call, const pointer function argument
404         TEST_CASE(findFunction27);
405         TEST_CASE(findFunction28);
406         TEST_CASE(findFunction29);
407         TEST_CASE(findFunction30);
408         TEST_CASE(findFunction31);
409         TEST_CASE(findFunction32); // C: relax type matching
410         TEST_CASE(findFunction33); // #9885 variadic function
411         TEST_CASE(findFunction34); // #10061
412         TEST_CASE(findFunction35);
413         TEST_CASE(findFunction36); // #10122
414         TEST_CASE(findFunction37); // #10124
415         TEST_CASE(findFunction38); // #10125
416         TEST_CASE(findFunction39); // #10127
417         TEST_CASE(findFunction40); // #10135
418         TEST_CASE(findFunction41); // #10202
419         TEST_CASE(findFunction42);
420         TEST_CASE(findFunction43); // #10087
421         TEST_CASE(findFunctionContainer);
422         TEST_CASE(findFunctionExternC);
423         TEST_CASE(findFunctionGlobalScope); // ::foo
424 
425         TEST_CASE(overloadedFunction1);
426 
427         TEST_CASE(valueTypeMatchParameter); // ValueType::matchParameter
428 
429         TEST_CASE(noexceptFunction1);
430         TEST_CASE(noexceptFunction2);
431         TEST_CASE(noexceptFunction3);
432         TEST_CASE(noexceptFunction4);
433 
434         TEST_CASE(throwFunction1);
435         TEST_CASE(throwFunction2);
436 
437         TEST_CASE(nothrowAttributeFunction);
438         TEST_CASE(nothrowDeclspecFunction);
439 
440         TEST_CASE(noreturnAttributeFunction);
441         TEST_CASE(nodiscardAttributeFunction);
442 
443         TEST_CASE(varTypesIntegral); // known integral
444         TEST_CASE(varTypesFloating); // known floating
445         TEST_CASE(varTypesOther);    // (un)known
446 
447         TEST_CASE(functionPrototype); // #5867
448 
449         TEST_CASE(lambda); // #5867
450         TEST_CASE(lambda2); // #7473
451         TEST_CASE(lambda3);
452 
453         TEST_CASE(circularDependencies); // #6298
454 
455         TEST_CASE(executableScopeWithUnknownFunction);
456 
457         TEST_CASE(valuetype);
458 
459         TEST_CASE(variadic1); // #7453
460         TEST_CASE(variadic2); // #7649
461         TEST_CASE(variadic3); // #7387
462 
463         TEST_CASE(noReturnType);
464 
465         TEST_CASE(auto1);
466         TEST_CASE(auto2);
467         TEST_CASE(auto3);
468         TEST_CASE(auto4);
469         TEST_CASE(auto5);
470         TEST_CASE(auto6); // #7963 (segmentation fault)
471         TEST_CASE(auto7);
472         TEST_CASE(auto8);
473         TEST_CASE(auto9); // #8044 (segmentation fault)
474         TEST_CASE(auto10); // #8020
475         TEST_CASE(auto11); // #8964 - const auto startX = x;
476         TEST_CASE(auto12); // #8993 - const std::string &x; auto y = x; if (y.empty()) ..
477         TEST_CASE(auto13);
478         TEST_CASE(auto14);
479         TEST_CASE(auto15); // C++17 auto deduction from braced-init-list
480 
481         TEST_CASE(unionWithConstructor);
482 
483         TEST_CASE(incomplete_type); // #9255 (infinite recursion)
484     }
485 
array()486     void array() {
487         GET_SYMBOL_DB_C("int a[10+2];");
488         ASSERT(db != nullptr);
489 
490         ASSERT(db->variableList().size() == 2); // the first one is not used
491         const Variable * v = db->getVariableFromVarId(1);
492         ASSERT(v != nullptr);
493 
494         ASSERT(v->isArray());
495         ASSERT_EQUALS(1U, v->dimensions().size());
496         ASSERT_EQUALS(12U, v->dimension(0));
497     }
498 
stlarray1()499     void stlarray1() {
500         GET_SYMBOL_DB("std::array<int, 16 + 4> arr;");
501         ASSERT(db != nullptr);
502 
503         ASSERT_EQUALS(2, db->variableList().size()); // the first one is not used
504         const Variable * v = db->getVariableFromVarId(1);
505         ASSERT(v != nullptr);
506 
507         ASSERT(v->isArray());
508         ASSERT_EQUALS(1U, v->dimensions().size());
509         ASSERT_EQUALS(20U, v->dimension(0));
510     }
511 
stlarray2()512     void stlarray2() {
513         GET_SYMBOL_DB("constexpr int sz = 16; std::array<int, sz + 4> arr;");
514         ASSERT(db != nullptr);
515 
516         ASSERT_EQUALS(3, db->variableList().size()); // the first one is not used
517         const Variable * v = db->getVariableFromVarId(2);
518         ASSERT(v != nullptr);
519 
520         ASSERT(v->isArray());
521         ASSERT_EQUALS(1U, v->dimensions().size());
522         ASSERT_EQUALS(20U, v->dimension(0));
523     }
524 
test_isVariableDeclarationCanHandleNull()525     void test_isVariableDeclarationCanHandleNull() {
526         reset();
527         const bool result = nullScope.isVariableDeclaration(nullptr, vartok, typetok);
528         ASSERT_EQUALS(false, result);
529         ASSERT(nullptr == vartok);
530         ASSERT(nullptr == typetok);
531         Variable v(nullptr, nullptr, nullptr, 0, AccessControl::Public, nullptr, nullptr, &settings1);
532     }
533 
test_isVariableDeclarationIdentifiesSimpleDeclaration()534     void test_isVariableDeclarationIdentifiesSimpleDeclaration() {
535         reset();
536         givenACodeSampleToTokenize simpleDeclaration("int x;");
537         const bool result = nullScope.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok);
538         ASSERT_EQUALS(true, result);
539         ASSERT_EQUALS("x", vartok->str());
540         ASSERT_EQUALS("int", typetok->str());
541         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
542         ASSERT(false == v.isArray());
543         ASSERT(false == v.isPointer());
544         ASSERT(false == v.isReference());
545     }
546 
test_isVariableDeclarationIdentifiesInitialization()547     void test_isVariableDeclarationIdentifiesInitialization() {
548         reset();
549         givenACodeSampleToTokenize simpleDeclaration("int x (1);");
550         const bool result = nullScope.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok);
551         ASSERT_EQUALS(true, result);
552         ASSERT_EQUALS("x", vartok->str());
553         ASSERT_EQUALS("int", typetok->str());
554         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
555         ASSERT(false == v.isArray());
556         ASSERT(false == v.isPointer());
557         ASSERT(false == v.isReference());
558     }
559 
test_isVariableDeclarationIdentifiesCpp11Initialization()560     void test_isVariableDeclarationIdentifiesCpp11Initialization() {
561         reset();
562         givenACodeSampleToTokenize simpleDeclaration("int x {1};");
563         const bool result = nullScope.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok);
564         ASSERT_EQUALS(true, result);
565         ASSERT_EQUALS("x", vartok->str());
566         ASSERT_EQUALS("int", typetok->str());
567         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
568         ASSERT(false == v.isArray());
569         ASSERT(false == v.isPointer());
570         ASSERT(false == v.isReference());
571     }
572 
test_isVariableDeclarationIdentifiesScopedDeclaration()573     void test_isVariableDeclarationIdentifiesScopedDeclaration() {
574         reset();
575         givenACodeSampleToTokenize ScopedDeclaration("::int x;");
576         const bool result = nullScope.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok);
577         ASSERT_EQUALS(true, result);
578         ASSERT_EQUALS("x", vartok->str());
579         ASSERT_EQUALS("int", typetok->str());
580         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
581         ASSERT(false == v.isArray());
582         ASSERT(false == v.isPointer());
583         ASSERT(false == v.isReference());
584     }
585 
test_isVariableDeclarationIdentifiesStdDeclaration()586     void test_isVariableDeclarationIdentifiesStdDeclaration() {
587         reset();
588         givenACodeSampleToTokenize StdDeclaration("std::string x;");
589         const bool result = nullScope.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok);
590         ASSERT_EQUALS(true, result);
591         ASSERT_EQUALS("x", vartok->str());
592         ASSERT_EQUALS("string", typetok->str());
593         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
594         ASSERT(false == v.isArray());
595         ASSERT(false == v.isPointer());
596         ASSERT(false == v.isReference());
597     }
598 
test_isVariableDeclarationIdentifiesScopedStdDeclaration()599     void test_isVariableDeclarationIdentifiesScopedStdDeclaration() {
600         reset();
601         givenACodeSampleToTokenize StdDeclaration("::std::string x;");
602         const bool result = nullScope.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok);
603         ASSERT_EQUALS(true, result);
604         ASSERT_EQUALS("x", vartok->str());
605         ASSERT_EQUALS("string", typetok->str());
606         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
607         ASSERT(false == v.isArray());
608         ASSERT(false == v.isPointer());
609         ASSERT(false == v.isReference());
610     }
611 
test_isVariableDeclarationIdentifiesManyScopes()612     void test_isVariableDeclarationIdentifiesManyScopes() {
613         reset();
614         givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;");
615         const bool result = nullScope.isVariableDeclaration(manyScopes.tokens(), vartok, typetok);
616         ASSERT_EQUALS(true, result);
617         ASSERT_EQUALS("x", vartok->str());
618         ASSERT_EQUALS("EE", typetok->str());
619         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
620         ASSERT(false == v.isArray());
621         ASSERT(false == v.isPointer());
622         ASSERT(false == v.isReference());
623     }
624 
test_isVariableDeclarationIdentifiesPointers()625     void test_isVariableDeclarationIdentifiesPointers() {
626         reset();
627         givenACodeSampleToTokenize pointer("int* p;");
628         const bool result1 = nullScope.isVariableDeclaration(pointer.tokens(), vartok, typetok);
629         ASSERT_EQUALS(true, result1);
630         ASSERT_EQUALS("p", vartok->str());
631         ASSERT_EQUALS("int", typetok->str());
632         Variable v1(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
633         ASSERT(false == v1.isArray());
634         ASSERT(true == v1.isPointer());
635         ASSERT(false == v1.isReference());
636 
637         reset();
638         givenACodeSampleToTokenize constpointer("const int* p;");
639         Variable v2(constpointer.tokens()->tokAt(3), constpointer.tokens()->next(), constpointer.tokens()->tokAt(2), 0, AccessControl::Public, nullptr, nullptr, &settings1);
640         ASSERT(false == v2.isArray());
641         ASSERT(true == v2.isPointer());
642         ASSERT(false == v2.isConst());
643         ASSERT(false == v2.isReference());
644 
645         reset();
646         givenACodeSampleToTokenize pointerconst("int* const p;");
647         const bool result2 = nullScope.isVariableDeclaration(pointerconst.tokens(), vartok, typetok);
648         ASSERT_EQUALS(true, result2);
649         ASSERT_EQUALS("p", vartok->str());
650         ASSERT_EQUALS("int", typetok->str());
651         Variable v3(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
652         ASSERT(false == v3.isArray());
653         ASSERT(true == v3.isPointer());
654         ASSERT(true == v3.isConst());
655         ASSERT(false == v3.isReference());
656     }
657 
test_isVariableDeclarationDoesNotIdentifyConstness()658     void test_isVariableDeclarationDoesNotIdentifyConstness() {
659         reset();
660         givenACodeSampleToTokenize constness("const int* cp;");
661         const bool result = nullScope.isVariableDeclaration(constness.tokens(), vartok, typetok);
662         ASSERT_EQUALS(false, result);
663         ASSERT(nullptr == vartok);
664         ASSERT(nullptr == typetok);
665     }
666 
test_isVariableDeclarationIdentifiesFirstOfManyVariables()667     void test_isVariableDeclarationIdentifiesFirstOfManyVariables() {
668         reset();
669         givenACodeSampleToTokenize multipleDeclaration("int first, second;");
670         const bool result = nullScope.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok);
671         ASSERT_EQUALS(true, result);
672         ASSERT_EQUALS("first", vartok->str());
673         ASSERT_EQUALS("int", typetok->str());
674         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
675         ASSERT(false == v.isArray());
676         ASSERT(false == v.isPointer());
677         ASSERT(false == v.isReference());
678     }
679 
test_isVariableDeclarationIdentifiesScopedPointerDeclaration()680     void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() {
681         reset();
682         givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;");
683         const bool result = nullScope.isVariableDeclaration(manyScopes.tokens(), vartok, typetok);
684         ASSERT_EQUALS(true, result);
685         ASSERT_EQUALS("p", vartok->str());
686         ASSERT_EQUALS("EE", typetok->str());
687         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
688         ASSERT(false == v.isArray());
689         ASSERT(true == v.isPointer());
690         ASSERT(false == v.isReference());
691     }
692 
test_isVariableDeclarationIdentifiesDeclarationWithIndirection()693     void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() {
694         reset();
695         givenACodeSampleToTokenize pointerToPointer("int** pp;");
696         const bool result = nullScope.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok);
697         ASSERT_EQUALS(true, result);
698         ASSERT_EQUALS("pp", vartok->str());
699         ASSERT_EQUALS("int", typetok->str());
700         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
701         ASSERT(false == v.isArray());
702         ASSERT(true == v.isPointer());
703         ASSERT(false == v.isReference());
704     }
705 
test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection()706     void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() {
707         reset();
708         givenACodeSampleToTokenize pointerToPointer("int***** p;");
709         const bool result = nullScope.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok);
710         ASSERT_EQUALS(true, result);
711         ASSERT_EQUALS("p", vartok->str());
712         ASSERT_EQUALS("int", typetok->str());
713         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
714         ASSERT(false == v.isArray());
715         ASSERT(true == v.isPointer());
716         ASSERT(false == v.isReference());
717     }
718 
test_isVariableDeclarationIdentifiesArray()719     void test_isVariableDeclarationIdentifiesArray() {
720         reset();
721         givenACodeSampleToTokenize arr("::std::string v[3];");
722         const bool result = nullScope.isVariableDeclaration(arr.tokens(), vartok, typetok);
723         ASSERT_EQUALS(true, result);
724         ASSERT_EQUALS("v", vartok->str());
725         ASSERT_EQUALS("string", typetok->str());
726         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
727         ASSERT(true == v.isArray());
728         ASSERT(false == v.isPointer());
729         ASSERT(false == v.isPointerArray());
730         ASSERT(false == v.isReference());
731     }
732 
test_isVariableDeclarationIdentifiesPointerArray()733     void test_isVariableDeclarationIdentifiesPointerArray() {
734         reset();
735         givenACodeSampleToTokenize arr("A *a[5];");
736         const bool result = nullScope.isVariableDeclaration(arr.tokens(), vartok, typetok);
737         ASSERT_EQUALS(true, result);
738         ASSERT_EQUALS("a", vartok->str());
739         ASSERT_EQUALS("A", typetok->str());
740         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
741         ASSERT(false == v.isPointer());
742         ASSERT(true == v.isArray());
743         ASSERT(false == v.isPointerToArray());
744         ASSERT(true == v.isPointerArray());
745         ASSERT(false == v.isReference());
746     }
747 
test_isVariableDeclarationIdentifiesOfArrayPointers()748     void test_isVariableDeclarationIdentifiesOfArrayPointers() {
749         reset();
750         givenACodeSampleToTokenize arr("A (*a)[5];");
751         const bool result = nullScope.isVariableDeclaration(arr.tokens(), vartok, typetok);
752         ASSERT_EQUALS(true, result);
753         ASSERT_EQUALS("a", vartok->str());
754         ASSERT_EQUALS("A", typetok->str());
755         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
756         ASSERT(true == v.isPointer());
757         ASSERT(false == v.isArray());
758         ASSERT(true == v.isPointerToArray());
759         ASSERT(false == v.isPointerArray());
760         ASSERT(false == v.isReference());
761     }
762 
isVariableDeclarationIdentifiesTemplatedPointerVariable()763     void isVariableDeclarationIdentifiesTemplatedPointerVariable() {
764         reset();
765         givenACodeSampleToTokenize var("std::set<char>* chars;");
766         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
767         ASSERT_EQUALS(true, result);
768         ASSERT_EQUALS("chars", vartok->str());
769         ASSERT_EQUALS("set", typetok->str());
770         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
771         ASSERT(false == v.isArray());
772         ASSERT(true == v.isPointer());
773         ASSERT(false == v.isReference());
774     }
775 
isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable()776     void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() {
777         reset();
778         givenACodeSampleToTokenize var("std::deque<int>*** ints;");
779         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
780         ASSERT_EQUALS(true, result);
781         ASSERT_EQUALS("ints", vartok->str());
782         ASSERT_EQUALS("deque", typetok->str());
783         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
784         ASSERT(false == v.isArray());
785         ASSERT(true == v.isPointer());
786         ASSERT(false == v.isReference());
787     }
788 
isVariableDeclarationIdentifiesTemplatedArrayVariable()789     void isVariableDeclarationIdentifiesTemplatedArrayVariable() {
790         reset();
791         givenACodeSampleToTokenize var("std::deque<int> ints[3];");
792         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
793         ASSERT_EQUALS(true, result);
794         ASSERT_EQUALS("ints", vartok->str());
795         ASSERT_EQUALS("deque", typetok->str());
796         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
797         ASSERT(true == v.isArray());
798         ASSERT(false == v.isPointer());
799         ASSERT(false == v.isReference());
800     }
801 
isVariableDeclarationIdentifiesTemplatedVariable()802     void isVariableDeclarationIdentifiesTemplatedVariable() {
803         reset();
804         givenACodeSampleToTokenize var("std::vector<int> ints;");
805         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
806         ASSERT_EQUALS(true, result);
807         ASSERT_EQUALS("ints", vartok->str());
808         ASSERT_EQUALS("vector", typetok->str());
809         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
810         ASSERT(false == v.isArray());
811         ASSERT(false == v.isPointer());
812         ASSERT(false == v.isReference());
813     }
814 
isVariableDeclarationIdentifiesTemplatedVariableIterator()815     void isVariableDeclarationIdentifiesTemplatedVariableIterator() {
816         reset();
817         givenACodeSampleToTokenize var("std::list<int>::const_iterator floats;");
818         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
819         ASSERT_EQUALS(true, result);
820         ASSERT_EQUALS("floats", vartok->str());
821         ASSERT_EQUALS("const_iterator", typetok->str());
822         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
823         ASSERT(false == v.isArray());
824         ASSERT(false == v.isPointer());
825         ASSERT(false == v.isReference());
826     }
827 
isVariableDeclarationIdentifiesNestedTemplateVariable()828     void isVariableDeclarationIdentifiesNestedTemplateVariable() {
829         reset();
830         givenACodeSampleToTokenize var("std::deque<std::set<int> > intsets;");
831         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
832         ASSERT_EQUALS(true, result);
833         ASSERT_EQUALS("intsets", vartok->str());
834         ASSERT_EQUALS("deque", typetok->str());
835         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
836         ASSERT(false == v.isArray());
837         ASSERT(false == v.isPointer());
838         ASSERT(false == v.isReference());
839     }
840 
isVariableDeclarationIdentifiesReference()841     void isVariableDeclarationIdentifiesReference() {
842         reset();
843         givenACodeSampleToTokenize var1("int& foo;");
844         const bool result1 = nullScope.isVariableDeclaration(var1.tokens(), vartok, typetok);
845         ASSERT_EQUALS(true, result1);
846         Variable v1(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
847         ASSERT(false == v1.isArray());
848         ASSERT(false == v1.isPointer());
849         ASSERT(true == v1.isReference());
850 
851         reset();
852         givenACodeSampleToTokenize var2("foo*& bar;");
853         const bool result2 = nullScope.isVariableDeclaration(var2.tokens(), vartok, typetok);
854         ASSERT_EQUALS(true, result2);
855         Variable v2(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
856         ASSERT(false == v2.isArray());
857         ASSERT(true == v2.isPointer());
858         ASSERT(true == v2.isReference());
859 
860         reset();
861         givenACodeSampleToTokenize var3("std::vector<int>& foo;");
862         const bool result3 = nullScope.isVariableDeclaration(var3.tokens(), vartok, typetok);
863         ASSERT_EQUALS(true, result3);
864         Variable v3(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
865         ASSERT(false == v3.isArray());
866         ASSERT(false == v3.isPointer());
867         ASSERT(true == v3.isReference());
868     }
869 
isVariableDeclarationDoesNotIdentifyTemplateClass()870     void isVariableDeclarationDoesNotIdentifyTemplateClass() {
871         reset();
872         givenACodeSampleToTokenize var("template <class T> class SomeClass{};");
873         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
874         ASSERT_EQUALS(false, result);
875     }
876 
isVariableDeclarationDoesNotIdentifyCppCast()877     void isVariableDeclarationDoesNotIdentifyCppCast() {
878         reset();
879         givenACodeSampleToTokenize var("reinterpret_cast <char *> (code)[0] = 0;");
880         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
881         ASSERT_EQUALS(false, result);
882     }
883 
isVariableDeclarationPointerConst()884     void isVariableDeclarationPointerConst() {
885         reset();
886         givenACodeSampleToTokenize var("std::string const* s;");
887         const bool result = nullScope.isVariableDeclaration(var.tokens()->next(), vartok, typetok);
888         ASSERT_EQUALS(true, result);
889         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
890         ASSERT(false == v.isArray());
891         ASSERT(true == v.isPointer());
892         ASSERT(false == v.isReference());
893     }
894 
isVariableDeclarationRValueRef()895     void isVariableDeclarationRValueRef() {
896         reset();
897         givenACodeSampleToTokenize var("int&& i;");
898         const bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
899         ASSERT_EQUALS(true, result);
900         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
901         ASSERT(false == v.isArray());
902         ASSERT(false == v.isPointer());
903         ASSERT(true == v.isReference());
904         ASSERT(true == v.isRValueReference());
905         ASSERT(var.tokens()->tokAt(2)->scope() != nullptr);
906     }
907 
isVariableDeclarationDoesNotIdentifyCase()908     void isVariableDeclarationDoesNotIdentifyCase() {
909         GET_SYMBOL_DB_C("a b;\n"
910                         "void f() {\n"
911                         "  switch (c) {\n"
912                         "    case b:;\n"
913                         "  }"
914                         "}");
915         const Variable* b = db->getVariableFromVarId(1);
916         ASSERT_EQUALS("b", b->name());
917         ASSERT_EQUALS("a", b->typeStartToken()->str());
918     }
919 
isVariableDeclarationIf()920     void isVariableDeclarationIf() {
921         GET_SYMBOL_DB("void foo() {\n"
922                       "    for (auto& elem : items) {\n"
923                       "        if (auto x = bar()) { int y = 3; }\n"
924                       "    }\n"
925                       "}");
926         const Token *x = Token::findsimplematch(tokenizer.tokens(), "x");
927         ASSERT(x);
928         ASSERT(x->varId());
929         ASSERT(x->variable());
930 
931         const Token *y = Token::findsimplematch(tokenizer.tokens(), "y");
932         ASSERT(y);
933         ASSERT(y->varId());
934         ASSERT(y->variable());
935     }
936 
VariableValueType1()937     void VariableValueType1() {
938         GET_SYMBOL_DB("typedef uint8_t u8;\n"
939                       "static u8 x;");
940         const Variable* x = db->getVariableFromVarId(1);
941         ASSERT_EQUALS("x", x->name());
942         ASSERT(x->valueType()->isIntegral());
943     }
944 
VariableValueType2()945     void VariableValueType2() {
946         GET_SYMBOL_DB("using u8 = uint8_t;\n"
947                       "static u8 x;");
948         const Variable* x = db->getVariableFromVarId(1);
949         ASSERT_EQUALS("x", x->name());
950         ASSERT(x->valueType()->isIntegral());
951     }
952 
VariableValueType3()953     void VariableValueType3() {
954         // std::string::size_type
955         {
956             GET_SYMBOL_DB("void f(std::string::size_type x);");
957             const Variable* const x = db->getVariableFromVarId(1);
958             ASSERT_EQUALS("x", x->name());
959             // TODO: Configure std::string::size_type somehow.
960             TODO_ASSERT_EQUALS(ValueType::Type::LONGLONG, ValueType::Type::UNKNOWN_INT, x->valueType()->type);
961             ASSERT_EQUALS(ValueType::Sign::UNSIGNED, x->valueType()->sign);
962         }
963         // std::wstring::size_type
964         {
965             GET_SYMBOL_DB("void f(std::wstring::size_type x);");
966             const Variable* const x = db->getVariableFromVarId(1);
967             ASSERT_EQUALS("x", x->name());
968             // TODO: Configure std::wstring::size_type somehow.
969             TODO_ASSERT_EQUALS(ValueType::Type::LONGLONG, ValueType::Type::UNKNOWN_INT, x->valueType()->type);
970             ASSERT_EQUALS(ValueType::Sign::UNSIGNED, x->valueType()->sign);
971         }
972         // std::u16string::size_type
973         {
974             GET_SYMBOL_DB("void f(std::u16string::size_type x);");
975             const Variable* const x = db->getVariableFromVarId(1);
976             ASSERT_EQUALS("x", x->name());
977             // TODO: Configure std::u16string::size_type somehow.
978             TODO_ASSERT_EQUALS(ValueType::Type::LONGLONG, ValueType::Type::UNKNOWN_INT, x->valueType()->type);
979             ASSERT_EQUALS(ValueType::Sign::UNSIGNED, x->valueType()->sign);
980         }
981         // std::u32string::size_type
982         {
983             GET_SYMBOL_DB("void f(std::u32string::size_type x);");
984             const Variable* const x = db->getVariableFromVarId(1);
985             ASSERT_EQUALS("x", x->name());
986             // TODO: Configure std::u32string::size_type somehow.
987             TODO_ASSERT_EQUALS(ValueType::Type::LONGLONG, ValueType::Type::UNKNOWN_INT, x->valueType()->type);
988             ASSERT_EQUALS(ValueType::Sign::UNSIGNED, x->valueType()->sign);
989         }
990     }
991 
VariableValueType4()992     void VariableValueType4() {
993         GET_SYMBOL_DB("class C {\n"
994                       "public:\n"
995                       "  std::shared_ptr<C> x;\n"
996                       "};");
997 
998         const Variable* const x = db->getVariableFromVarId(1);
999         ASSERT(x->valueType());
1000         ASSERT(x->valueType()->smartPointerType);
1001     }
1002 
VariableValueType5()1003     void VariableValueType5() {
1004         GET_SYMBOL_DB("class C {};\n"
1005                       "void foo(std::shared_ptr<C>* p) {}");
1006 
1007         const Variable* const p = db->getVariableFromVarId(1);
1008         ASSERT(p->valueType());
1009         ASSERT(p->valueType()->smartPointerTypeToken);
1010         ASSERT(p->valueType()->pointer == 1);
1011     }
1012 
VariableValueTypeReferences()1013     void VariableValueTypeReferences() {
1014         {
1015             GET_SYMBOL_DB("void foo(int x) {}\n");
1016             const Variable* const p = db->getVariableFromVarId(1);
1017             ASSERT(p->valueType());
1018             ASSERT(p->valueType()->pointer == 0);
1019             ASSERT(p->valueType()->constness == 0);
1020             ASSERT(p->valueType()->reference == Reference::None);
1021         }
1022         {
1023             GET_SYMBOL_DB("void foo(int* x) {}\n");
1024             const Variable* const p = db->getVariableFromVarId(1);
1025             ASSERT(p->valueType());
1026             ASSERT(p->valueType()->pointer == 1);
1027             ASSERT(p->valueType()->constness == 0);
1028             ASSERT(p->valueType()->reference == Reference::None);
1029         }
1030         {
1031             GET_SYMBOL_DB("void foo(int& x) {}\n");
1032             const Variable* const p = db->getVariableFromVarId(1);
1033             ASSERT(p->valueType());
1034             ASSERT(p->valueType()->pointer == 0);
1035             ASSERT(p->valueType()->constness == 0);
1036             ASSERT(p->valueType()->reference == Reference::LValue);
1037         }
1038         {
1039             GET_SYMBOL_DB("void foo(int&& x) {}\n");
1040             const Variable* const p = db->getVariableFromVarId(1);
1041             ASSERT(p->valueType());
1042             ASSERT(p->valueType()->pointer == 0);
1043             ASSERT(p->valueType()->constness == 0);
1044             ASSERT(p->valueType()->reference == Reference::RValue);
1045         }
1046         {
1047             GET_SYMBOL_DB("void foo(int*& x) {}\n");
1048             const Variable* const p = db->getVariableFromVarId(1);
1049             ASSERT(p->valueType());
1050             ASSERT(p->valueType()->pointer == 1);
1051             ASSERT(p->valueType()->constness == 0);
1052             ASSERT(p->valueType()->reference == Reference::LValue);
1053         }
1054         {
1055             GET_SYMBOL_DB("void foo(int*&& x) {}\n");
1056             const Variable* const p = db->getVariableFromVarId(1);
1057             ASSERT(p->valueType());
1058             ASSERT(p->valueType()->pointer == 1);
1059             ASSERT(p->valueType()->constness == 0);
1060             ASSERT(p->valueType()->reference == Reference::RValue);
1061         }
1062         {
1063             GET_SYMBOL_DB("void foo(int**& x) {}\n");
1064             const Variable* const p = db->getVariableFromVarId(1);
1065             ASSERT(p->valueType());
1066             ASSERT(p->valueType()->pointer == 2);
1067             ASSERT(p->valueType()->constness == 0);
1068             ASSERT(p->valueType()->reference == Reference::LValue);
1069         }
1070         {
1071             GET_SYMBOL_DB("void foo(int**&& x) {}\n");
1072             const Variable* const p = db->getVariableFromVarId(1);
1073             ASSERT(p->valueType());
1074             ASSERT(p->valueType()->pointer == 2);
1075             ASSERT(p->valueType()->constness == 0);
1076             ASSERT(p->valueType()->reference == Reference::RValue);
1077         }
1078         {
1079             GET_SYMBOL_DB("void foo(const int& x) {}\n");
1080             const Variable* const p = db->getVariableFromVarId(1);
1081             ASSERT(p->valueType());
1082             ASSERT(p->valueType()->pointer == 0);
1083             ASSERT(p->valueType()->constness == 1);
1084             ASSERT(p->valueType()->reference == Reference::LValue);
1085         }
1086         {
1087             GET_SYMBOL_DB("void foo(const int&& x) {}\n");
1088             const Variable* const p = db->getVariableFromVarId(1);
1089             ASSERT(p->valueType());
1090             ASSERT(p->valueType()->pointer == 0);
1091             ASSERT(p->valueType()->constness == 1);
1092             ASSERT(p->valueType()->reference == Reference::RValue);
1093         }
1094         {
1095             GET_SYMBOL_DB("void foo(const int*& x) {}\n");
1096             const Variable* const p = db->getVariableFromVarId(1);
1097             ASSERT(p->valueType());
1098             ASSERT(p->valueType()->pointer == 1);
1099             ASSERT(p->valueType()->constness == 1);
1100             ASSERT(p->valueType()->reference == Reference::LValue);
1101         }
1102         {
1103             GET_SYMBOL_DB("void foo(const int*&& x) {}\n");
1104             const Variable* const p = db->getVariableFromVarId(1);
1105             ASSERT(p->valueType());
1106             ASSERT(p->valueType()->pointer == 1);
1107             ASSERT(p->valueType()->constness == 1);
1108             ASSERT(p->valueType()->reference == Reference::RValue);
1109         }
1110         {
1111             GET_SYMBOL_DB("void foo(int* const & x) {}\n");
1112             const Variable* const p = db->getVariableFromVarId(1);
1113             ASSERT(p->valueType());
1114             ASSERT(p->valueType()->pointer == 1);
1115             ASSERT(p->valueType()->constness == 2);
1116             ASSERT(p->valueType()->reference == Reference::LValue);
1117         }
1118         {
1119             GET_SYMBOL_DB("void foo(int* const && x) {}\n");
1120             const Variable* const p = db->getVariableFromVarId(1);
1121             ASSERT(p->valueType());
1122             ASSERT(p->valueType()->pointer == 1);
1123             ASSERT(p->valueType()->constness == 2);
1124             ASSERT(p->valueType()->reference == Reference::RValue);
1125         }
1126     }
1127 
findVariableType1()1128     void findVariableType1() {
1129         GET_SYMBOL_DB("class A {\n"
1130                       "public:\n"
1131                       "    struct B {};\n"
1132                       "    void f();\n"
1133                       "};\n"
1134                       "\n"
1135                       "void f()\n"
1136                       "{\n"
1137                       "    struct A::B b;\n"
1138                       "    b.x = 1;\n"
1139                       "}");
1140         ASSERT(db != nullptr);
1141 
1142         const Variable* bvar = db->getVariableFromVarId(1);
1143         ASSERT_EQUALS("b", bvar->name());
1144         ASSERT(bvar->type() != nullptr);
1145     }
1146 
findVariableType2()1147     void findVariableType2() {
1148         GET_SYMBOL_DB("class A {\n"
1149                       "public:\n"
1150                       "    class B {\n"
1151                       "    public:\n"
1152                       "        struct C {\n"
1153                       "            int x;\n"
1154                       "            int y;\n"
1155                       "        };\n"
1156                       "    };\n"
1157                       "\n"
1158                       "    void f();\n"
1159                       "};\n"
1160                       "\n"
1161                       "void A::f()\n"
1162                       "{\n"
1163                       "    struct B::C c;\n"
1164                       "    c.x = 1;\n"
1165                       "}");
1166         ASSERT(db != nullptr);
1167 
1168         const Variable* cvar = db->getVariableFromVarId(3);
1169         ASSERT_EQUALS("c", cvar->name());
1170         ASSERT(cvar->type() != nullptr);
1171     }
1172 
findVariableType3()1173     void findVariableType3() {
1174         GET_SYMBOL_DB("namespace {\n"
1175                       "    struct A {\n"
1176                       "        int x;\n"
1177                       "        int y;\n"
1178                       "    };\n"
1179                       "}\n"
1180                       "\n"
1181                       "void f()\n"
1182                       "{\n"
1183                       "    struct A a;\n"
1184                       "    a.x = 1;\n"
1185                       "}");
1186         (void)db;
1187         const Variable* avar = Token::findsimplematch(tokenizer.tokens(), "a")->variable();
1188         ASSERT(avar);
1189         ASSERT(avar && avar->type() != nullptr);
1190     }
1191 
findVariableTypeExternC()1192     void findVariableTypeExternC() {
1193         GET_SYMBOL_DB("extern \"C\" { typedef int INT; }\n"
1194                       "void bar() {\n"
1195                       "    INT x = 3;\n"
1196                       "}");
1197         (void)db;
1198         const Variable* avar = Token::findsimplematch(tokenizer.tokens(), "x")->variable();
1199         ASSERT(avar);
1200         ASSERT(avar->valueType() != nullptr);
1201         ASSERT(avar->valueType()->str() == "signed int");
1202     }
1203 
rangeBasedFor()1204     void rangeBasedFor() {
1205         GET_SYMBOL_DB("void reset() {\n"
1206                       "    for(auto& e : array)\n"
1207                       "        foo(e);\n"
1208                       "}");
1209 
1210         ASSERT(db != nullptr);
1211 
1212         ASSERT(db->scopeList.back().type == Scope::eFor);
1213         ASSERT_EQUALS(2, db->variableList().size());
1214 
1215         const Variable* e = db->getVariableFromVarId(1);
1216         ASSERT(e && e->isReference() && e->isLocal());
1217     }
isVariableStlType()1218     void isVariableStlType() {
1219         {
1220             reset();
1221             std::istringstream code("std::string s;");
1222             TokenList list(nullptr);
1223             list.createTokens(code, "test.cpp");
1224             const bool result = nullScope.isVariableDeclaration(list.front(), vartok, typetok);
1225             ASSERT_EQUALS(true, result);
1226             Variable v(vartok, list.front(), list.back(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1227             static const std::set<std::string> types = { "string", "wstring" };
1228             static const std::set<std::string> no_types = { "set" };
1229             ASSERT_EQUALS(true, v.isStlType());
1230             ASSERT_EQUALS(true, v.isStlType(types));
1231             ASSERT_EQUALS(false, v.isStlType(no_types));
1232             ASSERT_EQUALS(true, v.isStlStringType());
1233         }
1234         {
1235             reset();
1236             std::istringstream code("std::vector<int> v;");
1237             TokenList list(nullptr);
1238             list.createTokens(code, "test.cpp");
1239             list.front()->tokAt(3)->link(list.front()->tokAt(5));
1240             const bool result = nullScope.isVariableDeclaration(list.front(), vartok, typetok);
1241             ASSERT_EQUALS(true, result);
1242             Variable v(vartok, list.front(), list.back(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1243             static const std::set<std::string> types = { "bitset", "set", "vector", "wstring" };
1244             static const std::set<std::string> no_types = { "bitset", "map", "set" };
1245             ASSERT_EQUALS(true, v.isStlType());
1246             ASSERT_EQUALS(true, v.isStlType(types));
1247             ASSERT_EQUALS(false, v.isStlType(no_types));
1248             ASSERT_EQUALS(false, v.isStlStringType());
1249         }
1250         {
1251             reset();
1252             std::istringstream code("SomeClass s;");
1253             TokenList list(nullptr);
1254             list.createTokens(code, "test.cpp");
1255             const bool result = nullScope.isVariableDeclaration(list.front(), vartok, typetok);
1256             ASSERT_EQUALS(true, result);
1257             Variable v(vartok, list.front(), list.back(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1258             static const std::set<std::string> types = { "bitset", "set", "vector" };
1259             ASSERT_EQUALS(false, v.isStlType());
1260             ASSERT_EQUALS(false, v.isStlType(types));
1261             ASSERT_EQUALS(false, v.isStlStringType());
1262         }
1263     }
1264 
isVariablePointerToConstPointer()1265     void isVariablePointerToConstPointer() {
1266         reset();
1267         givenACodeSampleToTokenize var("char* const * s;");
1268         bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
1269         ASSERT_EQUALS(true, result);
1270         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1271         ASSERT(false == v.isArray());
1272         ASSERT(true == v.isPointer());
1273         ASSERT(false == v.isReference());
1274     }
1275 
isVariablePointerToVolatilePointer()1276     void isVariablePointerToVolatilePointer() {
1277         reset();
1278         givenACodeSampleToTokenize var("char* volatile * s;");
1279         bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
1280         ASSERT_EQUALS(true, result);
1281         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1282         ASSERT(false == v.isArray());
1283         ASSERT(true == v.isPointer());
1284         ASSERT(false == v.isReference());
1285     }
1286 
isVariablePointerToConstVolatilePointer()1287     void isVariablePointerToConstVolatilePointer() {
1288         reset();
1289         givenACodeSampleToTokenize var("char* const volatile * s;");
1290         bool result = nullScope.isVariableDeclaration(var.tokens(), vartok, typetok);
1291         ASSERT_EQUALS(true, result);
1292         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1293         ASSERT(false == v.isArray());
1294         ASSERT(true == v.isPointer());
1295         ASSERT(false == v.isReference());
1296     }
1297 
isVariableMultiplePointersAndQualifiers()1298     void isVariableMultiplePointersAndQualifiers() {
1299         reset();
1300         givenACodeSampleToTokenize var("const char* const volatile * const volatile * const volatile * const volatile s;");
1301         bool result = nullScope.isVariableDeclaration(var.tokens()->next(), vartok, typetok);
1302         ASSERT_EQUALS(true, result);
1303         Variable v(vartok, typetok, vartok->previous(), 0, AccessControl::Public, nullptr, nullptr, &settings1);
1304         ASSERT(false == v.isArray());
1305         ASSERT(true == v.isPointer());
1306         ASSERT(false == v.isReference());
1307     }
1308 
variableVolatile()1309     void variableVolatile() {
1310         GET_SYMBOL_DB("std::atomic<int> x;\n"
1311                       "volatile int y;");
1312 
1313         const Token *x = Token::findsimplematch(tokenizer.tokens(), "x");
1314         ASSERT(x);
1315         ASSERT(x->variable());
1316         ASSERT(x->variable()->isVolatile());
1317 
1318         const Token *y = Token::findsimplematch(tokenizer.tokens(), "y");
1319         ASSERT(y);
1320         ASSERT(y->variable());
1321         ASSERT(y->variable()->isVolatile());
1322     }
1323 
variableConstexpr()1324     void variableConstexpr() {
1325         GET_SYMBOL_DB("constexpr int x = 16;");
1326 
1327         const Token *x = Token::findsimplematch(tokenizer.tokens(), "x");
1328         ASSERT(x);
1329         ASSERT(x->variable());
1330         ASSERT(x->variable()->isConst());
1331         ASSERT(x->variable()->isStatic());
1332         ASSERT(x->valueType());
1333         ASSERT(x->valueType()->pointer == 0);
1334         ASSERT(x->valueType()->constness == 1);
1335         ASSERT(x->valueType()->reference == Reference::None);
1336     }
1337 
isVariableDecltype()1338     void isVariableDecltype() {
1339         GET_SYMBOL_DB("int x;\n"
1340                       "decltype(x) a;\n"
1341                       "const decltype(x) b;\n"
1342                       "decltype(x) *c;\n");
1343         ASSERT(db);
1344         ASSERT_EQUALS(4, db->scopeList.front().varlist.size());
1345 
1346         const Variable *a = Token::findsimplematch(tokenizer.tokens(), "a")->variable();
1347         ASSERT(a);
1348         ASSERT_EQUALS("a", a->name());
1349         ASSERT(a->valueType());
1350         ASSERT_EQUALS("signed int", a->valueType()->str());
1351 
1352         const Variable *b = Token::findsimplematch(tokenizer.tokens(), "b")->variable();
1353         ASSERT(b);
1354         ASSERT_EQUALS("b", b->name());
1355         ASSERT(b->valueType());
1356         ASSERT_EQUALS("const signed int", b->valueType()->str());
1357 
1358         const Variable *c = Token::findsimplematch(tokenizer.tokens(), "c")->variable();
1359         ASSERT(c);
1360         ASSERT_EQUALS("c", c->name());
1361         ASSERT(c->valueType());
1362         ASSERT_EQUALS("signed int *", c->valueType()->str());
1363     }
1364 
arrayMemberVar1()1365     void arrayMemberVar1() {
1366         GET_SYMBOL_DB("struct Foo {\n"
1367                       "    int x;\n"
1368                       "};\n"
1369                       "void f() {\n"
1370                       "    struct Foo foo[10];\n"
1371                       "    foo[1].x = 123;\n"  // <- x should get a variable() pointer
1372                       "}");
1373 
1374         const Token *tok = Token::findsimplematch(tokenizer.tokens(), ". x");
1375         tok = tok ? tok->next() : nullptr;
1376         ASSERT(db != nullptr);
1377         ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;"));
1378         ASSERT(tok && tok->varId() == 3U); // It's possible to set a varId
1379     }
1380 
arrayMemberVar2()1381     void arrayMemberVar2() {
1382         GET_SYMBOL_DB("struct Foo {\n"
1383                       "    int x;\n"
1384                       "};\n"
1385                       "void f() {\n"
1386                       "    struct Foo foo[10][10];\n"
1387                       "    foo[1][2].x = 123;\n"  // <- x should get a variable() pointer
1388                       "}");
1389 
1390         const Token *tok = Token::findsimplematch(tokenizer.tokens(), ". x");
1391         tok = tok ? tok->next() : nullptr;
1392         ASSERT(db != nullptr);
1393         ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;"));
1394         ASSERT(tok && tok->varId() == 3U); // It's possible to set a varId
1395     }
1396 
arrayMemberVar3()1397     void arrayMemberVar3() {
1398         GET_SYMBOL_DB("struct Foo {\n"
1399                       "    int x;\n"
1400                       "};\n"
1401                       "void f() {\n"
1402                       "    struct Foo foo[10];\n"
1403                       "    (foo[1]).x = 123;\n"  // <- x should get a variable() pointer
1404                       "}");
1405 
1406         const Token *tok = Token::findsimplematch(tokenizer.tokens(), ". x");
1407         tok = tok ? tok->next() : nullptr;
1408         ASSERT(db != nullptr);
1409         ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;"));
1410         ASSERT(tok && tok->varId() == 3U); // It's possible to set a varId
1411     }
1412 
staticMemberVar()1413     void staticMemberVar() {
1414         GET_SYMBOL_DB("class Foo {\n"
1415                       "    static const double d;\n"
1416                       "};\n"
1417                       "const double Foo::d = 5.0;");
1418 
1419         const Variable* v = db->getVariableFromVarId(1);
1420         ASSERT(v && db->variableList().size() == 2);
1421         ASSERT(v && v->isStatic() && v->isConst() && v->isPrivate());
1422     }
1423 
getVariableFromVarIdBoundsCheck()1424     void getVariableFromVarIdBoundsCheck() {
1425         GET_SYMBOL_DB("int x;\n"
1426                       "int y;");
1427 
1428         const Variable* v = db->getVariableFromVarId(2);
1429         // three elements: varId 0 also counts via a fake-entry
1430         ASSERT(v && db->variableList().size() == 3);
1431 
1432         ASSERT_THROW(db->getVariableFromVarId(3), std::out_of_range);
1433     }
1434 
hasRegularFunction()1435     void hasRegularFunction() {
1436         GET_SYMBOL_DB("void func() { }");
1437 
1438         // 2 scopes: Global and Function
1439         ASSERT(db && db->scopeList.size() == 2);
1440 
1441         const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->next());
1442 
1443         ASSERT(scope && scope->className == "func");
1444 
1445         ASSERT(scope->functionOf == nullptr);
1446 
1447         const Function *function = findFunctionByName("func", &db->scopeList.front());
1448 
1449         ASSERT(function && function->token->str() == "func");
1450         ASSERT(function && function->token == tokenizer.tokens()->next());
1451         ASSERT(function && function->hasBody());
1452         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn != scope);
1453         ASSERT(function && function->retDef == tokenizer.tokens());
1454     }
1455 
hasRegularFunction_trailingReturnType()1456     void hasRegularFunction_trailingReturnType() {
1457         GET_SYMBOL_DB("auto func() -> int { }");
1458 
1459         // 2 scopes: Global and Function
1460         ASSERT(db && db->scopeList.size() == 2);
1461 
1462         const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->next());
1463 
1464         ASSERT(scope && scope->className == "func");
1465 
1466         ASSERT(scope->functionOf == nullptr);
1467 
1468         const Function *function = findFunctionByName("func", &db->scopeList.front());
1469 
1470         ASSERT(function && function->token->str() == "func");
1471         ASSERT(function && function->token == tokenizer.tokens()->next());
1472         ASSERT(function && function->hasBody());
1473         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn != scope);
1474         ASSERT(function && function->retDef == tokenizer.tokens()->tokAt(5));
1475     }
1476 
hasInlineClassFunction()1477     void hasInlineClassFunction() {
1478         GET_SYMBOL_DB("class Fred { void func() { } };");
1479 
1480         // 3 scopes: Global, Class, and Function
1481         ASSERT(db && db->scopeList.size() == 3);
1482 
1483         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1484 
1485         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1486 
1487         ASSERT(scope && scope->className == "func");
1488 
1489         ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
1490 
1491         const Function *function = findFunctionByName("func", &db->scopeList.back());
1492 
1493         ASSERT(function && function->token->str() == "func");
1494         ASSERT(function && function->token == functionToken);
1495         ASSERT(function && function->hasBody() && function->isInline());
1496         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
1497         ASSERT(function && function->retDef == functionToken->previous());
1498 
1499         ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("func") == function);
1500     }
1501 
1502 
hasInlineClassFunction_trailingReturnType()1503     void hasInlineClassFunction_trailingReturnType() {
1504         GET_SYMBOL_DB("class Fred { auto func() -> int { } };");
1505 
1506         // 3 scopes: Global, Class, and Function
1507         ASSERT(db && db->scopeList.size() == 3);
1508 
1509         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1510 
1511         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1512 
1513         ASSERT(scope && scope->className == "func");
1514 
1515         ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
1516 
1517         const Function *function = findFunctionByName("func", &db->scopeList.back());
1518 
1519         ASSERT(function && function->token->str() == "func");
1520         ASSERT(function && function->token == functionToken);
1521         ASSERT(function && function->hasBody() && function->isInline());
1522         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
1523         ASSERT(function && function->retDef == functionToken->tokAt(4));
1524 
1525         ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("func") == function);
1526     }
1527 
hasMissingInlineClassFunction()1528     void hasMissingInlineClassFunction() {
1529         GET_SYMBOL_DB("class Fred { void func(); };");
1530 
1531         // 2 scopes: Global and Class (no Function scope because there is no function implementation)
1532         ASSERT(db && db->scopeList.size() == 2);
1533 
1534         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1535 
1536         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1537 
1538         ASSERT(scope == nullptr);
1539 
1540         const Function *function = findFunctionByName("func", &db->scopeList.back());
1541 
1542         ASSERT(function && function->token->str() == "func");
1543         ASSERT(function && function->token == functionToken);
1544         ASSERT(function && !function->hasBody());
1545     }
1546 
hasInlineClassOperatorTemplate()1547     void hasInlineClassOperatorTemplate() {
1548         GET_SYMBOL_DB("struct Fred { template<typename T> Foo & operator=(const Foo &) { return *this; } };");
1549 
1550         // 3 scopes: Global, Class, and Function
1551         ASSERT(db && db->scopeList.size() == 3);
1552 
1553         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "operator=");
1554 
1555         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1556 
1557         ASSERT(scope && scope->className == "operator=");
1558 
1559         ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
1560 
1561         const Function *function = findFunctionByName("operator=", &db->scopeList.back());
1562 
1563         ASSERT(function && function->token->str() == "operator=");
1564         ASSERT(function && function->token == functionToken);
1565         ASSERT(function && function->hasBody() && function->isInline());
1566         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
1567         ASSERT(function && function->retDef == functionToken->tokAt(-2));
1568 
1569         ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("operator=") == function);
1570     }
1571 
hasClassFunction()1572     void hasClassFunction() {
1573         GET_SYMBOL_DB("class Fred { void func(); }; void Fred::func() { }");
1574 
1575         // 3 scopes: Global, Class, and Function
1576         ASSERT(db && db->scopeList.size() == 3);
1577 
1578         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens()->linkAt(2), "func");
1579 
1580         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1581 
1582         ASSERT(scope && scope->className == "func");
1583 
1584         ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
1585 
1586         const Function *function = findFunctionByName("func", &db->scopeList.back());
1587 
1588         ASSERT(function && function->token->str() == "func");
1589         ASSERT(function && function->token == functionToken);
1590         ASSERT(function && function->hasBody() && !function->isInline());
1591         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
1592     }
1593 
hasClassFunction_trailingReturnType()1594     void hasClassFunction_trailingReturnType() {
1595         GET_SYMBOL_DB("class Fred { auto func() -> int; }; auto Fred::func() -> int { }");
1596 
1597         // 3 scopes: Global, Class, and Function
1598         ASSERT(db && db->scopeList.size() == 3);
1599 
1600         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens()->linkAt(2), "func");
1601 
1602         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1603 
1604         ASSERT(scope && scope->className == "func");
1605 
1606         ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred"));
1607 
1608         const Function *function = findFunctionByName("func", &db->scopeList.back());
1609 
1610         ASSERT(function && function->token->str() == "func");
1611         ASSERT(function && function->token == functionToken);
1612         ASSERT(function && function->hasBody() && !function->isInline());
1613         ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
1614     }
1615 
hasRegularFunctionReturningFunctionPointer()1616     void hasRegularFunctionReturningFunctionPointer() {
1617         GET_SYMBOL_DB("void (*func(int f))(char) { }");
1618 
1619         // 2 scopes: Global and Function
1620         ASSERT(db && db->scopeList.size() == 2);
1621 
1622         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1623 
1624         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1625 
1626         ASSERT(scope && scope->className == "func");
1627 
1628         const Function *function = findFunctionByName("func", &db->scopeList.front());
1629 
1630         ASSERT(function && function->token->str() == "func");
1631         ASSERT(function && function->token == functionToken);
1632         ASSERT(function && function->hasBody());
1633     }
1634 
hasInlineClassFunctionReturningFunctionPointer()1635     void hasInlineClassFunctionReturningFunctionPointer() {
1636         GET_SYMBOL_DB("class Fred { void (*func(int f))(char) { } };");
1637 
1638         // 3 scopes: Global, Class, and Function
1639         ASSERT(db && db->scopeList.size() == 3);
1640 
1641         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1642 
1643         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1644 
1645         ASSERT(scope && scope->className == "func");
1646 
1647         const Function *function = findFunctionByName("func", &db->scopeList.back());
1648 
1649         ASSERT(function && function->token->str() == "func");
1650         ASSERT(function && function->token == functionToken);
1651         ASSERT(function && function->hasBody() && function->isInline());
1652     }
1653 
hasMissingInlineClassFunctionReturningFunctionPointer()1654     void hasMissingInlineClassFunctionReturningFunctionPointer() {
1655         GET_SYMBOL_DB("class Fred { void (*func(int f))(char); };");
1656 
1657         // 2 scopes: Global and Class (no Function scope because there is no function implementation)
1658         ASSERT(db && db->scopeList.size() == 2);
1659 
1660         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1661 
1662         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1663 
1664         ASSERT(scope == nullptr);
1665 
1666         const Function *function = findFunctionByName("func", &db->scopeList.back());
1667 
1668         ASSERT(function && function->token->str() == "func");
1669         ASSERT(function && function->token == functionToken);
1670         ASSERT(function && !function->hasBody());
1671     }
1672 
hasClassFunctionReturningFunctionPointer()1673     void hasClassFunctionReturningFunctionPointer() {
1674         GET_SYMBOL_DB("class Fred { void (*func(int f))(char); }; void (*Fred::func(int f))(char) { }");
1675 
1676         // 3 scopes: Global, Class, and Function
1677         ASSERT(db && db->scopeList.size() == 3);
1678 
1679         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens()->linkAt(2), "func");
1680 
1681         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1682 
1683         ASSERT(scope && scope->className == "func");
1684 
1685         const Function *function = findFunctionByName("func", &db->scopeList.back());
1686 
1687         ASSERT(function && function->token->str() == "func");
1688         ASSERT(function && function->token == functionToken);
1689         ASSERT(function && function->hasBody() && !function->isInline());
1690     }
1691 
methodWithRedundantScope()1692     void methodWithRedundantScope() {
1693         GET_SYMBOL_DB("class Fred { void Fred::func() {} };");
1694 
1695         // 3 scopes: Global, Class, and Function
1696         ASSERT(db && db->scopeList.size() == 3);
1697 
1698         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
1699 
1700         const Scope *scope = findFunctionScopeByToken(db, functionToken);
1701 
1702         ASSERT(scope && scope->className == "func");
1703 
1704         const Function *function = findFunctionByName("func", &db->scopeList.back());
1705 
1706         ASSERT(function && function->token->str() == "func");
1707         ASSERT(function && function->token == functionToken);
1708         ASSERT(function && function->hasBody() && function->isInline());
1709     }
1710 
complexFunctionArrayPtr()1711     void complexFunctionArrayPtr() {
1712         GET_SYMBOL_DB("int(*p1)[10]; \n"                            // pointer to array 10 of int
1713                       "void(*p2)(char); \n"                         // pointer to function (char) returning void
1714                       "int(*(*p3)(char))[10];\n"                    // pointer to function (char) returning pointer to array 10 of int
1715                       "float(*(*p4)(char))(long); \n"               // pointer to function (char) returning pointer to function (long) returning float
1716                       "short(*(*(*p5) (char))(long))(double);\n"    // pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short
1717                       "int(*a1[10])(void); \n"                      // array 10 of pointer to function (void) returning int
1718                       "float(*(*a2[10])(char))(long);\n"            // array 10 of pointer to func (char) returning pointer to func (long) returning float
1719                       "short(*(*(*a3[10])(char))(long))(double);\n" // array 10 of pointer to function (char) returning pointer to function (long) returning pointer to function (double) returning short
1720                       "::boost::rational(&r_)[9];\n"                // reference to array of ::boost::rational
1721                       "::boost::rational<T>(&r_)[9];");             // reference to array of ::boost::rational<T> (template!)
1722 
1723         ASSERT(db != nullptr);
1724 
1725         ASSERT_EQUALS(10, db->variableList().size() - 1);
1726         ASSERT_EQUALS(true, db->getVariableFromVarId(1) && db->getVariableFromVarId(1)->dimensions().size() == 1);
1727         ASSERT_EQUALS(true, db->getVariableFromVarId(2) != nullptr);
1728         ASSERT_EQUALS(true, db->getVariableFromVarId(3) && db->getVariableFromVarId(3)->dimensions().size() == 0);
1729         ASSERT_EQUALS(true, db->getVariableFromVarId(4) != nullptr);
1730         ASSERT_EQUALS(true, db->getVariableFromVarId(5) != nullptr);
1731         ASSERT_EQUALS(true, db->getVariableFromVarId(6) && db->getVariableFromVarId(6)->dimensions().size() == 1);
1732         ASSERT_EQUALS(true, db->getVariableFromVarId(7) && db->getVariableFromVarId(7)->dimensions().size() == 1);
1733         ASSERT_EQUALS(true, db->getVariableFromVarId(8) && db->getVariableFromVarId(8)->dimensions().size() == 1);
1734         ASSERT_EQUALS(true, db->getVariableFromVarId(9) && db->getVariableFromVarId(9)->dimensions().size() == 1);
1735         ASSERT_EQUALS(true, db->getVariableFromVarId(10) && db->getVariableFromVarId(10)->dimensions().size() == 1);
1736         ASSERT_EQUALS("", errout.str());
1737     }
1738 
pointerToMemberFunction()1739     void pointerToMemberFunction() {
1740         GET_SYMBOL_DB("bool (A::*pFun)();"); // Pointer to member function of A, returning bool and taking no parameters
1741 
1742         ASSERT(db != nullptr);
1743 
1744         ASSERT_EQUALS(1, db->variableList().size() - 1);
1745         ASSERT_EQUALS(true, db->getVariableFromVarId(1) != nullptr);
1746 
1747         ASSERT_EQUALS("pFun", db->getVariableFromVarId(1)->name());
1748         ASSERT_EQUALS("", errout.str());
1749     }
1750 
hasSubClassConstructor()1751     void hasSubClassConstructor() {
1752         GET_SYMBOL_DB("class Foo { class Sub; }; class Foo::Sub { Sub() {} };");
1753         ASSERT(db != nullptr);
1754 
1755         bool seen_something = false;
1756         for (const Scope & scope : db->scopeList) {
1757             for (std::list<Function>::const_iterator func = scope.functionList.begin(); func != scope.functionList.end(); ++func) {
1758                 ASSERT_EQUALS("Sub", func->token->str());
1759                 ASSERT_EQUALS(true, func->hasBody());
1760                 ASSERT_EQUALS(Function::eConstructor, func->type);
1761                 seen_something = true;
1762             }
1763         }
1764         ASSERT_EQUALS(true, seen_something);
1765     }
1766 
testConstructors()1767     void testConstructors() {
1768         {
1769             GET_SYMBOL_DB("class Foo { Foo(); };");
1770             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1771             ASSERT(db && ctor && ctor->type == Function::eConstructor);
1772             ASSERT(ctor && ctor->retDef == nullptr);
1773         }
1774         {
1775             GET_SYMBOL_DB("class Foo { Foo(Foo f); };");
1776             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1777             ASSERT(db && ctor && ctor->type == Function::eConstructor && !ctor->isExplicit());
1778             ASSERT(ctor && ctor->retDef == nullptr);
1779         }
1780         {
1781             GET_SYMBOL_DB("class Foo { explicit Foo(Foo f); };");
1782             const Function* ctor = tokenizer.tokens()->tokAt(4)->function();
1783             ASSERT(db && ctor && ctor->type == Function::eConstructor && ctor->isExplicit());
1784             ASSERT(ctor && ctor->retDef == nullptr);
1785         }
1786         {
1787             GET_SYMBOL_DB("class Foo { Foo(Bar& f); };");
1788             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1789             ASSERT(db && ctor && ctor->type == Function::eConstructor);
1790             ASSERT(ctor && ctor->retDef == nullptr);
1791         }
1792         {
1793             GET_SYMBOL_DB("class Foo { Foo(Foo& f); };");
1794             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1795             ASSERT(db && ctor && ctor->type == Function::eCopyConstructor);
1796             ASSERT(ctor && ctor->retDef == nullptr);
1797         }
1798         {
1799             GET_SYMBOL_DB("class Foo { Foo(const Foo &f); };");
1800             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1801             ASSERT(db && ctor && ctor->type == Function::eCopyConstructor);
1802             ASSERT(ctor && ctor->retDef == nullptr);
1803         }
1804         {
1805             GET_SYMBOL_DB("template <T> class Foo { Foo(Foo<T>& f); };");
1806             const Function* ctor = tokenizer.tokens()->tokAt(7)->function();
1807             ASSERT(db && ctor && ctor->type == Function::eCopyConstructor);
1808             ASSERT(ctor && ctor->retDef == nullptr);
1809         }
1810         {
1811             GET_SYMBOL_DB("class Foo { Foo(Foo& f, int default = 0); };");
1812             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1813             ASSERT(db && ctor && ctor->type == Function::eCopyConstructor);
1814             ASSERT(ctor && ctor->retDef == nullptr);
1815         }
1816         {
1817             GET_SYMBOL_DB("class Foo { Foo(Foo& f, char noDefault); };");
1818             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1819             ASSERT(db && ctor && ctor->type == Function::eConstructor);
1820             ASSERT(ctor && ctor->retDef == nullptr);
1821         }
1822         {
1823             GET_SYMBOL_DB("class Foo { Foo(Foo&& f); };");
1824             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1825             ASSERT(db && ctor && ctor->type == Function::eMoveConstructor);
1826             ASSERT(ctor && ctor->retDef == nullptr);
1827         }
1828         {
1829             GET_SYMBOL_DB("class Foo { Foo(Foo&& f, int default = 1, bool defaultToo = true); };");
1830             const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
1831             ASSERT(db && ctor && ctor->type == Function::eMoveConstructor);
1832             ASSERT(ctor && ctor->retDef == nullptr);
1833         }
1834     }
1835 
functionDeclarationTemplate()1836     void functionDeclarationTemplate() {
1837         GET_SYMBOL_DB("std::map<int, string> foo() {}");
1838 
1839         // 2 scopes: Global and Function
1840         ASSERT(db && db->scopeList.size() == 2 && findFunctionByName("foo", &db->scopeList.back()));
1841 
1842         const Scope *scope = &db->scopeList.front();
1843 
1844         ASSERT(scope && scope->functionList.size() == 1);
1845 
1846         const Function *foo = &scope->functionList.front();
1847 
1848         ASSERT(foo && foo->token->str() == "foo");
1849         ASSERT(foo && foo->hasBody());
1850     }
1851 
functionDeclarations()1852     void functionDeclarations() {
1853         GET_SYMBOL_DB("void foo();\nvoid foo();\nint foo(int i);\nvoid foo() {}");
1854 
1855         // 2 scopes: Global and Function
1856         ASSERT(db && db->scopeList.size() == 2 && findFunctionByName("foo", &db->scopeList.back()));
1857 
1858         const Scope *scope = &db->scopeList.front();
1859 
1860         ASSERT(scope && scope->functionList.size() == 2);
1861 
1862         const Function *foo = &scope->functionList.front();
1863         const Function *foo_int = &scope->functionList.back();
1864 
1865         ASSERT(foo && foo->token->str() == "foo");
1866         ASSERT(foo && foo->hasBody());
1867         ASSERT(foo && foo->token->strAt(2) == ")");
1868 
1869         ASSERT(foo_int && !foo_int->token);
1870         ASSERT(foo_int && foo_int->tokenDef->str() == "foo");
1871         ASSERT(foo_int && !foo_int->hasBody());
1872         ASSERT(foo_int && foo_int->tokenDef->strAt(2) == "int");
1873 
1874         ASSERT(&foo_int->argumentList.front() == db->getVariableFromVarId(1));
1875     }
1876 
functionDeclarations2()1877     void functionDeclarations2() {
1878         GET_SYMBOL_DB_STD("std::array<int,2> foo(int x);");
1879 
1880         // 1 scopes: Global
1881         ASSERT(db && db->scopeList.size() == 1);
1882 
1883         const Scope *scope = &db->scopeList.front();
1884 
1885         ASSERT(scope && scope->functionList.size() == 1);
1886 
1887         const Function *foo = &scope->functionList.front();
1888 
1889         ASSERT(foo);
1890         ASSERT(foo->tokenDef->str() == "foo");
1891         ASSERT(!foo->hasBody());
1892 
1893         const Token*parenthesis = foo->tokenDef->next();
1894         ASSERT(parenthesis->str() == "(" && parenthesis->previous()->str() == "foo");
1895         ASSERT(parenthesis->valueType()->type == ValueType::Type::CONTAINER);
1896     }
1897 
constexprFunction()1898     void constexprFunction() {
1899         GET_SYMBOL_DB_STD("constexpr int foo();");
1900 
1901         // 1 scopes: Global
1902         ASSERT(db && db->scopeList.size() == 1);
1903 
1904         const Scope *scope = &db->scopeList.front();
1905 
1906         ASSERT(scope && scope->functionList.size() == 1);
1907 
1908         const Function *foo = &scope->functionList.front();
1909 
1910         ASSERT(foo);
1911         ASSERT(foo->tokenDef->str() == "foo");
1912         ASSERT(!foo->hasBody());
1913         ASSERT(foo->isConstexpr());
1914     }
1915 
constructorInitialization()1916     void constructorInitialization() {
1917         GET_SYMBOL_DB("std::string logfile;\n"
1918                       "std::ofstream log(logfile.c_str(), std::ios::out);");
1919 
1920         // 1 scope: Global
1921         ASSERT(db && db->scopeList.size() == 1);
1922 
1923         // No functions
1924         ASSERT(db->scopeList.front().functionList.empty());
1925     }
1926 
memberFunctionOfUnknownClassMacro1()1927     void memberFunctionOfUnknownClassMacro1() {
1928         GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() SAL_OVERRIDE; };\n"
1929                       "void ScVbaValidation::getFormula1() {\n"
1930                       "    sal_uInt16 nFlags = 0;\n"
1931                       "    if (pDocSh && !getCellRangesForAddress(nFlags)) ;\n"
1932                       "}");
1933 
1934         ASSERT(db && errout.str().empty());
1935 
1936         const Scope *scope = db->findScopeByName("getFormula1");
1937         ASSERT(scope != nullptr);
1938         ASSERT(scope && scope->nestedIn == &db->scopeList.front());
1939     }
1940 
memberFunctionOfUnknownClassMacro2()1941     void memberFunctionOfUnknownClassMacro2() {
1942         GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() SAL_OVERRIDE {} };\n"
1943                       "void getFormula1() {\n"
1944                       "    sal_uInt16 nFlags = 0;\n"
1945                       "    if (pDocSh && !getCellRangesForAddress(nFlags)) ;\n"
1946                       "}");
1947 
1948         ASSERT(db && errout.str().empty());
1949 
1950         const Scope *scope = db->findScopeByName("getFormula1");
1951         ASSERT(scope != nullptr);
1952         ASSERT(scope && scope->nestedIn == &db->scopeList.front());
1953 
1954         scope = db->findScopeByName("getServiceImplName");
1955         ASSERT(scope != nullptr);
1956         ASSERT(scope && scope->nestedIn && scope->nestedIn->className == "ScVbaFormatCondition");
1957     }
1958 
memberFunctionOfUnknownClassMacro3()1959     void memberFunctionOfUnknownClassMacro3() {
1960         GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() THROW(whatever); };\n"
1961                       "void ScVbaValidation::getFormula1() {\n"
1962                       "    sal_uInt16 nFlags = 0;\n"
1963                       "    if (pDocSh && !getCellRangesForAddress(nFlags)) ;\n"
1964                       "}");
1965 
1966         ASSERT(db && errout.str().empty());
1967 
1968         const Scope *scope = db->findScopeByName("getFormula1");
1969         ASSERT(scope != nullptr);
1970         ASSERT(scope && scope->nestedIn == &db->scopeList.front());
1971     }
1972 
functionLinkage()1973     void functionLinkage() {
1974         GET_SYMBOL_DB("static void f1() { }\n"
1975                       "void f2();\n"
1976                       "extern void f3();\n"
1977                       "void f4();\n"
1978                       "extern void f5() { };\n"
1979                       "void f6() { }");
1980 
1981         ASSERT(db && errout.str().empty());
1982 
1983         const Token *f = Token::findsimplematch(tokenizer.tokens(), "f1");
1984         ASSERT(f && f->function() && f->function()->isStaticLocal() && f->function()->retDef->str() == "void");
1985 
1986         f = Token::findsimplematch(tokenizer.tokens(), "f2");
1987         ASSERT(f && f->function() && !f->function()->isStaticLocal() && f->function()->retDef->str() == "void");
1988 
1989         f = Token::findsimplematch(tokenizer.tokens(), "f3");
1990         ASSERT(f && f->function() && f->function()->isExtern() && f->function()->retDef->str() == "void");
1991 
1992         f = Token::findsimplematch(tokenizer.tokens(), "f4");
1993         ASSERT(f && f->function() && !f->function()->isExtern() && f->function()->retDef->str() == "void");
1994 
1995         f = Token::findsimplematch(tokenizer.tokens(), "f5");
1996         ASSERT(f && f->function() && f->function()->isExtern() && f->function()->retDef->str() == "void");
1997 
1998         f = Token::findsimplematch(tokenizer.tokens(), "f6");
1999         ASSERT(f && f->function() && !f->function()->isExtern() && f->function()->retDef->str() == "void");
2000     }
2001 
classWithFriend()2002     void classWithFriend() {
2003         GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };");
2004         // 3 scopes: Global, 3 classes
2005         ASSERT(db && db->scopeList.size() == 4);
2006 
2007         const Scope* foo = db->findScopeByName("Foo");
2008         ASSERT(foo != nullptr);
2009         const Scope* bar1 = db->findScopeByName("Bar1");
2010         ASSERT(bar1 != nullptr);
2011         const Scope* bar2 = db->findScopeByName("Bar2");
2012         ASSERT(bar2 != nullptr);
2013 
2014         ASSERT(bar1->definedType->friendList.size() == 1 && bar1->definedType->friendList.front().nameEnd->str() == "Foo" && bar1->definedType->friendList.front().type == foo->definedType);
2015         ASSERT(bar2->definedType->friendList.size() == 1 && bar2->definedType->friendList.front().nameEnd->str() == "Foo" && bar2->definedType->friendList.front().type == foo->definedType);
2016     }
2017 
parseFunctionCorrect()2018     void parseFunctionCorrect() {
2019         // ticket 3188 - "if" statement parsed as function
2020         GET_SYMBOL_DB("void func(i) int i; { if (i == 1) return; }");
2021         ASSERT(db != nullptr);
2022 
2023         // 3 scopes: Global, function, if
2024         ASSERT_EQUALS(3, db->scopeList.size());
2025 
2026         ASSERT(findFunctionByName("func", &db->scopeList.back()) != nullptr);
2027         ASSERT(findFunctionByName("if", &db->scopeList.back()) == nullptr);
2028     }
2029 
parseFunctionDeclarationCorrect()2030     void parseFunctionDeclarationCorrect() {
2031         GET_SYMBOL_DB("void func();\n"
2032                       "int bar() {}\n"
2033                       "void func() {}");
2034         ASSERT_EQUALS(3, db->findScopeByName("func")->bodyStart->linenr());
2035     }
2036 
Cpp11InitInInitList()2037     void Cpp11InitInInitList() {
2038         GET_SYMBOL_DB("class Foo {\n"
2039                       "    std::vector<std::string> bar;\n"
2040                       "    Foo() : bar({\"a\", \"b\"})\n"
2041                       "    {}\n"
2042                       "};");
2043         ASSERT_EQUALS(4, db->scopeList.front().nestedList.front()->nestedList.front()->bodyStart->linenr());
2044     }
2045 
hasGlobalVariables1()2046     void hasGlobalVariables1() {
2047         GET_SYMBOL_DB("int i;");
2048 
2049         ASSERT(db && db->scopeList.size() == 1);
2050 
2051         std::list<Scope>::const_iterator it = db->scopeList.begin();
2052         ASSERT(it->varlist.size() == 1);
2053         std::list<Variable>::const_iterator var = it->varlist.begin();
2054         ASSERT(var->name() == "i");
2055         ASSERT(var->typeStartToken()->str() == "int");
2056     }
2057 
hasGlobalVariables2()2058     void hasGlobalVariables2() {
2059         GET_SYMBOL_DB("int array[2][2];");
2060 
2061         ASSERT(db && db->scopeList.size() == 1);
2062 
2063         std::list<Scope>::const_iterator it = db->scopeList.begin();
2064         ASSERT(it->varlist.size() == 1);
2065 
2066         std::list<Variable>::const_iterator var = it->varlist.begin();
2067         ASSERT(var->name() == "array");
2068         ASSERT(var->typeStartToken()->str() == "int");
2069     }
2070 
hasGlobalVariables3()2071     void hasGlobalVariables3() {
2072         GET_SYMBOL_DB("int array[2][2] = { { 0, 0 }, { 0, 0 } };");
2073 
2074         ASSERT(db && db->scopeList.size() == 1);
2075 
2076         std::list<Scope>::const_iterator it = db->scopeList.begin();
2077         ASSERT(it->varlist.size() == 1);
2078 
2079         std::list<Variable>::const_iterator var = it->varlist.begin();
2080         ASSERT(var->name() == "array");
2081         ASSERT(var->typeStartToken()->str() == "int");
2082     }
2083 
checkTypeStartEndToken1()2084     void checkTypeStartEndToken1() {
2085         GET_SYMBOL_DB("static std::string i;\n"
2086                       "static const std::string j;\n"
2087                       "const std::string* k;\n"
2088                       "const char m[];\n"
2089                       "void f(const char* const l;) {}");
2090 
2091         ASSERT(db && db->variableList().size() == 6 && db->getVariableFromVarId(1) && db->getVariableFromVarId(2) && db->getVariableFromVarId(3) && db->getVariableFromVarId(4) && db->getVariableFromVarId(5));
2092 
2093         ASSERT_EQUALS("std", db->getVariableFromVarId(1)->typeStartToken()->str());
2094         ASSERT_EQUALS("std", db->getVariableFromVarId(2)->typeStartToken()->str());
2095         ASSERT_EQUALS("std", db->getVariableFromVarId(3)->typeStartToken()->str());
2096         ASSERT_EQUALS("char", db->getVariableFromVarId(4)->typeStartToken()->str());
2097         ASSERT_EQUALS("char", db->getVariableFromVarId(5)->typeStartToken()->str());
2098 
2099         ASSERT_EQUALS("string", db->getVariableFromVarId(1)->typeEndToken()->str());
2100         ASSERT_EQUALS("string", db->getVariableFromVarId(2)->typeEndToken()->str());
2101         ASSERT_EQUALS("*", db->getVariableFromVarId(3)->typeEndToken()->str());
2102         ASSERT_EQUALS("char", db->getVariableFromVarId(4)->typeEndToken()->str());
2103         ASSERT_EQUALS("*", db->getVariableFromVarId(5)->typeEndToken()->str());
2104     }
2105 
checkTypeStartEndToken2()2106     void checkTypeStartEndToken2() {
2107         GET_SYMBOL_DB("class CodeGenerator {\n"
2108                       "  DiagnosticsEngine Diags;\n"
2109                       "public:\n"
2110                       "  void Initialize() {\n"
2111                       "    Builder.reset(Diags);\n"
2112                       "  }\n"
2113                       "\n"
2114                       "  void HandleTagDeclRequiredDefinition() LLVM_OVERRIDE {\n"
2115                       "    if (Diags.hasErrorOccurred())\n"
2116                       "      return;\n"
2117                       "  }\n"
2118                       "};");
2119         ASSERT_EQUALS("DiagnosticsEngine", db->getVariableFromVarId(1)->typeStartToken()->str());
2120     }
2121 
checkTypeStartEndToken3()2122     void checkTypeStartEndToken3() {
2123         GET_SYMBOL_DB("void f(const char) {}");
2124 
2125         ASSERT(db && db->functionScopes.size()==1U);
2126 
2127         const Function * const f = db->functionScopes.front()->function;
2128         ASSERT_EQUALS(1U, f->argCount());
2129         ASSERT_EQUALS(0U, f->initializedArgCount());
2130         ASSERT_EQUALS(1U, f->minArgCount());
2131         const Variable * const arg1 = f->getArgumentVar(0);
2132         ASSERT_EQUALS("char", arg1->typeStartToken()->str());
2133         ASSERT_EQUALS("char", arg1->typeEndToken()->str());
2134     }
2135 
check(const char code[],bool debug=true,const char filename[]="test.cpp")2136     void check(const char code[], bool debug = true, const char filename[] = "test.cpp") {
2137         // Clear the error log
2138         errout.str("");
2139 
2140         // Check..
2141         settings1.debugwarnings = debug;
2142 
2143         // Tokenize..
2144         Tokenizer tokenizer(&settings1, this);
2145         std::istringstream istr(code);
2146         tokenizer.tokenize(istr, filename);
2147 
2148         // force symbol database creation
2149         tokenizer.createSymbolDatabase();
2150 
2151         settings1.debugwarnings = false;
2152     }
2153 
functionArgs1()2154     void functionArgs1() {
2155         {
2156             GET_SYMBOL_DB("void f(std::vector<std::string>, const std::vector<int> & v) { }");
2157             ASSERT_EQUALS(1+1, db->variableList().size());
2158             const Variable* v = db->getVariableFromVarId(1);
2159             ASSERT(v && v->isReference() && v->isConst() && v->isArgument());
2160             const Scope* f = db->findScopeByName("f");
2161             ASSERT(f && f->type == Scope::eFunction && f->function);
2162 
2163             ASSERT(f->function->argumentList.size() == 2 && f->function->argumentList.front().index() == 0 && f->function->argumentList.front().name() == "" && f->function->argumentList.back().index() == 1);
2164             ASSERT_EQUALS("", errout.str());
2165         }
2166         {
2167             GET_SYMBOL_DB("void g(std::map<std::string, std::vector<int> > m) { }");
2168             ASSERT_EQUALS(1+1, db->variableList().size());
2169             const Variable* m = db->getVariableFromVarId(1);
2170             ASSERT(m && !m->isReference() && !m->isConst() && m->isArgument() && m->isClass());
2171             const Scope* g = db->findScopeByName("g");
2172             ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().index() == 0);
2173             ASSERT_EQUALS("", errout.str());
2174         }
2175         {
2176             GET_SYMBOL_DB("void g(std::map<int, int> m = std::map<int, int>()) { }");
2177             const Scope* g = db->findScopeByName("g");
2178             ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().index() == 0 && g->function->initializedArgCount() == 1);
2179             ASSERT_EQUALS("", errout.str());
2180         }
2181         {
2182             GET_SYMBOL_DB("void g(int = 0) { }");
2183             const Scope* g = db->findScopeByName("g");
2184             ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().hasDefault());
2185             ASSERT_EQUALS("", errout.str());
2186         }
2187         {
2188             GET_SYMBOL_DB("void g(int*) { }"); // unnamed pointer argument (#8052)
2189             const Scope* g = db->findScopeByName("g");
2190             ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().nameToken() == nullptr && g->function->argumentList.front().isPointer());
2191             ASSERT_EQUALS("", errout.str());
2192         }
2193         {
2194             GET_SYMBOL_DB("void g(int* const) { }"); // 'const' is not the name of the variable - #5882
2195             const Scope* g = db->findScopeByName("g");
2196             ASSERT(g && g->type == Scope::eFunction && g->function && g->function->argumentList.size() == 1 && g->function->argumentList.front().nameToken() == nullptr);
2197             ASSERT_EQUALS("", errout.str());
2198         }
2199     }
2200 
functionArgs2()2201     void functionArgs2() {
2202         GET_SYMBOL_DB("void f(int a[][4]) { }");
2203         const Variable *a = db->getVariableFromVarId(1);
2204         ASSERT_EQUALS("a", a->nameToken()->str());
2205         ASSERT_EQUALS(2UL, a->dimensions().size());
2206         ASSERT_EQUALS(0UL, a->dimension(0));
2207         ASSERT_EQUALS(false, a->dimensions()[0].known);
2208         ASSERT_EQUALS(4UL, a->dimension(1));
2209         ASSERT_EQUALS(true, a->dimensions()[1].known);
2210     }
2211 
functionArgs4()2212     void functionArgs4() {
2213         GET_SYMBOL_DB("void f1(char [10], struct foo [10]);");
2214         ASSERT_EQUALS(true, db->scopeList.front().functionList.size() == 1UL);
2215         const Function *func = &db->scopeList.front().functionList.front();
2216         ASSERT_EQUALS(true, func && func->argumentList.size() == 2UL);
2217 
2218         const Variable *first = &func->argumentList.front();
2219         ASSERT_EQUALS(0UL, first->name().size());
2220         ASSERT_EQUALS(1UL, first->dimensions().size());
2221         ASSERT_EQUALS(10UL, first->dimension(0));
2222         const Variable *second = &func->argumentList.back();
2223         ASSERT_EQUALS(0UL, second->name().size());
2224         ASSERT_EQUALS(1UL, second->dimensions().size());
2225         ASSERT_EQUALS(10UL, second->dimension(0));
2226     }
2227 
functionArgs5()2228     void functionArgs5() { // #7650
2229         GET_SYMBOL_DB("class ABC {};\n"
2230                       "class Y {\n"
2231                       "  enum ABC {A,B,C};\n"
2232                       "  void f(enum ABC abc) {}\n"
2233                       "};");
2234         ASSERT_EQUALS(true, db != nullptr);
2235         const Token *f = Token::findsimplematch(tokenizer.tokens(), "f ( enum");
2236         ASSERT_EQUALS(true, f && f->function());
2237         const Function *func = f->function();
2238         ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
2239         const Type * type = func->argumentList.front().type();
2240         ASSERT_EQUALS(true, type->isEnumType());
2241     }
2242 
functionArgs6()2243     void functionArgs6() { // #7651
2244         GET_SYMBOL_DB("class ABC {};\n"
2245                       "class Y {\n"
2246                       "  enum ABC {A,B,C};\n"
2247                       "  void f(ABC abc) {}\n"
2248                       "};");
2249         ASSERT_EQUALS(true, db != nullptr);
2250         const Token *f = Token::findsimplematch(tokenizer.tokens(), "f ( ABC");
2251         ASSERT_EQUALS(true, f && f->function());
2252         const Function *func = f->function();
2253         ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
2254         const Type * type = func->argumentList.front().type();
2255         ASSERT_EQUALS(true, type->isEnumType());
2256     }
2257 
functionArgs7()2258     void functionArgs7() { // #7652
2259         {
2260             GET_SYMBOL_DB("struct AB { int a; int b; };\n"
2261                           "int foo(struct AB *ab);\n"
2262                           "void bar() {\n"
2263                           "  struct AB ab;\n"
2264                           "  foo(&ab);\n"
2265                           "};");
2266             ASSERT_EQUALS(true, db != nullptr);
2267             const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
2268             ASSERT_EQUALS(true, f && f->function());
2269             const Function *func = f->function();
2270             ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
2271             const Type * type = func->argumentList.front().type();
2272             ASSERT_EQUALS(true, type->classDef->linenr() == 1);
2273         }
2274         {
2275             GET_SYMBOL_DB("struct AB { int a; int b; };\n"
2276                           "int foo(AB *ab);\n"
2277                           "void bar() {\n"
2278                           "  struct AB ab;\n"
2279                           "  foo(&ab);\n"
2280                           "};");
2281             ASSERT_EQUALS(true, db != nullptr);
2282             const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
2283             ASSERT_EQUALS(true, f && f->function());
2284             const Function *func = f->function();
2285             ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
2286             const Type * type = func->argumentList.front().type();
2287             ASSERT_EQUALS(true, type->classDef->linenr() == 1);
2288         }
2289         {
2290             GET_SYMBOL_DB("struct AB { int a; int b; };\n"
2291                           "int foo(struct AB *ab);\n"
2292                           "void bar() {\n"
2293                           "  AB ab;\n"
2294                           "  foo(&ab);\n"
2295                           "};");
2296             ASSERT_EQUALS(true, db != nullptr);
2297             const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
2298             ASSERT_EQUALS(true, f && f->function());
2299             const Function *func = f->function();
2300             ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
2301             const Type * type = func->argumentList.front().type();
2302             ASSERT_EQUALS(true, type->classDef->linenr() == 1);
2303         }
2304         {
2305             GET_SYMBOL_DB("struct AB { int a; int b; };\n"
2306                           "int foo(AB *ab);\n"
2307                           "void bar() {\n"
2308                           "  AB ab;\n"
2309                           "  foo(&ab);\n"
2310                           "};");
2311             ASSERT_EQUALS(true, db != nullptr);
2312             const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( & ab");
2313             ASSERT_EQUALS(true, f && f->function());
2314             const Function *func = f->function();
2315             ASSERT_EQUALS(true, func->tokenDef->linenr() == 2 && func->argumentList.size() == 1 && func->argumentList.front().type());
2316             const Type * type = func->argumentList.front().type();
2317             ASSERT_EQUALS(true, type->classDef->linenr() == 1);
2318         }
2319     }
2320 
functionArgs8()2321     void functionArgs8() { // #7653
2322         GET_SYMBOL_DB("struct A { int i; };\n"
2323                       "struct B { double d; };\n"
2324                       "int    foo(struct A a);\n"
2325                       "double foo(struct B b);\n"
2326                       "void bar() {\n"
2327                       "  struct B b;\n"
2328                       "  foo(b);\n"
2329                       "}");
2330         ASSERT_EQUALS(true, db != nullptr);
2331         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( b");
2332         ASSERT_EQUALS(true, f && f->function());
2333         const Function *func = f->function();
2334         ASSERT_EQUALS(true, func->tokenDef->linenr() == 4 && func->argumentList.size() == 1 && func->argumentList.front().type());
2335         const Type * type = func->argumentList.front().type();
2336         ASSERT_EQUALS(true, type->isStructType());
2337     }
2338 
functionArgs9()2339     void functionArgs9() { // #7657
2340         GET_SYMBOL_DB("struct A {\n"
2341                       "  struct B {\n"
2342                       "    enum C { };\n"
2343                       "  };\n"
2344                       "};\n"
2345                       "void foo(A::B::C c) { }");
2346         ASSERT_EQUALS(true, db != nullptr);
2347         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo (");
2348         ASSERT_EQUALS(true, f && f->function());
2349         const Function *func = f->function();
2350         ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
2351         const Type * type = func->argumentList.front().type();
2352         ASSERT_EQUALS(true, type->isEnumType());
2353     }
2354 
functionArgs10()2355     void functionArgs10() {
2356         GET_SYMBOL_DB("class Fred {\n"
2357                       "public:\n"
2358                       "  Fred(Whitespace = PRESERVE_WHITESPACE);\n"
2359                       "};\n"
2360                       "Fred::Fred(Whitespace whitespace) { }");
2361         ASSERT_EQUALS(true, db != nullptr);
2362         ASSERT_EQUALS(3, db->scopeList.size());
2363         std::list<Scope>::const_iterator scope = db->scopeList.begin();
2364         ++scope;
2365         ASSERT_EQUALS((unsigned int)Scope::eClass, (unsigned int)scope->type);
2366         ASSERT_EQUALS(1, scope->functionList.size());
2367         ASSERT(scope->functionList.begin()->functionScope != nullptr);
2368         const Scope * functionScope = scope->functionList.begin()->functionScope;
2369         ++scope;
2370         ASSERT(functionScope == &*scope);
2371     }
2372 
functionArgs11()2373     void functionArgs11() {
2374         GET_SYMBOL_DB("class Fred {\n"
2375                       "public:\n"
2376                       "  void foo(char a[16]);\n"
2377                       "};\n"
2378                       "void Fred::foo(char b[16]) { }");
2379         ASSERT_EQUALS(true, db != nullptr);
2380         ASSERT_EQUALS(3, db->scopeList.size());
2381         std::list<Scope>::const_iterator scope = db->scopeList.begin();
2382         ++scope;
2383         ASSERT_EQUALS((unsigned int)Scope::eClass, (unsigned int)scope->type);
2384         ASSERT_EQUALS(1, scope->functionList.size());
2385         ASSERT(scope->functionList.begin()->functionScope != nullptr);
2386         const Scope * functionScope = scope->functionList.begin()->functionScope;
2387         ++scope;
2388         ASSERT(functionScope == &*scope);
2389     }
2390 
functionArgs12()2391     void functionArgs12() { // #7661
2392         GET_SYMBOL_DB("struct A {\n"
2393                       "    enum E { };\n"
2394                       "    int a[10];\n"
2395                       "};\n"
2396                       "struct B : public A {\n"
2397                       "    void foo(B::E e) { }\n"
2398                       "};");
2399 
2400         ASSERT_EQUALS(true, db != nullptr);
2401         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo (");
2402         ASSERT_EQUALS(true, f && f->function());
2403         const Function *func = f->function();
2404         ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
2405         const Type * type = func->argumentList.front().type();
2406         ASSERT_EQUALS(true, type->isEnumType());
2407     }
2408 
functionArgs13()2409     void functionArgs13() { // #7697
2410         GET_SYMBOL_DB("struct A {\n"
2411                       "    enum E { };\n"
2412                       "    struct S { };\n"
2413                       "};\n"
2414                       "struct B : public A {\n"
2415                       "    B(E e);\n"
2416                       "    B(S s);\n"
2417                       "};\n"
2418                       "B::B(A::E e) { }\n"
2419                       "B::B(A::S s) { }");
2420 
2421         ASSERT_EQUALS(true, db != nullptr);
2422         const Token *f = Token::findsimplematch(tokenizer.tokens(), "B ( A :: E");
2423         ASSERT_EQUALS(true, f && f->function());
2424         const Function *func = f->function();
2425         ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type());
2426         const Type * type = func->argumentList.front().type();
2427         ASSERT_EQUALS(true, type->isEnumType() && type->name() == "E");
2428 
2429         f = Token::findsimplematch(tokenizer.tokens(), "B ( A :: S");
2430         ASSERT_EQUALS(true, f && f->function());
2431         const Function *func2 = f->function();
2432         ASSERT_EQUALS(true, func2->argumentList.size() == 1 && func2->argumentList.front().type());
2433         const Type * type2 = func2->argumentList.front().type();
2434         ASSERT_EQUALS(true, type2->isStructType() && type2->name() == "S");
2435     }
2436 
functionArgs14()2437     void functionArgs14() { // #7697
2438         GET_SYMBOL_DB("void f(int (&a)[10], int (&b)[10]);");
2439         (void)db;
2440         const Function *func = tokenizer.tokens()->next()->function();
2441         ASSERT_EQUALS(true, func != nullptr);
2442         ASSERT_EQUALS(2, func ? func->argCount() : 0);
2443         ASSERT_EQUALS(0, func ? func->initializedArgCount() : 1);
2444         ASSERT_EQUALS(2, func ? func->minArgCount() : 0);
2445     }
2446 
functionArgs15()2447     void functionArgs15() { // #7159
2448         const char code[] =
2449             "class Class {\n"
2450             "    void Method(\n"
2451             "        char c = []()->char {\n"
2452             "            int d = rand();\n"// the '=' on this line used to reproduce the defect
2453             "            return d;\n"
2454             "        }()\n"
2455             "    );\n"
2456             "};\n";
2457         GET_SYMBOL_DB(code);
2458         ASSERT(db);
2459         ASSERT_EQUALS(2, db->scopeList.size());
2460         const Scope& classScope = db->scopeList.back();
2461         ASSERT_EQUALS(Scope::eClass, classScope.type);
2462         ASSERT_EQUALS("Class", classScope.className);
2463         ASSERT_EQUALS(1, classScope.functionList.size());
2464         const Function& method = classScope.functionList.front();
2465         ASSERT_EQUALS("Method", method.name());
2466         ASSERT_EQUALS(1, method.argCount());
2467         ASSERT_EQUALS(1, method.initializedArgCount());
2468         ASSERT_EQUALS(0, method.minArgCount());
2469     }
2470 
functionArgs16()2471     void functionArgs16() { // #9591
2472         const char code[] =
2473             "struct A { int var; };\n"
2474             "void foo(int x, decltype(A::var) *&p) {}";
2475         GET_SYMBOL_DB(code);
2476         ASSERT(db);
2477         const Scope *scope = db->functionScopes.front();
2478         const Function *func = scope->function;
2479         ASSERT_EQUALS(2, func->argCount());
2480         const Variable *arg2 = func->getArgumentVar(1);
2481         ASSERT_EQUALS("p", arg2->name());
2482         ASSERT(arg2->isPointer());
2483         ASSERT(arg2->isReference());
2484     }
2485 
functionArgs17()2486     void functionArgs17() {
2487         const char code[] = "void f(int (*fp)(), int x, int y) {}";
2488         GET_SYMBOL_DB(code);
2489         ASSERT(db != nullptr);
2490         const Scope *scope = db->functionScopes.front();
2491         const Function *func = scope->function;
2492         ASSERT_EQUALS(3, func->argCount());
2493     }
2494 
functionArgs18()2495     void functionArgs18() {
2496         const char code[] = "void f(int (*param1)[2], int param2) {}";
2497         GET_SYMBOL_DB(code);
2498         ASSERT(db != nullptr);
2499         const Scope *scope = db->functionScopes.front();
2500         const Function *func = scope->function;
2501         ASSERT_EQUALS(2, func->argCount());
2502     }
2503 
functionImplicitlyVirtual()2504     void functionImplicitlyVirtual() {
2505         GET_SYMBOL_DB("class base { virtual void f(); };\n"
2506                       "class derived : base { void f(); };\n"
2507                       "void derived::f() {}");
2508         ASSERT(db != nullptr);
2509         ASSERT_EQUALS(4, db->scopeList.size());
2510         const Function *function = db->scopeList.back().function;
2511         ASSERT_EQUALS(true, function && function->isImplicitlyVirtual(false));
2512     }
2513 
functionIsInlineKeyword()2514     void functionIsInlineKeyword() {
2515         GET_SYMBOL_DB("inline void fs() {}");
2516         (void)db;
2517         const Function *func = db->scopeList.back().function;
2518         ASSERT(func);
2519         ASSERT(func->isInlineKeyword());
2520     }
2521 
functionStatic()2522     void functionStatic() {
2523         GET_SYMBOL_DB("static void fs() {  }");
2524         (void)db;
2525         const Function *func = db->scopeList.back().function;
2526         ASSERT(func);
2527         ASSERT(func->isStatic());
2528     }
2529 
functionReturnsReference()2530     void functionReturnsReference() {
2531         GET_SYMBOL_DB("Fred::Reference foo();");
2532         ASSERT_EQUALS(1, db->scopeList.back().functionList.size());
2533         const Function &func = *db->scopeList.back().functionList.begin();
2534         ASSERT(!Function::returnsReference(&func, false));
2535         ASSERT(Function::returnsReference(&func, true));
2536     }
2537 
namespaces1()2538     void namespaces1() {
2539         GET_SYMBOL_DB("namespace fred {\n"
2540                       "    namespace barney {\n"
2541                       "        class X { X(int); };\n"
2542                       "    }\n"
2543                       "}\n"
2544                       "namespace barney { X::X(int) { } }");
2545 
2546         // Locate the scope for the class..
2547         const Scope *scope = nullptr;
2548         for (const Scope & it : db->scopeList) {
2549             if (it.isClassOrStruct()) {
2550                 scope = &it;
2551                 break;
2552             }
2553         }
2554 
2555         ASSERT(scope != nullptr);
2556         if (!scope)
2557             return;
2558 
2559         ASSERT_EQUALS("X", scope->className);
2560 
2561         // The class has a constructor but the implementation _is not_ seen
2562         ASSERT_EQUALS(1U, scope->functionList.size());
2563         const Function *function = &(scope->functionList.front());
2564         ASSERT_EQUALS(false, function->hasBody());
2565     }
2566 
2567     // based on namespaces1 but here the namespaces match
namespaces2()2568     void namespaces2() {
2569         GET_SYMBOL_DB("namespace fred {\n"
2570                       "    namespace barney {\n"
2571                       "        class X { X(int); };\n"
2572                       "    }\n"
2573                       "}\n"
2574                       "namespace fred {\n"
2575                       "    namespace barney {\n"
2576                       "        X::X(int) { }\n"
2577                       "    }\n"
2578                       "}");
2579 
2580         // Locate the scope for the class..
2581         const Scope *scope = nullptr;
2582         for (const Scope & it : db->scopeList) {
2583             if (it.isClassOrStruct()) {
2584                 scope = &it;
2585                 break;
2586             }
2587         }
2588 
2589         ASSERT(scope != nullptr);
2590         if (!scope)
2591             return;
2592 
2593         ASSERT_EQUALS("X", scope->className);
2594 
2595         // The class has a constructor and the implementation _is_ seen
2596         ASSERT_EQUALS(1U, scope->functionList.size());
2597         const Function *function = &(scope->functionList.front());
2598         ASSERT_EQUALS("X", function->tokenDef->str());
2599         ASSERT_EQUALS(true, function->hasBody());
2600     }
2601 
namespaces3()2602     void namespaces3() { // #3854 - namespace with unknown macro
2603         GET_SYMBOL_DB("namespace fred UNKNOWN_MACRO(default) {\n"
2604                       "}");
2605         ASSERT_EQUALS(2U, db->scopeList.size());
2606         ASSERT_EQUALS(Scope::eGlobal, db->scopeList.front().type);
2607         ASSERT_EQUALS(Scope::eNamespace, db->scopeList.back().type);
2608     }
2609 
namespaces4()2610     void namespaces4() { // #4698 - type lookup
2611         GET_SYMBOL_DB("struct A { int a; };\n"
2612                       "namespace fred { struct A {}; }\n"
2613                       "fred::A fredA;");
2614         const Variable *fredA = db->getVariableFromVarId(2U);
2615         ASSERT_EQUALS("fredA", fredA->name());
2616         const Type *fredAType = fredA->type();
2617         ASSERT_EQUALS(2U, fredAType->classDef->linenr());
2618     }
2619 
tryCatch1()2620     void tryCatch1() {
2621         const char str[] = "void foo() {\n"
2622                            "    try { }\n"
2623                            "    catch (const Error1 & x) { }\n"
2624                            "    catch (const X::Error2 & x) { }\n"
2625                            "    catch (Error3 x) { }\n"
2626                            "    catch (X::Error4 x) { }\n"
2627                            "}";
2628         GET_SYMBOL_DB(str);
2629         ASSERT_EQUALS("", errout.str());
2630         ASSERT(db && db->variableList().size() == 5); // index 0 + 4 variables
2631         ASSERT(db && db->scopeList.size() == 7); // global + function + try + 4 catch
2632     }
2633 
2634 
symboldatabase1()2635     void symboldatabase1() {
2636         check("namespace foo {\n"
2637               "    class bar;\n"
2638               "};");
2639         ASSERT_EQUALS("", errout.str());
2640 
2641         check("class foo : public bar < int, int> {\n"
2642               "};");
2643         ASSERT_EQUALS("", errout.str());
2644     }
2645 
symboldatabase2()2646     void symboldatabase2() {
2647         check("class foo {\n"
2648               "public slots :\n"
2649               "foo() { }\n"
2650               "};");
2651         ASSERT_EQUALS("", errout.str());
2652 
2653         check("class foo {\n"
2654               "class bar;\n"
2655               "foo() { }\n"
2656               "};");
2657         ASSERT_EQUALS("", errout.str());
2658     }
2659 
symboldatabase3()2660     void symboldatabase3() {
2661         check("typedef void (func_type)();\n"
2662               "struct A {\n"
2663               "    friend func_type f : 2;\n"
2664               "};");
2665         ASSERT_EQUALS("", errout.str());
2666     }
2667 
symboldatabase4()2668     void symboldatabase4() {
2669         check("static void function_declaration_before(void) __attribute__((__used__));\n"
2670               "static void function_declaration_before(void) {}\n"
2671               "static void function_declaration_after(void) {}\n"
2672               "static void function_declaration_after(void) __attribute__((__used__));");
2673         ASSERT_EQUALS("", errout.str());
2674 
2675         check("main(int argc, char *argv[]) { }", true, "test.c");
2676         ASSERT_EQUALS("[test.c:1]: (debug) SymbolDatabase::isFunction found C function 'main' without a return type.\n", errout.str());
2677 
2678         check("namespace boost {\n"
2679               "    std::locale generate_locale()\n"
2680               "    {\n"
2681               "        return std::locale();\n"
2682               "    }\n"
2683               "}");
2684         ASSERT_EQUALS("", errout.str());
2685 
2686         check("namespace X {\n"
2687               "    static void function_declaration_before(void) __attribute__((__used__));\n"
2688               "    static void function_declaration_before(void) {}\n"
2689               "    static void function_declaration_after(void) {}\n"
2690               "    static void function_declaration_after(void) __attribute__((__used__));\n"
2691               "}");
2692         ASSERT_EQUALS("", errout.str());
2693 
2694         check("testing::testing()\n"
2695               "{\n"
2696               "}");
2697         ASSERT_EQUALS("[test.cpp:1]: (debug) Executable scope 'testing' with unknown function.\n", errout.str());
2698     }
2699 
symboldatabase5()2700     void symboldatabase5() {
2701         // ticket #2178 - segmentation fault
2702         ASSERT_THROW(check("int CL_INLINE_DECL(integer_decode_float) (int x) {\n"
2703                            "    return (sign ? cl_I() : 0);\n"
2704                            "}"), InternalError);
2705     }
2706 
symboldatabase6()2707     void symboldatabase6() {
2708         // ticket #2221 - segmentation fault
2709         check("template<int i> class X { };\n"
2710               "X< 1>2 > x1;\n"
2711               "X<(1>2)> x2;\n"
2712               "template<class T> class Y { };\n"
2713               "Y<X<1>> x3;\n"
2714               "Y<X<6>>1>> x4;\n"
2715               "Y<X<(6>>1)>> x5;\n", false);
2716         ASSERT_EQUALS("", errout.str());
2717     }
2718 
symboldatabase7()2719     void symboldatabase7() {
2720         // ticket #2230 - segmentation fault
2721         check("template<template<class> class E,class D> class C : E<D>\n"
2722               "{\n"
2723               "public:\n"
2724               "    int f();\n"
2725               "};\n"
2726               "class E : C<D,int>\n"
2727               "{\n"
2728               "public:\n"
2729               "    int f() { return C< ::D,int>::f(); }\n"
2730               "};");
2731         ASSERT_EQUALS("", errout.str());
2732     }
2733 
symboldatabase8()2734     void symboldatabase8() {
2735         // ticket #2252 - segmentation fault
2736         check("struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,\n"
2737               "                                                           PaletteColorSpaceHolder>\n"
2738               "{\n"
2739               "    uno::Reference<rendering::XColorSpace> operator()()\n"
2740               "    {\n"
2741               "        return vcl::unotools::createStandardColorSpace();\n"
2742               "    }\n"
2743               "};");
2744 
2745         ASSERT_EQUALS("", errout.str());
2746     }
2747 
symboldatabase9()2748     void symboldatabase9() {
2749         // ticket #2425 - segmentation fault
2750         check("class CHyperlink : public CString\n"
2751               "{\n"
2752               "public:\n"
2753               "    const CHyperlink& operator=(LPCTSTR lpsz) {\n"
2754               "        CString::operator=(lpsz);\n"
2755               "        return *this;\n"
2756               "    }\n"
2757               "};\n", false);
2758 
2759         ASSERT_EQUALS("", errout.str());
2760     }
2761 
symboldatabase10()2762     void symboldatabase10() {
2763         // ticket #2537 - segmentation fault
2764         check("class A {\n"
2765               "private:\n"
2766               "  void f();\n"
2767               "};\n"
2768               "class B {\n"
2769               "  friend void A::f();\n"
2770               "};");
2771 
2772         ASSERT_EQUALS("", errout.str());
2773     }
2774 
symboldatabase11()2775     void symboldatabase11() {
2776         // ticket #2539 - segmentation fault
2777         check("int g ();\n"
2778               "struct S {\n"
2779               "  int i : (false ? g () : 1);\n"
2780               "};");
2781 
2782         ASSERT_EQUALS("", errout.str());
2783     }
2784 
symboldatabase12()2785     void symboldatabase12() {
2786         // ticket #2547 - segmentation fault
2787         check("class foo {\n"
2788               "    void bar2 () = __null;\n"
2789               "};");
2790 
2791         ASSERT_EQUALS("", errout.str());
2792     }
2793 
symboldatabase13()2794     void symboldatabase13() {
2795         // ticket #2577 - segmentation fault
2796         check("class foo {\n"
2797               "    void bar2 () = A::f;\n"
2798               "};");
2799 
2800         ASSERT_EQUALS("", errout.str());
2801     }
2802 
symboldatabase14()2803     void symboldatabase14() {
2804         // ticket #2589 - segmentation fault
2805         ASSERT_THROW(check("struct B : A\n"), InternalError);
2806     }
2807 
symboldatabase17()2808     void symboldatabase17() {
2809         // ticket #2657 - segmentation fault
2810         check("{return f(){}}");
2811 
2812         ASSERT_EQUALS("", errout.str());
2813     }
2814 
symboldatabase19()2815     void symboldatabase19() {
2816         // ticket #2991 - segmentation fault
2817         check("::y(){x}");
2818 
2819         ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:1]: (debug) Executable scope 'y' with unknown function.\n"
2820                                           "[test.cpp:1]: (debug) valueflow.cpp:1321:valueFlowConditionExpressions bailout: Skipping function due to incomplete variable x\n", errout.str());
2821     }
2822 
symboldatabase20()2823     void symboldatabase20() {
2824         // ticket #3013 - segmentation fault
2825         ASSERT_THROW(check("struct x : virtual y\n"), InternalError);
2826     }
2827 
symboldatabase21()2828     void symboldatabase21() {
2829         check("class Fred {\n"
2830               "    class Foo { };\n"
2831               "    void func() const;\n"
2832               "};\n"
2833               "Fred::func() const {\n"
2834               "    Foo foo;\n"
2835               "}");
2836 
2837         ASSERT_EQUALS("", errout.str());
2838     }
2839 
2840     // ticket 3437 (segmentation fault)
symboldatabase22()2841     void symboldatabase22() {
2842         check("template <class C> struct A {};\n"
2843               "A<int> a;");
2844         ASSERT_EQUALS("", errout.str());
2845     }
2846 
2847     // ticket 3435 (std::vector)
symboldatabase23()2848     void symboldatabase23() {
2849         GET_SYMBOL_DB("class A { std::vector<int*> ints; };");
2850         ASSERT_EQUALS(2U, db->scopeList.size());
2851         const Scope &scope = db->scopeList.back();
2852         ASSERT_EQUALS(1U, scope.varlist.size());
2853         const Variable &var = scope.varlist.front();
2854         ASSERT_EQUALS(std::string("ints"), var.name());
2855         ASSERT_EQUALS(true, var.isClass());
2856     }
2857 
2858     // ticket 3508 (constructor, destructor)
symboldatabase24()2859     void symboldatabase24() {
2860         GET_SYMBOL_DB("struct Fred {\n"
2861                       "    ~Fred();\n"
2862                       "    Fred();\n"
2863                       "};\n"
2864                       "Fred::Fred() { }\n"
2865                       "Fred::~Fred() { }");
2866         // Global scope, Fred, Fred::Fred, Fred::~Fred
2867         ASSERT_EQUALS(4U, db->scopeList.size());
2868 
2869         // Find the scope for the Fred struct..
2870         const Scope *fredScope = nullptr;
2871         for (const Scope & scope : db->scopeList) {
2872             if (scope.isClassOrStruct() && scope.className == "Fred")
2873                 fredScope = &scope;
2874         }
2875         ASSERT(fredScope != nullptr);
2876 
2877         // The struct Fred has two functions, a constructor and a destructor
2878         ASSERT_EQUALS(2U, fredScope->functionList.size());
2879 
2880         // Get linenumbers where the bodies for the constructor and destructor are..
2881         unsigned int constructor = 0;
2882         unsigned int destructor = 0;
2883         for (const Function & it : fredScope->functionList) {
2884             if (it.type == Function::eConstructor)
2885                 constructor = it.token->linenr();  // line number for constructor body
2886             if (it.type == Function::eDestructor)
2887                 destructor = it.token->linenr();  // line number for destructor body
2888         }
2889 
2890         // The body for the constructor is located at line 5..
2891         ASSERT_EQUALS(5U, constructor);
2892 
2893         // The body for the destructor is located at line 6..
2894         ASSERT_EQUALS(6U, destructor);
2895 
2896     }
2897 
2898     // ticket #3561 (throw C++)
symboldatabase25()2899     void symboldatabase25() {
2900         const char str[] = "int main() {\n"
2901                            "    foo bar;\n"
2902                            "    throw bar;\n"
2903                            "}";
2904         GET_SYMBOL_DB(str);
2905         ASSERT_EQUALS("", errout.str());
2906         ASSERT(db && db->variableList().size() == 2); // index 0 + 1 variable
2907     }
2908 
2909     // ticket #3561 (throw C)
symboldatabase26()2910     void symboldatabase26() {
2911         const char str[] = "int main() {\n"
2912                            "    throw bar;\n"
2913                            "}";
2914         GET_SYMBOL_DB_C(str);
2915         ASSERT_EQUALS("", errout.str());
2916         ASSERT(db && db->variableList().size() == 2); // index 0 + 1 variable
2917     }
2918 
2919     // ticket #3543 (segmentation fault)
symboldatabase27()2920     void symboldatabase27() {
2921         check("class C : public B1\n"
2922               "{\n"
2923               "    B1()\n"
2924               "    {} C(int) : B1() class\n"
2925               "};");
2926         ASSERT_EQUALS("", errout.str());
2927     }
2928 
symboldatabase28()2929     void symboldatabase28() {
2930         GET_SYMBOL_DB("struct S {};\n"
2931                       "void foo(struct S s) {}");
2932         ASSERT(db && db->getVariableFromVarId(1) && db->getVariableFromVarId(1)->typeScope() && db->getVariableFromVarId(1)->typeScope()->className == "S");
2933     }
2934 
2935     // ticket #4442 (segmentation fault)
symboldatabase29()2936     void symboldatabase29() {
2937         check("struct B : A {\n"
2938               "    B() : A {}\n"
2939               "};");
2940         ASSERT_EQUALS("", errout.str());
2941     }
2942 
symboldatabase30()2943     void symboldatabase30() {
2944         GET_SYMBOL_DB("struct A { void foo(const int a); };\n"
2945                       "void A::foo(int a) { }");
2946         ASSERT(db && db->functionScopes.size() == 1 && db->functionScopes[0]->functionOf);
2947     }
2948 
symboldatabase31()2949     void symboldatabase31() {
2950         GET_SYMBOL_DB("class Foo;\n"
2951                       "class Bar;\n"
2952                       "class Sub;\n"
2953                       "class Foo { class Sub; };\n"
2954                       "class Bar { class Sub; };\n"
2955                       "class Bar::Sub {\n"
2956                       "    int b;\n"
2957                       "public:\n"
2958                       "    Sub() { }\n"
2959                       "    Sub(int);\n"
2960                       "};\n"
2961                       "Bar::Sub::Sub(int) { };\n"
2962                       "class ::Foo::Sub {\n"
2963                       "    int f;\n"
2964                       "public:\n"
2965                       "    ~Sub();\n"
2966                       "    Sub();\n"
2967                       "};\n"
2968                       "::Foo::Sub::~Sub() { }\n"
2969                       "::Foo::Sub::Sub() { }\n"
2970                       "class Foo;\n"
2971                       "class Bar;\n"
2972                       "class Sub;");
2973         ASSERT(db && db->typeList.size() == 5);
2974 
2975         std::list<Type>::const_iterator i = db->typeList.begin();
2976         const Type* Foo = &(*i++);
2977         const Type* Bar = &(*i++);
2978         const Type* Sub = &(*i++);
2979         const Type* Foo_Sub = &(*i++);
2980         const Type* Bar_Sub = &(*i);
2981         ASSERT(Foo && Foo->classDef && Foo->classScope && Foo->enclosingScope && Foo->name() == "Foo");
2982         ASSERT(Bar && Bar->classDef && Bar->classScope && Bar->enclosingScope && Bar->name() == "Bar");
2983         ASSERT(Sub && Sub->classDef && !Sub->classScope && Sub->enclosingScope && Sub->name() == "Sub");
2984         ASSERT(Foo_Sub && Foo_Sub->classDef && Foo_Sub->classScope && Foo_Sub->enclosingScope == Foo->classScope && Foo_Sub->name() == "Sub");
2985         ASSERT(Bar_Sub && Bar_Sub->classDef && Bar_Sub->classScope && Bar_Sub->enclosingScope == Bar->classScope && Bar_Sub->name() == "Sub");
2986         ASSERT(Foo_Sub && Foo_Sub->classScope && Foo_Sub->classScope->numConstructors == 1 && Foo_Sub->classScope->className == "Sub");
2987         ASSERT(Bar_Sub && Bar_Sub->classScope && Bar_Sub->classScope->numConstructors == 2 && Bar_Sub->classScope->className == "Sub");
2988     }
2989 
symboldatabase32()2990     void symboldatabase32() {
2991         GET_SYMBOL_DB("struct Base {\n"
2992                       "    void foo() {}\n"
2993                       "};\n"
2994                       "class Deri : Base {\n"
2995                       "};");
2996         ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->definedType->getFunction("foo"));
2997     }
2998 
symboldatabase33()2999     void symboldatabase33() { // ticket #4682
3000         GET_SYMBOL_DB("static struct A::B s;\n"
3001                       "static struct A::B t = { 0 };\n"
3002                       "static struct A::B u(0);\n"
3003                       "static struct A::B v{0};\n"
3004                       "static struct A::B w({0});\n"
3005                       "void foo() { }");
3006         ASSERT(db && db->functionScopes.size() == 1);
3007     }
3008 
symboldatabase34()3009     void symboldatabase34() { // ticket #4694
3010         check("typedef _Atomic(int(A::*)) atomic_mem_ptr_to_int;\n"
3011               "typedef _Atomic(int)&atomic_int_ref;\n"
3012               "struct S {\n"
3013               "  _Atomic union { int n; };\n"
3014               "};");
3015         ASSERT_EQUALS("[test.cpp:2]: (debug) Failed to parse 'typedef _Atomic ( int ) & atomic_int_ref ;'. The checking continues anyway.\n", errout.str());
3016     }
3017 
symboldatabase35()3018     void symboldatabase35() { // ticket #4806 and #4841
3019         check("class FragmentQueue : public CL_NS(util)::PriorityQueue<CL_NS(util)::Deletor::Object<TextFragment> >\n"
3020               "{};");
3021         ASSERT_EQUALS("", errout.str());
3022     }
3023 
symboldatabase36()3024     void symboldatabase36() { // ticket #4892
3025         check("void struct ( ) { if ( 1 ) } int main ( ) { }");
3026         ASSERT_EQUALS("", errout.str());
3027     }
3028 
symboldatabase37()3029     void symboldatabase37() {
3030         GET_SYMBOL_DB("class Fred {\n"
3031                       "public:\n"
3032                       "    struct Wilma { };\n"
3033                       "    struct Barney {\n"
3034                       "        bool operator == (const struct Barney & b) const { return true; }\n"
3035                       "        bool operator == (const struct Wilma & w) const { return true; }\n"
3036                       "    };\n"
3037                       "    Fred(const struct Barney & b) { barney = b; }\n"
3038                       "private:\n"
3039                       "    struct Barney barney;\n"
3040                       "};");
3041         ASSERT(db && db->typeList.size() == 3);
3042 
3043         std::list<Type>::const_iterator i = db->typeList.begin();
3044         const Type* Fred = &(*i++);
3045         const Type* Wilma = &(*i++);
3046         const Type* Barney = &(*i++);
3047         ASSERT(Fred && Fred->classDef && Fred->classScope && Fred->enclosingScope && Fred->name() == "Fred");
3048         ASSERT(Wilma && Wilma->classDef && Wilma->classScope && Wilma->enclosingScope && Wilma->name() == "Wilma");
3049         ASSERT(Barney && Barney->classDef && Barney->classScope && Barney->enclosingScope && Barney->name() == "Barney");
3050         ASSERT(db->variableList().size() == 5);
3051 
3052         ASSERT(db->getVariableFromVarId(1) && db->getVariableFromVarId(1)->type() && db->getVariableFromVarId(1)->type()->name() == "Barney");
3053         ASSERT(db->getVariableFromVarId(2) && db->getVariableFromVarId(2)->type() && db->getVariableFromVarId(2)->type()->name() == "Wilma");
3054         ASSERT(db->getVariableFromVarId(3) && db->getVariableFromVarId(3)->type() && db->getVariableFromVarId(3)->type()->name() == "Barney");
3055     }
3056 
symboldatabase38()3057     void symboldatabase38() { // ticket #5125
3058         check("template <typename T = class service> struct scoped_service;\n"
3059               "struct service {};\n"
3060               "template <> struct scoped_service<service> {};\n"
3061               "template <typename T>\n"
3062               "struct scoped_service : scoped_service<service>\n"
3063               "{\n"
3064               "  scoped_service( T* ptr ) : scoped_service<service>(ptr), m_ptr(ptr) {}\n"
3065               "  T* const m_ptr;\n"
3066               "};");
3067     }
3068 
symboldatabase40()3069     void symboldatabase40() { // ticket #5153
3070         check("void f() {\n"
3071               "    try {  }\n"
3072               "    catch (std::bad_alloc) {  }\n"
3073               "}");
3074         ASSERT_EQUALS("", errout.str());
3075     }
3076 
symboldatabase41()3077     void symboldatabase41() { // ticket #5197 (unknown macro)
3078         GET_SYMBOL_DB("struct X1 { MACRO1 f(int spd) MACRO2; };");
3079         ASSERT(db && db->findScopeByName("X1") && db->findScopeByName("X1")->functionList.size() == 1 && !db->findScopeByName("X1")->functionList.front().hasBody());
3080     }
3081 
symboldatabase42()3082     void symboldatabase42() { // only put variables in variable list
3083         GET_SYMBOL_DB("void f() { extern int x(); }");
3084         ASSERT(db != nullptr);
3085         const Scope * const fscope = db ? db->findScopeByName("f") : nullptr;
3086         ASSERT(fscope != nullptr);
3087         ASSERT_EQUALS(0U, fscope ? fscope->varlist.size() : ~0U);  // "x" is not a variable
3088     }
3089 
symboldatabase43()3090     void symboldatabase43() { // ticket #4738
3091         check("void f() {\n"
3092               "    new int;\n"
3093               "}");
3094         ASSERT_EQUALS("", errout.str());
3095     }
3096 
symboldatabase44()3097     void symboldatabase44() {
3098         GET_SYMBOL_DB("int i { 1 };\n"
3099                       "int j ( i );\n"
3100                       "void foo() {\n"
3101                       "    int k { 1 };\n"
3102                       "    int l ( 1 );\n"
3103                       "}");
3104         ASSERT(db != nullptr);
3105         ASSERT_EQUALS(4U, db->variableList().size() - 1);
3106         ASSERT_EQUALS(2U, db->scopeList.size());
3107         for (std::size_t i = 1U; i < db->variableList().size(); i++)
3108             ASSERT(db->getVariableFromVarId(i) != nullptr);
3109     }
3110 
symboldatabase45()3111     void symboldatabase45() {
3112         GET_SYMBOL_DB("typedef struct {\n"
3113                       "    unsigned long bits;\n"
3114                       "} S;\n"
3115                       "struct T {\n"
3116                       "    S span;\n"
3117                       "    int flags;\n"
3118                       "};\n"
3119                       "struct T f(int x) {\n"
3120                       "    return (struct T) {\n"
3121                       "        .span = (S) { 0UL },\n"
3122                       "        .flags = (x ? 256 : 0),\n"
3123                       "    };\n"
3124                       "}");
3125 
3126         ASSERT(db != nullptr);
3127         ASSERT_EQUALS(4U, db->variableList().size() - 1);
3128         for (std::size_t i = 1U; i < db->variableList().size(); i++)
3129             ASSERT(db->getVariableFromVarId(i) != nullptr);
3130 
3131         ASSERT_EQUALS(4U, db->scopeList.size());
3132         std::list<Scope>::const_iterator scope = db->scopeList.begin();
3133         ASSERT_EQUALS(Scope::eGlobal, scope->type);
3134         ++scope;
3135         ASSERT_EQUALS(Scope::eStruct, scope->type);
3136         ++scope;
3137         ASSERT_EQUALS(Scope::eStruct, scope->type);
3138         ++scope;
3139         ASSERT_EQUALS(Scope::eFunction, scope->type);
3140     }
3141 
symboldatabase46()3142     void symboldatabase46() { // #6171 (anonymous namespace)
3143         GET_SYMBOL_DB("struct S { };\n"
3144                       "namespace {\n"
3145                       "    struct S { };\n"
3146                       "}");
3147 
3148         ASSERT(db != nullptr);
3149         ASSERT_EQUALS(4U, db->scopeList.size());
3150         std::list<Scope>::const_iterator scope = db->scopeList.begin();
3151         ASSERT_EQUALS(Scope::eGlobal, scope->type);
3152         ++scope;
3153         ASSERT_EQUALS(Scope::eStruct, scope->type);
3154         ASSERT_EQUALS(scope->className, "S");
3155         ++scope;
3156         ASSERT_EQUALS(Scope::eNamespace, scope->type);
3157         ASSERT_EQUALS(scope->className, "");
3158         ++scope;
3159         ASSERT_EQUALS(Scope::eStruct, scope->type);
3160         ASSERT_EQUALS(scope->className, "S");
3161     }
3162 
symboldatabase47()3163     void symboldatabase47() { // #6308 - associate Function and Scope for destructors
3164         GET_SYMBOL_DB("namespace NS {\n"
3165                       "    class MyClass {\n"
3166                       "        ~MyClass();\n"
3167                       "    };\n"
3168                       "}\n"
3169                       "using namespace NS;\n"
3170                       "MyClass::~MyClass() {\n"
3171                       "    delete Example;\n"
3172                       "}");
3173         ASSERT(db && !db->functionScopes.empty() && db->functionScopes.front()->function && db->functionScopes.front()->function->functionScope == db->functionScopes.front());
3174     }
3175 
symboldatabase48()3176     void symboldatabase48() { // #6417
3177         GET_SYMBOL_DB("namespace NS {\n"
3178                       "    class MyClass {\n"
3179                       "        MyClass();\n"
3180                       "        ~MyClass();\n"
3181                       "    };\n"
3182                       "}\n"
3183                       "using namespace NS;\n"
3184                       "MyClass::~MyClass() { }\n"
3185                       "MyClass::MyClass() { }");
3186         ASSERT(db && !db->functionScopes.empty() && db->functionScopes.front()->function && db->functionScopes.front()->function->functionScope == db->functionScopes.front());
3187 
3188         const Token *f = Token::findsimplematch(tokenizer.tokens(), "MyClass ( ) ;");
3189         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3 && f->function()->token->linenr() == 9);
3190 
3191         f = Token::findsimplematch(tokenizer.tokens(), "~ MyClass ( ) ;");
3192         f = f->next();
3193         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4 && f->function()->token->linenr() == 8);
3194     }
3195 
symboldatabase49()3196     void symboldatabase49() { // #6424
3197         GET_SYMBOL_DB("namespace Ns { class C; }\n"
3198                       "void f1() { char *p; *p = 0; }\n"
3199                       "class Ns::C* p;\n"
3200                       "void f2() { char *p; *p = 0; }");
3201         ASSERT(db != nullptr);
3202         const Token *f = Token::findsimplematch(tokenizer.tokens(), "p ; void f2");
3203         ASSERT_EQUALS(true, db && f && f->variable());
3204         f = Token::findsimplematch(tokenizer.tokens(), "f2");
3205         ASSERT_EQUALS(true, db && f && f->function());
3206     }
3207 
symboldatabase50()3208     void symboldatabase50() { // #6432
3209         GET_SYMBOL_DB("template <bool del, class T>\n"
3210                       "class _ConstTessMemberResultCallback_0_0<del, void, T>\n"
3211                       "   {\n"
3212                       " public:\n"
3213                       "  typedef void (T::*MemberSignature)() const;\n"
3214                       "\n"
3215                       " private:\n"
3216                       "  const T* object_;\n"
3217                       "  MemberSignature member_;\n"
3218                       "\n"
3219                       " public:\n"
3220                       "  inline _ConstTessMemberResultCallback_0_0(\n"
3221                       "      const T* object, MemberSignature member)\n"
3222                       "    : object_(object),\n"
3223                       "      member_(member) {\n"
3224                       "  }\n"
3225                       "};");
3226         ASSERT(db != nullptr);
3227         const Token *f = Token::findsimplematch(tokenizer.tokens(), "_ConstTessMemberResultCallback_0_0 (");
3228         ASSERT_EQUALS(true, db && f && f->function() && f->function()->isConstructor());
3229     }
3230 
symboldatabase51()3231     void symboldatabase51() { // #6538
3232         GET_SYMBOL_DB("static const float f1 = 2 * foo1(a, b);\n"
3233                       "static const float f2 = 2 * ::foo2(a, b);\n"
3234                       "static const float f3 = 2 * std::foo3(a, b);\n"
3235                       "static const float f4 = c * foo4(a, b);\n"
3236                       "static const int i1 = 2 & foo5(a, b);\n"
3237                       "static const bool b1 = 2 > foo6(a, b);");
3238         ASSERT(db != nullptr);
3239         ASSERT(findFunctionByName("foo1", &db->scopeList.front()) == nullptr);
3240         ASSERT(findFunctionByName("foo2", &db->scopeList.front()) == nullptr);
3241         ASSERT(findFunctionByName("foo3", &db->scopeList.front()) == nullptr);
3242         ASSERT(findFunctionByName("foo4", &db->scopeList.front()) == nullptr);
3243         ASSERT(findFunctionByName("foo5", &db->scopeList.front()) == nullptr);
3244         ASSERT(findFunctionByName("foo6", &db->scopeList.front()) == nullptr);
3245     }
3246 
symboldatabase52()3247     void symboldatabase52() { // #6581
3248         GET_SYMBOL_DB("void foo() {\n"
3249                       "    int i = 0;\n"
3250                       "    S s{ { i }, 0 };\n"
3251                       "}");
3252 
3253         ASSERT(db != nullptr);
3254         ASSERT_EQUALS(2, db->scopeList.size());
3255         ASSERT_EQUALS(2, db->variableList().size()-1);
3256         ASSERT(db->getVariableFromVarId(1) != nullptr);
3257         ASSERT(db->getVariableFromVarId(2) != nullptr);
3258     }
3259 
symboldatabase53()3260     void symboldatabase53() { // #7124
3261         GET_SYMBOL_DB("int32_t x;"
3262                       "std::int32_t y;");
3263 
3264         ASSERT(db != nullptr);
3265         ASSERT(db->getVariableFromVarId(1) != nullptr);
3266         ASSERT(db->getVariableFromVarId(2) != nullptr);
3267         ASSERT_EQUALS(false, db->getVariableFromVarId(1)->isClass());
3268         ASSERT_EQUALS(false, db->getVariableFromVarId(2)->isClass());
3269     }
3270 
symboldatabase54()3271     void symboldatabase54() { // #7343
3272         GET_SYMBOL_DB("class A {\n"
3273                       "  void getReg() const override {\n"
3274                       "    assert(Kind == k_ShiftExtend);\n"
3275                       "  }\n"
3276                       "};");
3277 
3278         ASSERT(db != nullptr);
3279         ASSERT_EQUALS(1U, db->functionScopes.size());
3280         ASSERT_EQUALS("getReg", db->functionScopes.front()->className);
3281         ASSERT_EQUALS(true, db->functionScopes.front()->function->hasOverrideSpecifier());
3282     }
3283 
symboldatabase55()3284     void symboldatabase55() { // #7767
3285         GET_SYMBOL_DB("PRIVATE S32 testfunc(void) {\n"
3286                       "    return 0;\n"
3287                       "}");
3288 
3289         ASSERT(db != nullptr);
3290         ASSERT_EQUALS(1U, db->functionScopes.size());
3291         ASSERT_EQUALS("testfunc", db->functionScopes.front()->className);
3292     }
3293 
symboldatabase56()3294     void symboldatabase56() { // #7909
3295         {
3296             GET_SYMBOL_DB("class Class {\n"
3297                           "    class NestedClass {\n"
3298                           "    public:\n"
3299                           "        virtual void f();\n"
3300                           "    };\n"
3301                           "    friend void NestedClass::f();\n"
3302                           "}");
3303 
3304             ASSERT(db != nullptr);
3305             ASSERT_EQUALS(0U, db->functionScopes.size());
3306             ASSERT(db->scopeList.back().type == Scope::eClass && db->scopeList.back().className == "NestedClass");
3307             ASSERT(db->scopeList.back().functionList.size() == 1U && !db->scopeList.back().functionList.front().hasBody());
3308         }
3309         {
3310             GET_SYMBOL_DB("class Class {\n"
3311                           "    friend void f1();\n"
3312                           "    friend void f2() { }\n"
3313                           "}");
3314 
3315             ASSERT(db != nullptr);
3316             ASSERT_EQUALS(1U, db->functionScopes.size());
3317             ASSERT(db->scopeList.back().type == Scope::eFunction && db->scopeList.back().className == "f2");
3318             ASSERT(db->scopeList.back().function && db->scopeList.back().function->hasBody());
3319         }
3320         {
3321             GET_SYMBOL_DB_C("friend f1();\n"
3322                             "friend f2() { }");
3323 
3324             ASSERT(db != nullptr);
3325             ASSERT_EQUALS(2U, db->scopeList.size());
3326             ASSERT_EQUALS(2U, db->scopeList.begin()->functionList.size());
3327         }
3328     }
3329 
symboldatabase57()3330     void symboldatabase57() {
3331         GET_SYMBOL_DB("int bar(bool b)\n"
3332                       "{\n"
3333                       "    if(b)\n"
3334                       "         return 1;\n"
3335                       "    else\n"
3336                       "         return 1;\n"
3337                       "}");
3338         ASSERT(db != nullptr);
3339         ASSERT(db->scopeList.size() == 4U);
3340         std::list<Scope>::const_iterator it = db->scopeList.begin();
3341         ASSERT(it->type == Scope::eGlobal);
3342         ASSERT((++it)->type == Scope::eFunction);
3343         ASSERT((++it)->type == Scope::eIf);
3344         ASSERT((++it)->type == Scope::eElse);
3345     }
3346 
symboldatabase58()3347     void symboldatabase58() { // #6985 (using namespace type lookup)
3348         GET_SYMBOL_DB("namespace N2\n"
3349                       "{\n"
3350                       "class B { };\n"
3351                       "}\n"
3352                       "using namespace N2;\n"
3353                       "class C {\n"
3354                       "    class A : public B\n"
3355                       "    {\n"
3356                       "    };\n"
3357                       "};");
3358         ASSERT(db != nullptr);
3359         ASSERT(db->typeList.size() == 3U);
3360         std::list<Type>::const_iterator it = db->typeList.begin();
3361         const Type * classB = &(*it);
3362         const Type * classC = &(*(++it));
3363         const Type * classA = &(*(++it));
3364         ASSERT(classA->name() == "A" && classB->name() == "B" && classC->name() == "C");
3365         ASSERT(classA->derivedFrom.size() == 1U);
3366         ASSERT(classA->derivedFrom[0].type != nullptr);
3367         ASSERT(classA->derivedFrom[0].type == classB);
3368     }
3369 
symboldatabase59()3370     void symboldatabase59() { // #8465
3371         GET_SYMBOL_DB("struct A::B ab[10];\n"
3372                       "void f() {}");
3373         ASSERT(db != nullptr);
3374         ASSERT(db && db->scopeList.size() == 2);
3375     }
3376 
symboldatabase60()3377     void symboldatabase60() { // #8470
3378         GET_SYMBOL_DB("struct A::someType A::bar() { return 0; }");
3379         ASSERT(db != nullptr);
3380         ASSERT(db && db->scopeList.size() == 2);
3381     }
3382 
symboldatabase61()3383     void symboldatabase61() {
3384         GET_SYMBOL_DB("struct Fred {\n"
3385                       "    struct Info { };\n"
3386                       "};\n"
3387                       "void foo() {\n"
3388                       "    struct Fred::Info* info;\n"
3389                       "    info = new (nothrow) struct Fred::Info();\n"
3390                       "    info = new struct Fred::Info();\n"
3391                       "    memset(info, 0, sizeof(struct Fred::Info));\n"
3392                       "}");
3393 
3394         ASSERT(db != nullptr);
3395         ASSERT(db && db->scopeList.size() == 4);
3396     }
3397 
symboldatabase62()3398     void symboldatabase62() {
3399         {
3400             GET_SYMBOL_DB("struct A {\n"
3401                           "public:\n"
3402                           "    struct X { int a; };\n"
3403                           "    void Foo(const std::vector<struct X> &includes);\n"
3404                           "};\n"
3405                           "void A::Foo(const std::vector<struct A::X> &includes) {\n"
3406                           "    for (std::vector<struct A::X>::const_iterator it = includes.begin(); it != includes.end(); ++it) {\n"
3407                           "        const struct A::X currentIncList = *it;\n"
3408                           "    }\n"
3409                           "}");
3410             ASSERT(db != nullptr);
3411             ASSERT(db && db->scopeList.size() == 5);
3412             const Scope *scope = db->findScopeByName("A");
3413             ASSERT(scope != nullptr);
3414             const Function *function = findFunctionByName("Foo", scope);
3415             ASSERT(function != nullptr);
3416             ASSERT(function->hasBody());
3417         }
3418         {
3419             GET_SYMBOL_DB("class A {\n"
3420                           "public:\n"
3421                           "    class X { public: int a; };\n"
3422                           "    void Foo(const std::vector<class X> &includes);\n"
3423                           "};\n"
3424                           "void A::Foo(const std::vector<class A::X> &includes) {\n"
3425                           "    for (std::vector<class A::X>::const_iterator it = includes.begin(); it != includes.end(); ++it) {\n"
3426                           "        const class A::X currentIncList = *it;\n"
3427                           "    }\n"
3428                           "}");
3429             ASSERT(db != nullptr);
3430             ASSERT(db && db->scopeList.size() == 5);
3431             const Scope *scope = db->findScopeByName("A");
3432             ASSERT(scope != nullptr);
3433             const Function *function = findFunctionByName("Foo", scope);
3434             ASSERT(function != nullptr);
3435             ASSERT(function->hasBody());
3436         }
3437         {
3438             GET_SYMBOL_DB("struct A {\n"
3439                           "public:\n"
3440                           "    union X { int a; float b; };\n"
3441                           "    void Foo(const std::vector<union X> &includes);\n"
3442                           "};\n"
3443                           "void A::Foo(const std::vector<union A::X> &includes) {\n"
3444                           "    for (std::vector<union A::X>::const_iterator it = includes.begin(); it != includes.end(); ++it) {\n"
3445                           "        const union A::X currentIncList = *it;\n"
3446                           "    }\n"
3447                           "}");
3448             ASSERT(db != nullptr);
3449             ASSERT(db && db->scopeList.size() == 5);
3450             const Scope *scope = db->findScopeByName("A");
3451             ASSERT(scope != nullptr);
3452             const Function *function = findFunctionByName("Foo", scope);
3453             ASSERT(function != nullptr);
3454             ASSERT(function->hasBody());
3455         }
3456         {
3457             GET_SYMBOL_DB("struct A {\n"
3458                           "public:\n"
3459                           "    enum X { a, b };\n"
3460                           "    void Foo(const std::vector<enum X> &includes);\n"
3461                           "};\n"
3462                           "void A::Foo(const std::vector<enum A::X> &includes) {\n"
3463                           "    for (std::vector<enum A::X>::const_iterator it = includes.begin(); it != includes.end(); ++it) {\n"
3464                           "        const enum A::X currentIncList = *it;\n"
3465                           "    }\n"
3466                           "}");
3467             ASSERT(db != nullptr);
3468             ASSERT(db && db->scopeList.size() == 5);
3469             const Scope *scope = db->findScopeByName("A");
3470             ASSERT(scope != nullptr);
3471             const Function *function = findFunctionByName("Foo", scope);
3472             ASSERT(function != nullptr);
3473             ASSERT(function->hasBody());
3474         }
3475     }
3476 
symboldatabase63()3477     void symboldatabase63() {
3478         {
3479             GET_SYMBOL_DB("template class T<int> ; void foo() { }");
3480             ASSERT(db != nullptr);
3481             ASSERT(db && db->scopeList.size() == 2);
3482         }
3483         {
3484             GET_SYMBOL_DB("template struct T<int> ; void foo() { }");
3485             ASSERT(db != nullptr);
3486             ASSERT(db && db->scopeList.size() == 2);
3487         }
3488     }
3489 
symboldatabase64()3490     void symboldatabase64() {
3491         {
3492             GET_SYMBOL_DB("class Fred { struct impl; };\n"
3493                           "struct Fred::impl {\n"
3494                           "    impl() { }\n"
3495                           "    ~impl() { }\n"
3496                           "    impl(const impl &) { }\n"
3497                           "    void foo(const impl &, const impl &) const { }\n"
3498                           "};");
3499 
3500             ASSERT(db != nullptr);
3501             ASSERT(db && db->scopeList.size() == 7);
3502             ASSERT(db && db->classAndStructScopes.size() == 2);
3503             ASSERT(db && db->typeList.size() == 2);
3504             ASSERT(db && db->functionScopes.size() == 4);
3505 
3506             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3507             ASSERT(db && functionToken && functionToken->function() &&
3508                    functionToken->function()->functionScope &&
3509                    functionToken->function()->tokenDef->linenr() == 3 &&
3510                    functionToken->function()->token->linenr() == 3);
3511 
3512             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3513             ASSERT(db && functionToken && functionToken->next()->function() &&
3514                    functionToken->next()->function()->functionScope &&
3515                    functionToken->next()->function()->tokenDef->linenr() == 4 &&
3516                    functionToken->next()->function()->token->linenr() == 4);
3517 
3518             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
3519             ASSERT(db && functionToken && functionToken->function() &&
3520                    functionToken->function()->functionScope &&
3521                    functionToken->function()->tokenDef->linenr() == 5 &&
3522                    functionToken->function()->token->linenr() == 5);
3523 
3524             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
3525             ASSERT(db && functionToken && functionToken->function() &&
3526                    functionToken->function()->functionScope &&
3527                    functionToken->function()->tokenDef->linenr() == 6 &&
3528                    functionToken->function()->token->linenr() == 6);
3529         }
3530         {
3531             GET_SYMBOL_DB("class Fred { struct impl; };\n"
3532                           "struct Fred::impl {\n"
3533                           "    impl();\n"
3534                           "    ~impl();\n"
3535                           "    impl(const impl &);\n"
3536                           "    void foo(const impl &, const impl &) const;\n"
3537                           "};\n"
3538                           "Fred::impl::impl() { }\n"
3539                           "Fred::impl::~impl() { }\n"
3540                           "Fred::impl::impl(const Fred::impl &) { }\n"
3541                           "void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }");
3542 
3543             ASSERT(db != nullptr);
3544             ASSERT(db && db->scopeList.size() == 7);
3545             ASSERT(db && db->classAndStructScopes.size() == 2);
3546             ASSERT(db && db->typeList.size() == 2);
3547             ASSERT(db && db->functionScopes.size() == 4);
3548 
3549             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3550             ASSERT(db && functionToken && functionToken->function() &&
3551                    functionToken->function()->functionScope &&
3552                    functionToken->function()->tokenDef->linenr() == 3 &&
3553                    functionToken->function()->token->linenr() == 8);
3554 
3555             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3556             ASSERT(db && functionToken && functionToken->next()->function() &&
3557                    functionToken->next()->function()->functionScope &&
3558                    functionToken->next()->function()->tokenDef->linenr() == 4 &&
3559                    functionToken->next()->function()->token->linenr() == 9);
3560 
3561             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
3562             ASSERT(db && functionToken && functionToken->function() &&
3563                    functionToken->function()->functionScope &&
3564                    functionToken->function()->tokenDef->linenr() == 5 &&
3565                    functionToken->function()->token->linenr() == 10);
3566 
3567             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
3568             ASSERT(db && functionToken && functionToken->function() &&
3569                    functionToken->function()->functionScope &&
3570                    functionToken->function()->tokenDef->linenr() == 6 &&
3571                    functionToken->function()->token->linenr() == 11);
3572         }
3573         {
3574             GET_SYMBOL_DB("namespace NS {\n"
3575                           "    class Fred { struct impl; };\n"
3576                           "    struct Fred::impl {\n"
3577                           "        impl() { }\n"
3578                           "        ~impl() { }\n"
3579                           "        impl(const impl &) { }\n"
3580                           "        void foo(const impl &, const impl &) const { }\n"
3581                           "    };\n"
3582                           "}");
3583 
3584             ASSERT(db != nullptr);
3585             ASSERT(db && db->scopeList.size() == 8);
3586             ASSERT(db && db->classAndStructScopes.size() == 2);
3587             ASSERT(db && db->typeList.size() == 2);
3588             ASSERT(db && db->functionScopes.size() == 4);
3589 
3590             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3591             ASSERT(db && functionToken && functionToken->function() &&
3592                    functionToken->function()->functionScope &&
3593                    functionToken->function()->tokenDef->linenr() == 4 &&
3594                    functionToken->function()->token->linenr() == 4);
3595 
3596             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3597             ASSERT(db && functionToken && functionToken->next()->function() &&
3598                    functionToken->next()->function()->functionScope &&
3599                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
3600                    functionToken->next()->function()->token->linenr() == 5);
3601 
3602             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
3603             ASSERT(db && functionToken && functionToken->function() &&
3604                    functionToken->function()->functionScope &&
3605                    functionToken->function()->tokenDef->linenr() == 6 &&
3606                    functionToken->function()->token->linenr() == 6);
3607 
3608             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
3609             ASSERT(db && functionToken && functionToken->function() &&
3610                    functionToken->function()->functionScope &&
3611                    functionToken->function()->tokenDef->linenr() == 7 &&
3612                    functionToken->function()->token->linenr() == 7);
3613         }
3614         {
3615             GET_SYMBOL_DB("namespace NS {\n"
3616                           "    class Fred { struct impl; };\n"
3617                           "    struct Fred::impl {\n"
3618                           "        impl();\n"
3619                           "        ~impl();\n"
3620                           "        impl(const impl &);\n"
3621                           "        void foo(const impl &, const impl &) const;\n"
3622                           "    };\n"
3623                           "    Fred::impl::impl() { }\n"
3624                           "    Fred::impl::~impl() { }\n"
3625                           "    Fred::impl::impl(const Fred::impl &) { }\n"
3626                           "    void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }\n"
3627                           "}");
3628 
3629             ASSERT(db != nullptr);
3630             ASSERT(db && db->scopeList.size() == 8);
3631             ASSERT(db && db->classAndStructScopes.size() == 2);
3632             ASSERT(db && db->typeList.size() == 2);
3633             ASSERT(db && db->functionScopes.size() == 4);
3634 
3635             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3636             ASSERT(db && functionToken && functionToken->function() &&
3637                    functionToken->function()->functionScope &&
3638                    functionToken->function()->tokenDef->linenr() == 4 &&
3639                    functionToken->function()->token->linenr() == 9);
3640 
3641             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3642             ASSERT(db && functionToken && functionToken->next()->function() &&
3643                    functionToken->next()->function()->functionScope &&
3644                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
3645                    functionToken->next()->function()->token->linenr() == 10);
3646 
3647             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
3648             ASSERT(db && functionToken && functionToken->function() &&
3649                    functionToken->function()->functionScope &&
3650                    functionToken->function()->tokenDef->linenr() == 6 &&
3651                    functionToken->function()->token->linenr() == 11);
3652 
3653             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
3654             ASSERT(db && functionToken && functionToken->function() &&
3655                    functionToken->function()->functionScope &&
3656                    functionToken->function()->tokenDef->linenr() == 7 &&
3657                    functionToken->function()->token->linenr() == 12);
3658         }
3659         {
3660             GET_SYMBOL_DB("namespace NS {\n"
3661                           "    class Fred { struct impl; };\n"
3662                           "    struct Fred::impl {\n"
3663                           "        impl();\n"
3664                           "        ~impl();\n"
3665                           "        impl(const impl &);\n"
3666                           "        void foo(const impl &, const impl &) const;\n"
3667                           "    };\n"
3668                           "}\n"
3669                           "NS::Fred::impl::impl() { }\n"
3670                           "NS::Fred::impl::~impl() { }\n"
3671                           "NS::Fred::impl::impl(const NS::Fred::impl &) { }\n"
3672                           "void NS::Fred::impl::foo(const NS::Fred::impl &, const NS::Fred::impl &) const { }");
3673 
3674             ASSERT(db != nullptr);
3675             ASSERT(db && db->scopeList.size() == 8);
3676             ASSERT(db && db->classAndStructScopes.size() == 2);
3677             ASSERT(db && db->typeList.size() == 2);
3678             ASSERT(db && db->functionScopes.size() == 4);
3679 
3680             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3681             ASSERT(db && functionToken && functionToken->function() &&
3682                    functionToken->function()->functionScope &&
3683                    functionToken->function()->tokenDef->linenr() == 4 &&
3684                    functionToken->function()->token->linenr() == 10);
3685 
3686             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3687             ASSERT(db && functionToken && functionToken->next()->function() &&
3688                    functionToken->next()->function()->functionScope &&
3689                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
3690                    functionToken->next()->function()->token->linenr() == 11);
3691 
3692             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
3693             ASSERT(db && functionToken && functionToken->function() &&
3694                    functionToken->function()->functionScope &&
3695                    functionToken->function()->tokenDef->linenr() == 6 &&
3696                    functionToken->function()->token->linenr() == 12);
3697 
3698             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred :: impl & , const NS :: Fred :: impl & ) const { }");
3699             ASSERT(db && functionToken && functionToken->function() &&
3700                    functionToken->function()->functionScope &&
3701                    functionToken->function()->tokenDef->linenr() == 7 &&
3702                    functionToken->function()->token->linenr() == 13);
3703         }
3704         {
3705             GET_SYMBOL_DB("namespace NS {\n"
3706                           "    class Fred { struct impl; };\n"
3707                           "}\n"
3708                           "struct NS::Fred::impl {\n"
3709                           "    impl() { }\n"
3710                           "    ~impl() { }\n"
3711                           "    impl(const impl &) { }\n"
3712                           "    void foo(const impl &, const impl &) const { }\n"
3713                           "};");
3714 
3715             ASSERT(db != nullptr);
3716             ASSERT(db && db->scopeList.size() == 8);
3717             ASSERT(db && db->classAndStructScopes.size() == 2);
3718             ASSERT(db && db->typeList.size() == 2);
3719             ASSERT(db && db->functionScopes.size() == 4);
3720 
3721             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3722             ASSERT(db && functionToken && functionToken->function() &&
3723                    functionToken->function()->functionScope &&
3724                    functionToken->function()->tokenDef->linenr() == 5 &&
3725                    functionToken->function()->token->linenr() == 5);
3726 
3727             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3728             ASSERT(db && functionToken && functionToken->next()->function() &&
3729                    functionToken->next()->function()->functionScope &&
3730                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
3731                    functionToken->next()->function()->token->linenr() == 6);
3732 
3733             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
3734             ASSERT(db && functionToken && functionToken->function() &&
3735                    functionToken->function()->functionScope &&
3736                    functionToken->function()->tokenDef->linenr() == 7 &&
3737                    functionToken->function()->token->linenr() == 7);
3738 
3739             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
3740             ASSERT(db && functionToken && functionToken->function() &&
3741                    functionToken->function()->functionScope &&
3742                    functionToken->function()->tokenDef->linenr() == 8 &&
3743                    functionToken->function()->token->linenr() == 8);
3744         }
3745         {
3746             GET_SYMBOL_DB("namespace NS {\n"
3747                           "    class Fred { struct impl; };\n"
3748                           "}\n"
3749                           "struct NS::Fred::impl {\n"
3750                           "    impl();\n"
3751                           "    ~impl();\n"
3752                           "    impl(const impl &);\n"
3753                           "    void foo(const impl &, const impl &) const;\n"
3754                           "};\n"
3755                           "NS::Fred::impl::impl() { }\n"
3756                           "NS::Fred::impl::~impl() { }\n"
3757                           "NS::Fred::impl::impl(const NS::Fred::impl &) { }\n"
3758                           "void NS::Fred::impl::foo(const NS::Fred::impl &, const NS::Fred::impl &) const { }");
3759 
3760             ASSERT(db != nullptr);
3761             ASSERT(db && db->scopeList.size() == 8);
3762             ASSERT(db && db->classAndStructScopes.size() == 2);
3763             ASSERT(db && db->typeList.size() == 2);
3764             ASSERT(db && db->functionScopes.size() == 4);
3765 
3766             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3767             ASSERT(db && functionToken && functionToken->function() &&
3768                    functionToken->function()->functionScope &&
3769                    functionToken->function()->tokenDef->linenr() == 5 &&
3770                    functionToken->function()->token->linenr() == 10);
3771 
3772             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3773             ASSERT(db && functionToken && functionToken->next()->function() &&
3774                    functionToken->next()->function()->functionScope &&
3775                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
3776                    functionToken->next()->function()->token->linenr() == 11);
3777 
3778             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
3779             ASSERT(db && functionToken && functionToken->function() &&
3780                    functionToken->function()->functionScope &&
3781                    functionToken->function()->tokenDef->linenr() == 7 &&
3782                    functionToken->function()->token->linenr() == 12);
3783 
3784             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred :: impl & , const NS :: Fred :: impl & ) const { }");
3785             ASSERT(db && functionToken && functionToken->function() &&
3786                    functionToken->function()->functionScope &&
3787                    functionToken->function()->tokenDef->linenr() == 8 &&
3788                    functionToken->function()->token->linenr() == 13);
3789         }
3790         {
3791             GET_SYMBOL_DB("namespace NS {\n"
3792                           "    class Fred { struct impl; };\n"
3793                           "}\n"
3794                           "struct NS::Fred::impl {\n"
3795                           "    impl();\n"
3796                           "    ~impl();\n"
3797                           "    impl(const impl &);\n"
3798                           "    void foo(const impl &, const impl &) const;\n"
3799                           "};\n"
3800                           "namespace NS {\n"
3801                           "    Fred::impl::impl() { }\n"
3802                           "    Fred::impl::~impl() { }\n"
3803                           "    Fred::impl::impl(const Fred::impl &) { }\n"
3804                           "    void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }\n"
3805                           "}");
3806 
3807             ASSERT(db != nullptr);
3808             ASSERT(db && db->scopeList.size() == 8);
3809             ASSERT(db && db->classAndStructScopes.size() == 2);
3810             ASSERT(db && db->typeList.size() == 2);
3811             ASSERT(db && db->functionScopes.size() == 4);
3812 
3813             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3814             ASSERT(db && functionToken && functionToken->function() &&
3815                    functionToken->function()->functionScope &&
3816                    functionToken->function()->tokenDef->linenr() == 5 &&
3817                    functionToken->function()->token->linenr() == 11);
3818 
3819             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3820             ASSERT(db && functionToken && functionToken->next()->function() &&
3821                    functionToken->next()->function()->functionScope &&
3822                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
3823                    functionToken->next()->function()->token->linenr() == 12);
3824 
3825             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
3826             ASSERT(db && functionToken && functionToken->function() &&
3827                    functionToken->function()->functionScope &&
3828                    functionToken->function()->tokenDef->linenr() == 7 &&
3829                    functionToken->function()->token->linenr() == 13);
3830 
3831             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
3832             ASSERT(db && functionToken && functionToken->function() &&
3833                    functionToken->function()->functionScope &&
3834                    functionToken->function()->tokenDef->linenr() == 8 &&
3835                    functionToken->function()->token->linenr() == 14);
3836         }
3837         {
3838             GET_SYMBOL_DB("namespace NS {\n"
3839                           "    class Fred { struct impl; };\n"
3840                           "}\n"
3841                           "struct NS::Fred::impl {\n"
3842                           "    impl();\n"
3843                           "    ~impl();\n"
3844                           "    impl(const impl &);\n"
3845                           "    void foo(const impl &, const impl &) const;\n"
3846                           "};\n"
3847                           "using namespace NS;\n"
3848                           "Fred::impl::impl() { }\n"
3849                           "Fred::impl::~impl() { }\n"
3850                           "Fred::impl::impl(const Fred::impl &) { }\n"
3851                           "void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }");
3852 
3853             ASSERT(db != nullptr);
3854             ASSERT(db && db->scopeList.size() == 8);
3855             ASSERT(db && db->classAndStructScopes.size() == 2);
3856             ASSERT(db && db->typeList.size() == 2);
3857             ASSERT(db && db->functionScopes.size() == 4);
3858 
3859             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3860             ASSERT(db && functionToken && functionToken->function() &&
3861                    functionToken->function()->functionScope &&
3862                    functionToken->function()->tokenDef->linenr() == 5 &&
3863                    functionToken->function()->token->linenr() == 11);
3864 
3865             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3866             ASSERT(db && functionToken && functionToken->next()->function() &&
3867                    functionToken->next()->function()->functionScope &&
3868                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
3869                    functionToken->next()->function()->token->linenr() == 12);
3870 
3871             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
3872             ASSERT(db && functionToken && functionToken->function() &&
3873                    functionToken->function()->functionScope &&
3874                    functionToken->function()->tokenDef->linenr() == 7 &&
3875                    functionToken->function()->token->linenr() == 13);
3876 
3877             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
3878             ASSERT(db && functionToken && functionToken->function() &&
3879                    functionToken->function()->functionScope &&
3880                    functionToken->function()->tokenDef->linenr() == 8 &&
3881                    functionToken->function()->token->linenr() == 14);
3882         }
3883         {
3884             GET_SYMBOL_DB("template <typename A> class Fred { struct impl; };\n"
3885                           "template <typename A> struct Fred<A>::impl {\n"
3886                           "    impl() { }\n"
3887                           "    ~impl() { }\n"
3888                           "    impl(const impl &) { }\n"
3889                           "    void foo(const impl &, const impl &) const { }\n"
3890                           "};");
3891 
3892             ASSERT(db != nullptr);
3893             ASSERT(db && db->scopeList.size() == 7);
3894             ASSERT(db && db->classAndStructScopes.size() == 2);
3895             ASSERT(db && db->typeList.size() == 2);
3896             ASSERT(db && db->functionScopes.size() == 4);
3897 
3898             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3899             ASSERT(db && functionToken && functionToken->function() &&
3900                    functionToken->function()->functionScope &&
3901                    functionToken->function()->tokenDef->linenr() == 3 &&
3902                    functionToken->function()->token->linenr() == 3);
3903 
3904             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3905             ASSERT(db && functionToken && functionToken->next()->function() &&
3906                    functionToken->next()->function()->functionScope &&
3907                    functionToken->next()->function()->tokenDef->linenr() == 4 &&
3908                    functionToken->next()->function()->token->linenr() == 4);
3909 
3910             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
3911             ASSERT(db && functionToken && functionToken->function() &&
3912                    functionToken->function()->functionScope &&
3913                    functionToken->function()->tokenDef->linenr() == 5 &&
3914                    functionToken->function()->token->linenr() == 5);
3915 
3916             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
3917             ASSERT(db && functionToken && functionToken->function() &&
3918                    functionToken->function()->functionScope &&
3919                    functionToken->function()->tokenDef->linenr() == 6 &&
3920                    functionToken->function()->token->linenr() == 6);
3921         }
3922         {
3923             GET_SYMBOL_DB("template <typename A> class Fred { struct impl; };\n"
3924                           "template <typename A> struct Fred<A>::impl {\n"
3925                           "    impl();\n"
3926                           "    ~impl();\n"
3927                           "    impl(const impl &);\n"
3928                           "    void foo(const impl &, const impl &) const;\n"
3929                           "};\n"
3930                           "template <typename A> Fred<A>::impl::impl() { }\n"
3931                           "template <typename A> Fred<A>::impl::~impl() { }\n"
3932                           "template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
3933                           "template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }");
3934 
3935             ASSERT(db != nullptr);
3936             ASSERT(db && db->scopeList.size() == 7);
3937             ASSERT(db && db->classAndStructScopes.size() == 2);
3938             ASSERT(db && db->typeList.size() == 2);
3939             ASSERT(db && db->functionScopes.size() == 4);
3940 
3941             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3942             ASSERT(db && functionToken && functionToken->function() &&
3943                    functionToken->function()->functionScope &&
3944                    functionToken->function()->tokenDef->linenr() == 3 &&
3945                    functionToken->function()->token->linenr() == 8);
3946 
3947             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3948             ASSERT(db && functionToken && functionToken->next()->function() &&
3949                    functionToken->next()->function()->functionScope &&
3950                    functionToken->next()->function()->tokenDef->linenr() == 4 &&
3951                    functionToken->next()->function()->token->linenr() == 9);
3952 
3953             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
3954             ASSERT(db && functionToken && functionToken->function() &&
3955                    functionToken->function()->functionScope &&
3956                    functionToken->function()->tokenDef->linenr() == 5 &&
3957                    functionToken->function()->token->linenr() == 10);
3958 
3959             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
3960             ASSERT(db && functionToken && functionToken->function() &&
3961                    functionToken->function()->functionScope &&
3962                    functionToken->function()->tokenDef->linenr() == 6 &&
3963                    functionToken->function()->token->linenr() == 11);
3964         }
3965         {
3966             GET_SYMBOL_DB("namespace NS {\n"
3967                           "    template <typename A> class Fred { struct impl; };\n"
3968                           "    template <typename A> struct Fred<A>::impl {\n"
3969                           "        impl() { }\n"
3970                           "        ~impl() { }\n"
3971                           "        impl(const impl &) { }\n"
3972                           "        void foo(const impl &, const impl &) const { }\n"
3973                           "    };\n"
3974                           "}");
3975 
3976             ASSERT(db != nullptr);
3977             ASSERT(db && db->scopeList.size() == 8);
3978             ASSERT(db && db->classAndStructScopes.size() == 2);
3979             ASSERT(db && db->typeList.size() == 2);
3980             ASSERT(db && db->functionScopes.size() == 4);
3981 
3982             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
3983             ASSERT(db && functionToken && functionToken->function() &&
3984                    functionToken->function()->functionScope &&
3985                    functionToken->function()->tokenDef->linenr() == 4 &&
3986                    functionToken->function()->token->linenr() == 4);
3987 
3988             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
3989             ASSERT(db && functionToken && functionToken->next()->function() &&
3990                    functionToken->next()->function()->functionScope &&
3991                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
3992                    functionToken->next()->function()->token->linenr() == 5);
3993 
3994             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
3995             ASSERT(db && functionToken && functionToken->function() &&
3996                    functionToken->function()->functionScope &&
3997                    functionToken->function()->tokenDef->linenr() == 6 &&
3998                    functionToken->function()->token->linenr() == 6);
3999 
4000             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
4001             ASSERT(db && functionToken && functionToken->function() &&
4002                    functionToken->function()->functionScope &&
4003                    functionToken->function()->tokenDef->linenr() == 7 &&
4004                    functionToken->function()->token->linenr() == 7);
4005         }
4006         {
4007             GET_SYMBOL_DB("namespace NS {\n"
4008                           "    template <typename A> class Fred { struct impl; };\n"
4009                           "    template <typename A> struct Fred<A>::impl {\n"
4010                           "        impl();\n"
4011                           "        ~impl();\n"
4012                           "        impl(const impl &);\n"
4013                           "        void foo(const impl &, const impl &) const;\n"
4014                           "    };\n"
4015                           "    template <typename A> Fred<A>::impl::impl() { }\n"
4016                           "    template <typename A> Fred<A>::impl::~impl() { }\n"
4017                           "    template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
4018                           "    template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n"
4019                           "}");
4020 
4021             ASSERT(db != nullptr);
4022             ASSERT(db && db->scopeList.size() == 8);
4023             ASSERT(db && db->classAndStructScopes.size() == 2);
4024             ASSERT(db && db->typeList.size() == 2);
4025             ASSERT(db && db->functionScopes.size() == 4);
4026 
4027             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4028             ASSERT(db && functionToken && functionToken->function() &&
4029                    functionToken->function()->functionScope &&
4030                    functionToken->function()->tokenDef->linenr() == 4 &&
4031                    functionToken->function()->token->linenr() == 9);
4032 
4033             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4034             ASSERT(db && functionToken && functionToken->next()->function() &&
4035                    functionToken->next()->function()->functionScope &&
4036                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
4037                    functionToken->next()->function()->token->linenr() == 10);
4038 
4039             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
4040             ASSERT(db && functionToken && functionToken->function() &&
4041                    functionToken->function()->functionScope &&
4042                    functionToken->function()->tokenDef->linenr() == 6 &&
4043                    functionToken->function()->token->linenr() == 11);
4044 
4045             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
4046             ASSERT(db && functionToken && functionToken->function() &&
4047                    functionToken->function()->functionScope &&
4048                    functionToken->function()->tokenDef->linenr() == 7 &&
4049                    functionToken->function()->token->linenr() == 12);
4050         }
4051         {
4052             GET_SYMBOL_DB("namespace NS {\n"
4053                           "    template <typename A> class Fred { struct impl; };\n"
4054                           "    template <typename A> struct Fred<A>::impl {\n"
4055                           "        impl();\n"
4056                           "        ~impl();\n"
4057                           "        impl(const impl &);\n"
4058                           "        void foo(const impl &, const impl &) const;\n"
4059                           "    };\n"
4060                           "}\n"
4061                           "template <typename A> NS::Fred<A>::impl::impl() { }\n"
4062                           "template <typename A> NS::Fred<A>::impl::~impl() { }\n"
4063                           "template <typename A> NS::Fred<A>::impl::impl(const NS::Fred<A>::impl &) { }\n"
4064                           "template <typename A> void NS::Fred<A>::impl::foo(const NS::Fred<A>::impl &, const NS::Fred<A>::impl &) const { }");
4065 
4066             ASSERT(db != nullptr);
4067             ASSERT(db && db->scopeList.size() == 8);
4068             ASSERT(db && db->classAndStructScopes.size() == 2);
4069             ASSERT(db && db->typeList.size() == 2);
4070             ASSERT(db && db->functionScopes.size() == 4);
4071 
4072             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4073             ASSERT(db && functionToken && functionToken->function() &&
4074                    functionToken->function()->functionScope &&
4075                    functionToken->function()->tokenDef->linenr() == 4 &&
4076                    functionToken->function()->token->linenr() == 10);
4077 
4078             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4079             ASSERT(db && functionToken && functionToken->next()->function() &&
4080                    functionToken->next()->function()->functionScope &&
4081                    functionToken->next()->function()->tokenDef->linenr() == 5 &&
4082                    functionToken->next()->function()->token->linenr() == 11);
4083 
4084             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred < A > :: impl & ) { }");
4085             ASSERT(db && functionToken && functionToken->function() &&
4086                    functionToken->function()->functionScope &&
4087                    functionToken->function()->tokenDef->linenr() == 6 &&
4088                    functionToken->function()->token->linenr() == 12);
4089 
4090             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred < A > :: impl & , const NS :: Fred < A > :: impl & ) const { }");
4091             ASSERT(db && functionToken && functionToken->function() &&
4092                    functionToken->function()->functionScope &&
4093                    functionToken->function()->tokenDef->linenr() == 7 &&
4094                    functionToken->function()->token->linenr() == 13);
4095         }
4096         {
4097             GET_SYMBOL_DB("namespace NS {\n"
4098                           "    template <typename A> class Fred { struct impl; };\n"
4099                           "}\n"
4100                           "template <typename A> struct NS::Fred<A>::impl {\n"
4101                           "    impl() { }\n"
4102                           "    ~impl() { }\n"
4103                           "    impl(const impl &) { }\n"
4104                           "    void foo(const impl &, const impl &) const { }\n"
4105                           "};");
4106 
4107             ASSERT(db != nullptr);
4108             ASSERT(db && db->scopeList.size() == 8);
4109             ASSERT(db && db->classAndStructScopes.size() == 2);
4110             ASSERT(db && db->typeList.size() == 2);
4111             ASSERT(db && db->functionScopes.size() == 4);
4112 
4113             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4114             ASSERT(db && functionToken && functionToken->function() &&
4115                    functionToken->function()->functionScope &&
4116                    functionToken->function()->tokenDef->linenr() == 5 &&
4117                    functionToken->function()->token->linenr() == 5);
4118 
4119             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4120             ASSERT(db && functionToken && functionToken->next()->function() &&
4121                    functionToken->next()->function()->functionScope &&
4122                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
4123                    functionToken->next()->function()->token->linenr() == 6);
4124 
4125             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
4126             ASSERT(db && functionToken && functionToken->function() &&
4127                    functionToken->function()->functionScope &&
4128                    functionToken->function()->tokenDef->linenr() == 7 &&
4129                    functionToken->function()->token->linenr() == 7);
4130 
4131             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
4132             ASSERT(db && functionToken && functionToken->function() &&
4133                    functionToken->function()->functionScope &&
4134                    functionToken->function()->tokenDef->linenr() == 8 &&
4135                    functionToken->function()->token->linenr() == 8);
4136         }
4137         {
4138             GET_SYMBOL_DB("namespace NS {\n"
4139                           "    template <typename A> class Fred { struct impl; };\n"
4140                           "}\n"
4141                           "template <typename A> struct NS::Fred<A>::impl {\n"
4142                           "    impl();\n"
4143                           "    ~impl();\n"
4144                           "    impl(const impl &);\n"
4145                           "    void foo(const impl &, const impl &) const;\n"
4146                           "};\n"
4147                           "template <typename A> NS::Fred<A>::impl::impl() { }\n"
4148                           "template <typename A> NS::Fred<A>::impl::~impl() { }\n"
4149                           "template <typename A> NS::Fred<A>::impl::impl(const NS::Fred<A>::impl &) { }\n"
4150                           "template <typename A> void NS::Fred<A>::impl::foo(const NS::Fred<A>::impl &, const NS::Fred<A>::impl &) const { }");
4151 
4152             ASSERT(db != nullptr);
4153             ASSERT(db && db->scopeList.size() == 8);
4154             ASSERT(db && db->classAndStructScopes.size() == 2);
4155             ASSERT(db && db->typeList.size() == 2);
4156             ASSERT(db && db->functionScopes.size() == 4);
4157 
4158             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4159             ASSERT(db && functionToken && functionToken->function() &&
4160                    functionToken->function()->functionScope &&
4161                    functionToken->function()->tokenDef->linenr() == 5 &&
4162                    functionToken->function()->token->linenr() == 10);
4163 
4164             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4165             ASSERT(db && functionToken && functionToken->next()->function() &&
4166                    functionToken->next()->function()->functionScope &&
4167                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
4168                    functionToken->next()->function()->token->linenr() == 11);
4169 
4170             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred < A > :: impl & ) { }");
4171             ASSERT(db && functionToken && functionToken->function() &&
4172                    functionToken->function()->functionScope &&
4173                    functionToken->function()->tokenDef->linenr() == 7 &&
4174                    functionToken->function()->token->linenr() == 12);
4175 
4176             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred < A > :: impl & , const NS :: Fred < A > :: impl & ) const { }");
4177             ASSERT(db && functionToken && functionToken->function() &&
4178                    functionToken->function()->functionScope &&
4179                    functionToken->function()->tokenDef->linenr() == 8 &&
4180                    functionToken->function()->token->linenr() == 13);
4181         }
4182         {
4183             GET_SYMBOL_DB("namespace NS {\n"
4184                           "    template <typename A> class Fred { struct impl; };\n"
4185                           "}\n"
4186                           "template <typename A> struct NS::Fred<A>::impl {\n"
4187                           "    impl();\n"
4188                           "    ~impl();\n"
4189                           "    impl(const impl &);\n"
4190                           "    void foo(const impl &, const impl &) const;\n"
4191                           "};\n"
4192                           "namespace NS {\n"
4193                           "    template <typename A> Fred<A>::impl::impl() { }\n"
4194                           "    template <typename A> Fred<A>::impl::~impl() { }\n"
4195                           "    template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
4196                           "    template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n"
4197                           "}");
4198 
4199             ASSERT(db != nullptr);
4200             ASSERT(db && db->scopeList.size() == 8);
4201             ASSERT(db && db->classAndStructScopes.size() == 2);
4202             ASSERT(db && db->typeList.size() == 2);
4203             ASSERT(db && db->functionScopes.size() == 4);
4204 
4205             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4206             ASSERT(db && functionToken && functionToken->function() &&
4207                    functionToken->function()->functionScope &&
4208                    functionToken->function()->tokenDef->linenr() == 5 &&
4209                    functionToken->function()->token->linenr() == 11);
4210 
4211             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4212             ASSERT(db && functionToken && functionToken->next()->function() &&
4213                    functionToken->next()->function()->functionScope &&
4214                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
4215                    functionToken->next()->function()->token->linenr() == 12);
4216 
4217             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
4218             ASSERT(db && functionToken && functionToken->function() &&
4219                    functionToken->function()->functionScope &&
4220                    functionToken->function()->tokenDef->linenr() == 7 &&
4221                    functionToken->function()->token->linenr() == 13);
4222 
4223             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
4224             ASSERT(db && functionToken && functionToken->function() &&
4225                    functionToken->function()->functionScope &&
4226                    functionToken->function()->tokenDef->linenr() == 8 &&
4227                    functionToken->function()->token->linenr() == 14);
4228         }
4229         {
4230             GET_SYMBOL_DB("namespace NS {\n"
4231                           "    template <typename A> class Fred { struct impl; };\n"
4232                           "}\n"
4233                           "template <typename A> struct NS::Fred::impl {\n"
4234                           "    impl();\n"
4235                           "    ~impl();\n"
4236                           "    impl(const impl &);\n"
4237                           "    void foo(const impl &, const impl &) const;\n"
4238                           "};\n"
4239                           "using namespace NS;\n"
4240                           "template <typename A> Fred<A>::impl::impl() { }\n"
4241                           "template <typename A> Fred<A>::impl::~impl() { }\n"
4242                           "template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
4243                           "template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }");
4244 
4245             ASSERT(db != nullptr);
4246             ASSERT(db && db->scopeList.size() == 8);
4247             ASSERT(db && db->classAndStructScopes.size() == 2);
4248             ASSERT(db && db->typeList.size() == 2);
4249             ASSERT(db && db->functionScopes.size() == 4);
4250 
4251             const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
4252             ASSERT(db && functionToken && functionToken->function() &&
4253                    functionToken->function()->functionScope &&
4254                    functionToken->function()->tokenDef->linenr() == 5 &&
4255                    functionToken->function()->token->linenr() == 11);
4256 
4257             functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
4258             ASSERT(db && functionToken && functionToken->next()->function() &&
4259                    functionToken->next()->function()->functionScope &&
4260                    functionToken->next()->function()->tokenDef->linenr() == 6 &&
4261                    functionToken->next()->function()->token->linenr() == 12);
4262 
4263             functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
4264             ASSERT(db && functionToken && functionToken->function() &&
4265                    functionToken->function()->functionScope &&
4266                    functionToken->function()->tokenDef->linenr() == 7 &&
4267                    functionToken->function()->token->linenr() == 13);
4268 
4269             functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
4270             ASSERT(db && functionToken && functionToken->function() &&
4271                    functionToken->function()->functionScope &&
4272                    functionToken->function()->tokenDef->linenr() == 8 &&
4273                    functionToken->function()->token->linenr() == 14);
4274         }
4275     }
4276 
symboldatabase65()4277     void symboldatabase65() {
4278         // don't crash on missing links from instantiation of template with typedef
4279         check("int ( * X0 ) ( long ) < int ( ) ( long ) > :: f0 ( int * ) { return 0 ; }");
4280         ASSERT_EQUALS("[test.cpp:1]: (debug) SymbolDatabase::findFunction found '>' without link.\n", errout.str());
4281     }
4282 
symboldatabase66()4283     void symboldatabase66() { // #8540
4284         GET_SYMBOL_DB("enum class ENUM1;\n"
4285                       "enum class ENUM2 { MEMBER2 };\n"
4286                       "enum class ENUM3 : int { MEMBER1, };");
4287         ASSERT(db != nullptr);
4288         ASSERT(db && db->scopeList.size() == 3);
4289         ASSERT(db && db->typeList.size() == 3);
4290     }
4291 
symboldatabase67()4292     void symboldatabase67() { // #8538
4293         GET_SYMBOL_DB("std::string get_endpoint_url() const noexcept override;");
4294         const Function *f = db ? &db->scopeList.front().functionList.front() : nullptr;
4295         ASSERT(f != nullptr);
4296         ASSERT(f && f->hasOverrideSpecifier());
4297         ASSERT(f && f->isConst());
4298         ASSERT(f && f->isNoExcept());
4299     }
4300 
symboldatabase68()4301     void symboldatabase68() { // #8560
4302         GET_SYMBOL_DB("struct Bar {\n"
4303                       "    virtual std::string get_endpoint_url() const noexcept;\n"
4304                       "};\n"
4305                       "struct Foo : Bar {\n"
4306                       "    virtual std::string get_endpoint_url() const noexcept override final;\n"
4307                       "};");
4308         const Token *f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept ;") : nullptr;
4309         ASSERT(f != nullptr);
4310         ASSERT(f && f->function() && f->function()->token->linenr() == 2);
4311         ASSERT(f && f->function() && f->function()->hasVirtualSpecifier());
4312         ASSERT(f && f->function() && !f->function()->hasOverrideSpecifier());
4313         ASSERT(f && f->function() && !f->function()->hasFinalSpecifier());
4314         ASSERT(f && f->function() && f->function()->isConst());
4315         ASSERT(f && f->function() && f->function()->isNoExcept());
4316         f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept override final ;") : nullptr;
4317         ASSERT(f != nullptr);
4318         ASSERT(f && f->function() && f->function()->token->linenr() == 5);
4319         ASSERT(f && f->function() && f->function()->hasVirtualSpecifier());
4320         ASSERT(f && f->function() && f->function()->hasOverrideSpecifier());
4321         ASSERT(f && f->function() && f->function()->hasFinalSpecifier());
4322         ASSERT(f && f->function() && f->function()->isConst());
4323         ASSERT(f && f->function() && f->function()->isNoExcept());
4324     }
4325 
symboldatabase69()4326     void symboldatabase69() {
4327         GET_SYMBOL_DB("struct Fred {\n"
4328                       "    int x, y;\n"
4329                       "    void foo() const volatile { }\n"
4330                       "    void foo() volatile { }\n"
4331                       "    void foo() const { }\n"
4332                       "    void foo() { }\n"
4333                       "};");
4334         const Token *f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) const volatile {") : nullptr;
4335         ASSERT(f != nullptr);
4336         ASSERT(f && f->function() && f->function()->token->linenr() == 3);
4337         ASSERT(f && f->function() && f->function()->isConst());
4338         ASSERT(f && f->function() && f->function()->isVolatile());
4339         f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) volatile {") : nullptr;
4340         ASSERT(f != nullptr);
4341         ASSERT(f && f->function() && f->function()->token->linenr() == 4);
4342         ASSERT(f && f->function() && !f->function()->isConst());
4343         ASSERT(f && f->function() && f->function()->isVolatile());
4344         f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) const {") : nullptr;
4345         ASSERT(f != nullptr);
4346         ASSERT(f && f->function() && f->function()->token->linenr() == 5);
4347         ASSERT(f && f->function() && f->function()->isConst());
4348         ASSERT(f && f->function() && !f->function()->isVolatile());
4349         f = db ? Token::findsimplematch(tokenizer.tokens(), "foo ( ) {") : nullptr;
4350         ASSERT(f != nullptr);
4351         ASSERT(f && f->function() && f->function()->token->linenr() == 6);
4352         ASSERT(f && f->function() && !f->function()->isVolatile());
4353         ASSERT(f && f->function() && !f->function()->isConst());
4354     }
4355 
symboldatabase70()4356     void symboldatabase70() {
4357         {
4358             GET_SYMBOL_DB("class Map<String,Entry>::Entry* e;");
4359             ASSERT(db != nullptr);
4360             ASSERT(db && db->scopeList.size() == 1);
4361             ASSERT(db && db->variableList().size() == 2);
4362         }
4363         {
4364             GET_SYMBOL_DB("template class boost::token_iterator_generator<boost::offset_separator>::type; void foo() { }");
4365             ASSERT(db != nullptr);
4366             ASSERT(db && db->scopeList.size() == 2);
4367         }
4368         {
4369             GET_SYMBOL_DB("void foo() {\n"
4370                           "    return class Arm_relocate_functions<big_endian>::thumb32_branch_offset(upper_insn, lower_insn);\n"
4371                           "}");
4372             ASSERT(db != nullptr);
4373             ASSERT(db && db->scopeList.size() == 2);
4374         }
4375     }
4376 
symboldatabase71()4377     void symboldatabase71() {
4378         GET_SYMBOL_DB("class A { };\n"
4379                       "class B final : public A { };");
4380         ASSERT(db && db->scopeList.size() == 3);
4381         ASSERT(db && db->typeList.size() == 2);
4382     }
4383 
symboldatabase72()4384     void symboldatabase72() { // #8600
4385         GET_SYMBOL_DB("struct A { struct B; };\n"
4386                       "struct A::B {\n"
4387                       "    B() = default;\n"
4388                       "    B(const B&) {}\n"
4389                       "};");
4390 
4391         ASSERT(db && db->scopeList.size() == 4);
4392         ASSERT(db && db->typeList.size() == 2);
4393         const Token * f = db ? Token::findsimplematch(tokenizer.tokens(), "B ( const B & ) { }") : nullptr;
4394         ASSERT(f != nullptr);
4395         ASSERT(f && f->function() && f->function()->token->linenr() == 4);
4396         ASSERT(f && f->function() && f->function()->type == Function::eCopyConstructor);
4397     }
4398 
symboldatabase74()4399     void symboldatabase74() { // #8838 - final
4400         GET_SYMBOL_DB("class Base { virtual int f() const = 0; };\n"
4401                       "class Derived : Base { virtual int f() const final { return 6; } };");
4402 
4403         ASSERT_EQUALS(4, db->scopeList.size());
4404         ASSERT_EQUALS(1, db->functionScopes.size());
4405 
4406         const Scope *f1 = db->functionScopes[0];
4407         ASSERT(f1->function->hasFinalSpecifier());
4408     }
4409 
symboldatabase75()4410     void symboldatabase75() {
4411         GET_SYMBOL_DB("template <typename T>\n"
4412                       "class optional {\n"
4413                       "  auto     value() & -> T &;\n"
4414                       "  auto     value() && -> T &&;\n"
4415                       "  auto     value() const& -> T const &;\n"
4416                       "};\n"
4417                       "template <typename T>\n"
4418                       "auto optional<T>::value() & -> T & {}\n"
4419                       "template <typename T>\n"
4420                       "auto optional<T>::value() && -> T && {}\n"
4421                       "template <typename T>\n"
4422                       "auto optional<T>::value() const & -> T const & {}\n"
4423                       "optional<int> i;");
4424 
4425         ASSERT_EQUALS(5, db->scopeList.size());
4426         ASSERT_EQUALS(3, db->functionScopes.size());
4427 
4428         const Scope *f = db->functionScopes[0];
4429         ASSERT(f->function->hasBody());
4430         ASSERT(!f->function->isConst());
4431         ASSERT(f->function->hasTrailingReturnType());
4432         ASSERT(f->function->hasLvalRefQualifier());
4433 
4434         f = db->functionScopes[1];
4435         ASSERT(f->function->hasBody());
4436         ASSERT(!f->function->isConst());
4437         ASSERT(f->function->hasTrailingReturnType());
4438         ASSERT(f->function->hasRvalRefQualifier());
4439 
4440         f = db->functionScopes[2];
4441         ASSERT(f->function->hasBody());
4442         ASSERT(f->function->isConst());
4443         ASSERT(f->function->hasTrailingReturnType());
4444         ASSERT(f->function->hasLvalRefQualifier());
4445     }
4446 
symboldatabase76()4447     void symboldatabase76() { // #9056
4448         GET_SYMBOL_DB("namespace foo {\n"
4449                       "  using namespace bar::baz;\n"
4450                       "  auto func(int arg) -> bar::quux {}\n"
4451                       "}");
4452         ASSERT_EQUALS(2, db->mVariableList.size());
4453     }
4454 
symboldatabase77()4455     void symboldatabase77() { // #8663
4456         GET_SYMBOL_DB("template <class T1, class T2>\n"
4457                       "void f() {\n"
4458                       "  using T3 = typename T1::template T3<T2>;\n"
4459                       "  T3 t;\n"
4460                       "}");
4461         ASSERT_EQUALS(2, db->mVariableList.size());
4462     }
4463 
symboldatabase78()4464     void symboldatabase78() { // #9147
4465         GET_SYMBOL_DB("template <class...> struct a;\n"
4466                       "namespace {\n"
4467                       "template <class, class> struct b;\n"
4468                       "template <template <class> class c, class... f, template <class...> class d>\n"
4469                       "struct b<c<f...>, d<>>;\n"
4470                       "}\n"
4471                       "void e() { using c = a<>; }");
4472         ASSERT(db != nullptr);
4473         ASSERT_EQUALS("", errout.str());
4474     }
4475 
symboldatabase79()4476     void symboldatabase79() { // #9392
4477         {
4478             GET_SYMBOL_DB("class C { C(); };\n"
4479                           "C::C() = default;");
4480             ASSERT(db->scopeList.size() == 2);
4481             ASSERT(db->scopeList.back().functionList.size() == 1);
4482             ASSERT(db->scopeList.back().functionList.front().isDefault() == true);
4483         }
4484         {
4485             GET_SYMBOL_DB("namespace ns {\n"
4486                           "class C { C(); };\n"
4487                           "}\n"
4488                           "using namespace ns;\n"
4489                           "C::C() = default;");
4490             ASSERT(db->scopeList.size() == 3);
4491             ASSERT(db->scopeList.back().functionList.size() == 1);
4492             ASSERT(db->scopeList.back().functionList.front().isDefault() == true);
4493         }
4494     }
4495 
symboldatabase80()4496     void symboldatabase80() { // #9389
4497         {
4498             GET_SYMBOL_DB("namespace ns {\n"
4499                           "class A {};\n"
4500                           "}\n"
4501                           "class AA {\n"
4502                           "private:\n"
4503                           "    void f(const ns::A&);\n"
4504                           "};\n"
4505                           "using namespace ns;\n"
4506                           "void AA::f(const A&) { }");
4507             ASSERT(db->scopeList.size() == 5);
4508             ASSERT(db->functionScopes.size() == 1);
4509             const Scope *scope = db->findScopeByName("AA");
4510             ASSERT(scope);
4511             ASSERT(scope->functionList.size() == 1);
4512             ASSERT(scope->functionList.front().name() == "f");
4513             ASSERT(scope->functionList.front().hasBody() == true);
4514         }
4515         {
4516             GET_SYMBOL_DB("namespace ns {\n"
4517                           "namespace ns1 {\n"
4518                           "class A {};\n"
4519                           "}\n"
4520                           "}\n"
4521                           "class AA {\n"
4522                           "private:\n"
4523                           "    void f(const ns::ns1::A&);\n"
4524                           "};\n"
4525                           "using namespace ns::ns1;\n"
4526                           "void AA::f(const A&) { }");
4527             ASSERT(db->scopeList.size() == 6);
4528             ASSERT(db->functionScopes.size() == 1);
4529             const Scope *scope = db->findScopeByName("AA");
4530             ASSERT(scope);
4531             ASSERT(scope->functionList.size() == 1);
4532             ASSERT(scope->functionList.front().name() == "f");
4533             ASSERT(scope->functionList.front().hasBody() == true);
4534         }
4535         {
4536             GET_SYMBOL_DB("namespace ns {\n"
4537                           "namespace ns1 {\n"
4538                           "class A {};\n"
4539                           "}\n"
4540                           "}\n"
4541                           "class AA {\n"
4542                           "private:\n"
4543                           "    void f(const ns::ns1::A&);\n"
4544                           "};\n"
4545                           "using namespace ns;\n"
4546                           "void AA::f(const ns1::A&) { }");
4547             ASSERT(db->scopeList.size() == 6);
4548             ASSERT(db->functionScopes.size() == 1);
4549             const Scope *scope = db->findScopeByName("AA");
4550             ASSERT(scope);
4551             ASSERT(scope->functionList.size() == 1);
4552             ASSERT(scope->functionList.front().name() == "f");
4553             ASSERT(scope->functionList.front().hasBody() == true);
4554         }
4555     }
4556 
symboldatabase81()4557     void symboldatabase81() { // #9411
4558         {
4559             GET_SYMBOL_DB("namespace Terminal {\n"
4560                           "    class Complete {\n"
4561                           "    public:\n"
4562                           "        std::string act(const Parser::Action *act);\n"
4563                           "    };\n"
4564                           "}\n"
4565                           "using namespace std;\n"
4566                           "using namespace Parser;\n"
4567                           "using namespace Terminal;\n"
4568                           "string Complete::act(const Action *act) { }");
4569             ASSERT(db->scopeList.size() == 4);
4570             ASSERT(db->functionScopes.size() == 1);
4571             const Scope *scope = db->findScopeByName("Complete");
4572             ASSERT(scope);
4573             ASSERT(scope->functionList.size() == 1);
4574             ASSERT(scope->functionList.front().name() == "act");
4575             ASSERT(scope->functionList.front().hasBody() == true);
4576         }
4577         {
4578             GET_SYMBOL_DB("namespace Terminal {\n"
4579                           "    class Complete {\n"
4580                           "    public:\n"
4581                           "        std::string act(const Foo::Parser::Action *act);\n"
4582                           "    };\n"
4583                           "}\n"
4584                           "using namespace std;\n"
4585                           "using namespace Foo::Parser;\n"
4586                           "using namespace Terminal;\n"
4587                           "string Complete::act(const Action *act) { }");
4588             ASSERT(db->scopeList.size() == 4);
4589             ASSERT(db->functionScopes.size() == 1);
4590             const Scope *scope = db->findScopeByName("Complete");
4591             ASSERT(scope);
4592             ASSERT(scope->functionList.size() == 1);
4593             ASSERT(scope->functionList.front().name() == "act");
4594             ASSERT(scope->functionList.front().hasBody() == true);
4595         }
4596     }
4597 
symboldatabase82()4598     void symboldatabase82() {
4599         GET_SYMBOL_DB("namespace foo { void foo() {} }");
4600         ASSERT(db->functionScopes.size() == 1);
4601         ASSERT_EQUALS(false, db->functionScopes[0]->function->isConstructor());
4602     }
4603 
symboldatabase83()4604     void symboldatabase83() { // #9431
4605         const bool old = settings1.debugwarnings;
4606         settings1.debugwarnings = true;
4607         GET_SYMBOL_DB("struct a { a() noexcept; };\n"
4608                       "a::a() noexcept = default;");
4609         settings1.debugwarnings = old;
4610         const Scope *scope = db->findScopeByName("a");
4611         ASSERT(scope);
4612         ASSERT(scope->functionList.size() == 1);
4613         ASSERT(scope->functionList.front().name() == "a");
4614         ASSERT(scope->functionList.front().hasBody() == false);
4615         ASSERT(scope->functionList.front().isConstructor() == true);
4616         ASSERT(scope->functionList.front().isDefault() == true);
4617         ASSERT(scope->functionList.front().isNoExcept() == true);
4618         ASSERT_EQUALS("", errout.str());
4619     }
4620 
symboldatabase84()4621     void symboldatabase84() {
4622         {
4623             const bool old = settings1.debugwarnings;
4624             settings1.debugwarnings = true;
4625             GET_SYMBOL_DB("struct a { a() noexcept(false); };\n"
4626                           "a::a() noexcept(false) = default;");
4627             settings1.debugwarnings = old;
4628             const Scope *scope = db->findScopeByName("a");
4629             ASSERT(scope);
4630             ASSERT(scope->functionList.size() == 1);
4631             ASSERT(scope->functionList.front().name() == "a");
4632             ASSERT(scope->functionList.front().hasBody() == false);
4633             ASSERT(scope->functionList.front().isConstructor() == true);
4634             ASSERT(scope->functionList.front().isDefault() == true);
4635             ASSERT(scope->functionList.front().isNoExcept() == false);
4636             ASSERT_EQUALS("", errout.str());
4637         }
4638         {
4639             const bool old = settings1.debugwarnings;
4640             settings1.debugwarnings = true;
4641             GET_SYMBOL_DB("struct a { a() noexcept(true); };\n"
4642                           "a::a() noexcept(true) = default;");
4643             settings1.debugwarnings = old;
4644             const Scope *scope = db->findScopeByName("a");
4645             ASSERT(scope);
4646             ASSERT(scope->functionList.size() == 1);
4647             ASSERT(scope->functionList.front().name() == "a");
4648             ASSERT(scope->functionList.front().hasBody() == false);
4649             ASSERT(scope->functionList.front().isConstructor() == true);
4650             ASSERT(scope->functionList.front().isDefault() == true);
4651             ASSERT(scope->functionList.front().isNoExcept() == true);
4652             ASSERT_EQUALS("", errout.str());
4653         }
4654     }
4655 
symboldatabase85()4656     void symboldatabase85() {
4657         GET_SYMBOL_DB("class Fred {\n"
4658                       "  enum Mode { Mode1, Mode2, Mode3 };\n"
4659                       "  void f() { _mode = x; }\n"
4660                       "  Mode _mode;\n"
4661                       "  DECLARE_PROPERTY_FIELD(_mode);\n"
4662                       "};");
4663         const Token *vartok1 = Token::findsimplematch(tokenizer.tokens(), "_mode =");
4664         ASSERT(vartok1);
4665         ASSERT(vartok1->variable());
4666         ASSERT(vartok1->variable()->scope());
4667 
4668         const Token *vartok2 = Token::findsimplematch(tokenizer.tokens(), "( _mode ) ;")->next();
4669         ASSERT_EQUALS(std::intptr_t(vartok1->variable()), std::intptr_t(vartok2->variable()));
4670     }
4671 
symboldatabase86()4672     void symboldatabase86() {
4673         GET_SYMBOL_DB("class C { auto operator=(const C&) -> C&; };\n"
4674                       "auto C::operator=(const C&) -> C& = default;");
4675         ASSERT(db->scopeList.size() == 2);
4676         ASSERT(db->scopeList.back().functionList.size() == 1);
4677         ASSERT(db->scopeList.back().functionList.front().isDefault() == true);
4678         ASSERT(db->scopeList.back().functionList.front().hasBody() == false);
4679     }
4680 
symboldatabase87()4681     void symboldatabase87() { // #9922 'extern const char ( * x [ 256 ] ) ;'
4682         GET_SYMBOL_DB("extern const char ( * x [ 256 ] ) ;");
4683         const Token *xtok = Token::findsimplematch(tokenizer.tokens(), "x");
4684         ASSERT(xtok->variable());
4685     }
4686 
symboldatabase88()4687     void symboldatabase88() { // #10040 (using namespace)
4688         check("namespace external {\n"
4689               "namespace ns {\n"
4690               "enum class s { O };\n"
4691               "}\n"
4692               "}\n"
4693               "namespace internal {\n"
4694               "namespace ns1 {\n"
4695               "template <typename T>\n"
4696               "void make(external::ns::s) {\n"
4697               "}\n"
4698               "}\n"
4699               "}\n"
4700               "using namespace external::ns;\n"
4701               "struct A { };\n"
4702               "static void make(external::ns::s ss) {\n"
4703               "  internal::ns1::make<A>(ss);\n"
4704               "}\n", true);
4705         ASSERT_EQUALS("", errout.str());
4706     }
4707 
symboldatabase89()4708     void symboldatabase89() { // valuetype name
4709         GET_SYMBOL_DB("namespace external {\n"
4710                       "namespace ns1 {\n"
4711                       "class A {\n"
4712                       "public:\n"
4713                       "  struct S { };\n"
4714                       "  A(const S&) { }\n"
4715                       "};\n"
4716                       "static const A::S AS = A::S();\n"
4717                       "}\n"
4718                       "}\n"
4719                       "using namespace external::ns1;\n"
4720                       "A a{AS};");
4721         const Token *vartok1 = Token::findsimplematch(tokenizer.tokens(), "A a");
4722         ASSERT(vartok1);
4723         ASSERT(vartok1->next());
4724         ASSERT(vartok1->next()->variable());
4725         ASSERT(vartok1->next()->variable()->valueType());
4726         ASSERT(vartok1->next()->variable()->valueType()->str() == "external::ns1::A");
4727     }
4728 
symboldatabase90()4729     void symboldatabase90() {
4730         GET_SYMBOL_DB("struct Fred {\n"
4731                       "    void foo(const int * const x);\n"
4732                       "};\n"
4733                       "void Fred::foo(const int * x) { }");
4734         ASSERT_EQUALS("", errout.str());
4735         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "foo ( const int * x )");
4736         ASSERT(functok);
4737         ASSERT(functok->function());
4738         ASSERT(functok->function()->name() == "foo");
4739     }
4740 
symboldatabase91()4741     void symboldatabase91() {
4742         GET_SYMBOL_DB("namespace Fred {\n"
4743                       "    struct Value {};\n"
4744                       "    void foo(const std::vector<std::function<void(const Fred::Value &)>> &callbacks);\n"
4745                       "}\n"
4746                       "void Fred::foo(const std::vector<std::function<void(const Fred::Value &)>> &callbacks) { }");
4747         ASSERT_EQUALS("", errout.str());
4748         const Token *functok = Token::findsimplematch(tokenizer.tokens(),
4749                                                       "foo ( const std :: vector < std :: function < void ( const Fred :: Value & ) > > & callbacks ) { }");
4750         ASSERT(functok);
4751         ASSERT(functok->function());
4752         ASSERT(functok->function()->name() == "foo");
4753     }
4754 
symboldatabase92()4755     void symboldatabase92() { // daca crash
4756         GET_SYMBOL_DB("template <size_t, typename...> struct a;\n"
4757                       "template <size_t b, typename c, typename... d>\n"
4758                       "struct a<b, c, d...> : a<1, d...> {};\n"
4759                       "template <typename... e> struct f : a<0, e...> {};");
4760         ASSERT_EQUALS("", errout.str());
4761     }
4762 
symboldatabase93()4763     void symboldatabase93() { // alignas attribute
4764         GET_SYMBOL_DB("struct alignas(int) A{\n"
4765                       "};\n"
4766                       );
4767         ASSERT(db != nullptr);
4768         const Scope* scope = db->findScopeByName("A");
4769         ASSERT(scope);
4770     }
4771 
symboldatabase94()4772     void symboldatabase94() { // structured bindings
4773         GET_SYMBOL_DB("int foo() { auto [x,y] = xy(); return x+y; }");
4774         ASSERT(db != nullptr);
4775         ASSERT(db->getVariableFromVarId(1) != nullptr);
4776         ASSERT(db->getVariableFromVarId(2) != nullptr);
4777     }
4778 
symboldatabase95()4779     void symboldatabase95() { // #10295
4780         GET_SYMBOL_DB("struct B {\n"
4781                       "    void foo1(void);\n"
4782                       "    void foo2();\n"
4783                       "};\n"
4784                       "void B::foo1() {}\n"
4785                       "void B::foo2(void) {}\n");
4786         ASSERT_EQUALS("", errout.str());
4787         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "foo1 ( ) { }");
4788         ASSERT(functok);
4789         ASSERT(functok->function());
4790         ASSERT(functok->function()->name() == "foo1");
4791         functok = Token::findsimplematch(tokenizer.tokens(), "foo2 ( void ) { }");
4792         ASSERT(functok);
4793         ASSERT(functok->function());
4794         ASSERT(functok->function()->name() == "foo2");
4795     }
4796 
createSymbolDatabaseFindAllScopes1()4797     void createSymbolDatabaseFindAllScopes1() {
4798         GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }");
4799         ASSERT(db->scopeList.size() == 3);
4800         ASSERT_EQUALS(Scope::eUnion, db->scopeList.back().type);
4801     }
4802 
createSymbolDatabaseFindAllScopes2()4803     void createSymbolDatabaseFindAllScopes2() {
4804         GET_SYMBOL_DB("namespace ns { auto var1{0}; }\n"
4805                       "namespace ns { auto var2{0}; }\n");
4806         ASSERT(db);
4807         ASSERT_EQUALS(2, db->scopeList.size());
4808         ASSERT_EQUALS(2, db->scopeList.back().varlist.size());
4809         const Token* const var1 = Token::findsimplematch(tokenizer.tokens(), "var1");
4810         const Token* const var2 = Token::findsimplematch(tokenizer.tokens(), "var2");
4811         ASSERT(var1->variable());
4812         ASSERT(var2->variable());
4813     }
4814 
createSymbolDatabaseFindAllScopes3()4815     void createSymbolDatabaseFindAllScopes3() {
4816         GET_SYMBOL_DB("namespace ns {\n"
4817                       "\n"
4818                       "namespace ns_details {\n"
4819                       "template <typename T, typename = void> struct has_A : std::false_type {};\n"
4820                       "template <typename T> struct has_A<T, typename make_void<typename T::A>::type> : std::true_type {};\n"
4821                       "template <typename T, bool> struct is_A_impl : public std::is_trivially_copyable<T> {};\n"
4822                       "template <typename T> struct is_A_impl<T, true> : public std::is_same<typename T::A, std::true_type> {};\n"
4823                       "}\n"
4824                       "\n"
4825                       "template <typename T> struct is_A : ns_details::is_A_impl<T, ns_details::has_A<T>::value> {};\n"
4826                       "template <class T, class U> struct is_A<std::pair<T, U>> : std::integral_constant<bool, is_A<T>::value && is_A<U>::value> {};\n"
4827                       "}\n"
4828                       "\n"
4829                       "extern \"C\" {\n"
4830                       "static const int foo = 8;\n"
4831                       "}\n");
4832         ASSERT(db);
4833         ASSERT_EQUALS(6, db->scopeList.size());
4834         ASSERT_EQUALS(1, db->scopeList.front().varlist.size());
4835         auto list = db->scopeList;
4836         list.pop_front();
4837         for (const auto &scope : list) {
4838             ASSERT_EQUALS(0, scope.varlist.size());
4839         }
4840     }
4841 
enum1()4842     void enum1() {
4843         GET_SYMBOL_DB("enum BOOL { FALSE, TRUE }; enum BOOL b;");
4844 
4845         /* there is a enum scope with the name BOOL */
4846         ASSERT(db && db->scopeList.back().type == Scope::eEnum && db->scopeList.back().className == "BOOL");
4847 
4848         /* b is a enum variable, type is BOOL */
4849         ASSERT(db && db->getVariableFromVarId(1)->isEnumType());
4850     }
4851 
enum2()4852     void enum2() {
4853         GET_SYMBOL_DB("enum BOOL { FALSE, TRUE } b;");
4854 
4855         /* there is a enum scope with the name BOOL */
4856         ASSERT(db && db->scopeList.back().type == Scope::eEnum && db->scopeList.back().className == "BOOL");
4857 
4858         /* b is a enum variable, type is BOOL */
4859         ASSERT(db && db->getVariableFromVarId(1)->isEnumType());
4860     }
4861 
enum3()4862     void enum3() {
4863         GET_SYMBOL_DB("enum ABC { A=11,B,C=A+B };");
4864         ASSERT(db && db->scopeList.back().type == Scope::eEnum);
4865 
4866         /* There is an enum A with value 11 */
4867         const Enumerator *A = db->scopeList.back().findEnumerator("A");
4868         ASSERT(A && A->value==11 && A->value_known);
4869 
4870         /* There is an enum B with value 12 */
4871         const Enumerator *B = db->scopeList.back().findEnumerator("B");
4872         ASSERT(B && B->value==12 && B->value_known);
4873 
4874         /* There is an enum C with value 23 */
4875         const Enumerator *C = db->scopeList.back().findEnumerator("C");
4876         ASSERT(C && C->value==23 && C->value_known);
4877     }
4878 
enum4()4879     void enum4() { // #7493
4880         GET_SYMBOL_DB("enum Offsets { O1, O2, O3=5, O4 };\n"
4881                       "enum MyEnums { E1=O1+1, E2, E3=O3+1 };");
4882         ASSERT(db != nullptr);
4883 
4884         ASSERT_EQUALS(3U, db->scopeList.size());
4885 
4886         // Assert that all enum values are known
4887         std::list<Scope>::const_iterator scope = db->scopeList.begin();
4888 
4889         // Offsets
4890         ++scope;
4891         ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
4892         ASSERT_EQUALS(4U, scope->enumeratorList.size());
4893 
4894         ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]);
4895         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType());
4896         ASSERT(scope->enumeratorList[0].scope == &*scope);
4897         ASSERT_EQUALS("O1", scope->enumeratorList[0].name->str());
4898         ASSERT(scope->enumeratorList[0].start == nullptr);
4899         ASSERT(scope->enumeratorList[0].end == nullptr);
4900         ASSERT_EQUALS(true, scope->enumeratorList[0].value_known);
4901         ASSERT_EQUALS(0, scope->enumeratorList[0].value);
4902 
4903         ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]);
4904         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType());
4905         ASSERT(scope->enumeratorList[1].scope == &*scope);
4906         ASSERT_EQUALS("O2", scope->enumeratorList[1].name->str());
4907         ASSERT(scope->enumeratorList[1].start == nullptr);
4908         ASSERT(scope->enumeratorList[1].end == nullptr);
4909         ASSERT_EQUALS(true, scope->enumeratorList[1].value_known);
4910         ASSERT_EQUALS(1, scope->enumeratorList[1].value);
4911 
4912         ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]);
4913         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType());
4914         ASSERT(scope->enumeratorList[2].scope == &*scope);
4915         ASSERT_EQUALS("O3", scope->enumeratorList[2].name->str());
4916         ASSERT(scope->enumeratorList[2].start != nullptr);
4917         ASSERT(scope->enumeratorList[2].end != nullptr);
4918         ASSERT_EQUALS(true, scope->enumeratorList[2].value_known);
4919         ASSERT_EQUALS(5, scope->enumeratorList[2].value);
4920 
4921         ASSERT(scope->enumeratorList[3].name->enumerator() == &scope->enumeratorList[3]);
4922         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[3].name->tokType());
4923         ASSERT(scope->enumeratorList[3].scope == &*scope);
4924         ASSERT_EQUALS("O4", scope->enumeratorList[3].name->str());
4925         ASSERT(scope->enumeratorList[3].start == nullptr);
4926         ASSERT(scope->enumeratorList[3].end == nullptr);
4927         ASSERT_EQUALS(true, scope->enumeratorList[3].value_known);
4928         ASSERT_EQUALS(6, scope->enumeratorList[3].value);
4929 
4930         // MyEnums
4931         ++scope;
4932         ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
4933         ASSERT_EQUALS(3U, scope->enumeratorList.size());
4934 
4935         ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]);
4936         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType());
4937         ASSERT(scope->enumeratorList[0].scope == &*scope);
4938         ASSERT_EQUALS("E1", scope->enumeratorList[0].name->str());
4939         ASSERT(scope->enumeratorList[0].start != nullptr);
4940         ASSERT(scope->enumeratorList[0].end != nullptr);
4941         ASSERT_EQUALS(true, scope->enumeratorList[0].value_known);
4942         ASSERT_EQUALS(1, scope->enumeratorList[0].value);
4943 
4944         ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]);
4945         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType());
4946         ASSERT(scope->enumeratorList[1].scope == &*scope);
4947         ASSERT_EQUALS("E2", scope->enumeratorList[1].name->str());
4948         ASSERT(scope->enumeratorList[1].start == nullptr);
4949         ASSERT(scope->enumeratorList[1].end == nullptr);
4950         ASSERT_EQUALS(true, scope->enumeratorList[1].value_known);
4951         ASSERT_EQUALS(2, scope->enumeratorList[1].value);
4952 
4953         ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]);
4954         ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType());
4955         ASSERT(scope->enumeratorList[2].scope == &*scope);
4956         ASSERT_EQUALS("E3", scope->enumeratorList[2].name->str());
4957         ASSERT(scope->enumeratorList[2].start != nullptr);
4958         ASSERT(scope->enumeratorList[2].end != nullptr);
4959         ASSERT_EQUALS(true, scope->enumeratorList[2].value_known);
4960         ASSERT_EQUALS(6, scope->enumeratorList[2].value);
4961     }
4962 
enum5()4963     void enum5() {
4964         GET_SYMBOL_DB("enum { A = 10, B = 2 };\n"
4965                       "int a[10 + 2];\n"
4966                       "int b[A];\n"
4967                       "int c[A + 2];\n"
4968                       "int d[10 + B];\n"
4969                       "int e[A + B];");
4970         ASSERT(db != nullptr);
4971 
4972         ASSERT_EQUALS(2U, db->scopeList.size());
4973 
4974         // Assert that all enum values are known
4975         std::list<Scope>::const_iterator scope = db->scopeList.begin();
4976 
4977         ++scope;
4978         ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
4979         ASSERT_EQUALS(2U, scope->enumeratorList.size());
4980         ASSERT_EQUALS(true, scope->enumeratorList[0].value_known);
4981         ASSERT_EQUALS(10, scope->enumeratorList[0].value);
4982         ASSERT_EQUALS(true, scope->enumeratorList[1].value_known);
4983         ASSERT_EQUALS(2, scope->enumeratorList[1].value);
4984 
4985         ASSERT(db->variableList().size() == 6); // the first one is not used
4986         const Variable * v = db->getVariableFromVarId(1);
4987         ASSERT(v != nullptr);
4988 
4989         ASSERT(v->isArray());
4990         ASSERT_EQUALS(1U, v->dimensions().size());
4991         ASSERT_EQUALS(12U, v->dimension(0));
4992         v = db->getVariableFromVarId(2);
4993         ASSERT(v != nullptr);
4994 
4995         ASSERT(v->isArray());
4996         ASSERT_EQUALS(1U, v->dimensions().size());
4997         ASSERT_EQUALS(10U, v->dimension(0));
4998         v = db->getVariableFromVarId(3);
4999         ASSERT(v != nullptr);
5000 
5001         ASSERT(v->isArray());
5002         ASSERT_EQUALS(1U, v->dimensions().size());
5003         ASSERT_EQUALS(12U, v->dimension(0));
5004         v = db->getVariableFromVarId(4);
5005         ASSERT(v != nullptr);
5006 
5007         ASSERT(v->isArray());
5008         ASSERT_EQUALS(1U, v->dimensions().size());
5009         ASSERT_EQUALS(12U, v->dimension(0));
5010         v = db->getVariableFromVarId(5);
5011         ASSERT(v != nullptr);
5012 
5013         ASSERT(v->isArray());
5014         ASSERT_EQUALS(1U, v->dimensions().size());
5015         ASSERT_EQUALS(12U, v->dimension(0));
5016     }
5017 
enum6()5018     void enum6() {
5019         GET_SYMBOL_DB("struct Fred {\n"
5020                       "    enum Enum { E0, E1 };\n"
5021                       "};\n"
5022                       "struct Barney : public Fred {\n"
5023                       "    Enum func(Enum e) { return e; }\n"
5024                       "};");
5025         ASSERT(db != nullptr);
5026 
5027         const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func");
5028         ASSERT(functionToken != nullptr);
5029 
5030         const Function *function = functionToken->function();
5031         ASSERT(function != nullptr);
5032 
5033         ASSERT(function->token->str() == "func");
5034         ASSERT(function->retDef && function->retDef->str() == "Enum");
5035         ASSERT(function->retType && function->retType->name() == "Enum");
5036     }
5037 
5038 #define TEST(S) \
5039     v = db->getVariableFromVarId(id++); \
5040     ASSERT(v != nullptr); \
5041     ASSERT(v->isArray()); \
5042     ASSERT_EQUALS(1U, v->dimensions().size()); \
5043     ASSERT_EQUALS(S, v->dimension(0))
5044 
enum7()5045     void enum7() {
5046         GET_SYMBOL_DB("enum E { X };\n"
5047                       "enum EC : char { C };\n"
5048                       "enum ES : short { S };\n"
5049                       "enum EI : int { I };\n"
5050                       "enum EL : long { L };\n"
5051                       "enum ELL : long long { LL };\n"
5052                       "char array1[sizeof(E)];\n"
5053                       "char array2[sizeof(X)];\n"
5054                       "char array3[sizeof(EC)];\n"
5055                       "char array4[sizeof(C)];\n"
5056                       "char array5[sizeof(ES)];\n"
5057                       "char array6[sizeof(S)];\n"
5058                       "char array7[sizeof(EI)];\n"
5059                       "char array8[sizeof(I)];\n"
5060                       "char array9[sizeof(EL)];\n"
5061                       "char array10[sizeof(L)];\n"
5062                       "char array11[sizeof(ELL)];\n"
5063                       "char array12[sizeof(LL)];");
5064         ASSERT(db != nullptr);
5065 
5066         ASSERT(db->variableList().size() == 13); // the first one is not used
5067         const Variable * v;
5068         unsigned int id = 1;
5069         TEST(settings1.sizeof_int);
5070         TEST(settings1.sizeof_int);
5071         TEST(1);
5072         TEST(1);
5073         TEST(settings1.sizeof_short);
5074         TEST(settings1.sizeof_short);
5075         TEST(settings1.sizeof_int);
5076         TEST(settings1.sizeof_int);
5077         TEST(settings1.sizeof_long);
5078         TEST(settings1.sizeof_long);
5079         TEST(settings1.sizeof_long_long);
5080         TEST(settings1.sizeof_long_long);
5081     }
5082 
enum8()5083     void enum8() {
5084         GET_SYMBOL_DB("enum E { X0 = x, X1, X2 = 2, X3, X4 = y, X5 };\n");
5085         ASSERT(db != nullptr);
5086         const Enumerator *X0 = db->scopeList.back().findEnumerator("X0");
5087         ASSERT(X0);
5088         ASSERT(!X0->value_known);
5089         const Enumerator *X1 = db->scopeList.back().findEnumerator("X1");
5090         ASSERT(X1);
5091         ASSERT(!X1->value_known);
5092         const Enumerator *X2 = db->scopeList.back().findEnumerator("X2");
5093         ASSERT(X2);
5094         ASSERT(X2->value_known);
5095         ASSERT_EQUALS(X2->value, 2);
5096         const Enumerator *X3 = db->scopeList.back().findEnumerator("X3");
5097         ASSERT(X3);
5098         ASSERT(X3->value_known);
5099         ASSERT_EQUALS(X3->value, 3);
5100         const Enumerator *X4 = db->scopeList.back().findEnumerator("X4");
5101         ASSERT(X4);
5102         ASSERT(!X4->value_known);
5103         const Enumerator *X5 = db->scopeList.back().findEnumerator("X5");
5104         ASSERT(X5);
5105         ASSERT(!X5->value_known);
5106     }
5107 
enum9()5108     void enum9() {
5109         GET_SYMBOL_DB("const int x = 7; enum E { X0 = x, X1 };\n");
5110         ASSERT(db != nullptr);
5111         const Enumerator *X0 = db->scopeList.back().findEnumerator("X0");
5112         ASSERT(X0);
5113         ASSERT(X0->value_known);
5114         ASSERT_EQUALS(X0->value, 7);
5115         const Enumerator *X1 = db->scopeList.back().findEnumerator("X1");
5116         ASSERT(X1);
5117         ASSERT(X1->value_known);
5118         ASSERT_EQUALS(X1->value, 8);
5119     }
5120 
sizeOfType()5121     void sizeOfType() {
5122         // #7615 - crash in Symboldatabase::sizeOfType()
5123         GET_SYMBOL_DB("enum e;\n"
5124                       "void foo() {\n"
5125                       "    e abc[] = {A,B,C};\n"
5126                       "    int i = abc[ARRAY_SIZE(cats)];\n"
5127                       "}");
5128         const Token *e = Token::findsimplematch(tokenizer.tokens(), "e abc");
5129         db->sizeOfType(e);  // <- don't crash
5130     }
5131 
isImplicitlyVirtual()5132     void isImplicitlyVirtual() {
5133         {
5134             GET_SYMBOL_DB("class Base {\n"
5135                           "    virtual void foo() {}\n"
5136                           "};\n"
5137                           "class Deri : Base {\n"
5138                           "    void foo() {}\n"
5139                           "};");
5140             ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual());
5141         }
5142         {
5143             GET_SYMBOL_DB("class Base {\n"
5144                           "    virtual void foo() {}\n"
5145                           "};\n"
5146                           "class Deri1 : Base {\n"
5147                           "    void foo() {}\n"
5148                           "};\n"
5149                           "class Deri2 : Deri1 {\n"
5150                           "    void foo() {}\n"
5151                           "};");
5152             ASSERT(db && db->findScopeByName("Deri2") && db->findScopeByName("Deri2")->functionList.front().isImplicitlyVirtual());
5153         }
5154         {
5155             GET_SYMBOL_DB("class Base {\n"
5156                           "    void foo() {}\n"
5157                           "};\n"
5158                           "class Deri : Base {\n"
5159                           "    void foo() {}\n"
5160                           "};");
5161             ASSERT(db && db->findScopeByName("Deri") && !db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual(true));
5162         }
5163         {
5164             GET_SYMBOL_DB("class Base {\n"
5165                           "    virtual void foo() {}\n"
5166                           "};\n"
5167                           "class Deri : Base {\n"
5168                           "    void foo(std::string& s) {}\n"
5169                           "};");
5170             ASSERT(db && db->findScopeByName("Deri") && !db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual(true));
5171         }
5172         {
5173             GET_SYMBOL_DB("class Base {\n"
5174                           "    virtual void foo() {}\n"
5175                           "};\n"
5176                           "class Deri1 : Base {\n"
5177                           "    void foo(int i) {}\n"
5178                           "};\n"
5179                           "class Deri2 : Deri1 {\n"
5180                           "    void foo() {}\n"
5181                           "};");
5182             ASSERT(db && db->findScopeByName("Deri2") && db->findScopeByName("Deri2")->functionList.front().isImplicitlyVirtual());
5183         }
5184         {
5185             GET_SYMBOL_DB("class Base : Base2 {\n" // We don't know Base2
5186                           "    void foo() {}\n"
5187                           "};\n"
5188                           "class Deri : Base {\n"
5189                           "    void foo() {}\n"
5190                           "};");
5191             ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual(true)); // Default true -> true
5192         }
5193         {
5194             GET_SYMBOL_DB("class Base : Base2 {\n" // We don't know Base2
5195                           "    void foo() {}\n"
5196                           "};\n"
5197                           "class Deri : Base {\n"
5198                           "    void foo() {}\n"
5199                           "};");
5200             ASSERT(db && db->findScopeByName("Deri") && !db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual(false)); // Default false -> false
5201         }
5202         {
5203             GET_SYMBOL_DB("class Base : Base2 {\n" // We don't know Base2
5204                           "    virtual void foo() {}\n"
5205                           "};\n"
5206                           "class Deri : Base {\n"
5207                           "    void foo() {}\n"
5208                           "};");
5209             ASSERT(db && db->findScopeByName("Deri") && db->findScopeByName("Deri")->functionList.front().isImplicitlyVirtual(false)); // Default false, but we saw "virtual" -> true
5210         }
5211         // #5289
5212         {
5213             GET_SYMBOL_DB("template<>\n"
5214                           "class Bar<void, void> {\n"
5215                           "};\n"
5216                           "template<typename K, typename V, int KeySize>\n"
5217                           "class Bar : private Bar<void, void> {\n"
5218                           "   void foo() {\n"
5219                           "   }\n"
5220                           "};");
5221             ASSERT(db && db->findScopeByName("Bar") && !db->findScopeByName("Bar")->functionList.empty() && !db->findScopeByName("Bar")->functionList.front().isImplicitlyVirtual(false));
5222             ASSERT_EQUALS(1, db->findScopeByName("Bar")->functionList.size());
5223         }
5224 
5225         // #5590
5226         {
5227             GET_SYMBOL_DB("class InfiniteB : InfiniteA {\n"
5228                           "    class D {\n"
5229                           "    };\n"
5230                           "};\n"
5231                           "namespace N {\n"
5232                           "    class InfiniteA : InfiniteB {\n"
5233                           "    };\n"
5234                           "}\n"
5235                           "class InfiniteA : InfiniteB {\n"
5236                           "    void foo();\n"
5237                           "};\n"
5238                           "void InfiniteA::foo() {\n"
5239                           "    C a;\n"
5240                           "}");
5241             //ASSERT(db && db->findScopeByName("InfiniteA") && !db->findScopeByName("InfiniteA")->functionList.front().isImplicitlyVirtual());
5242             TODO_ASSERT_EQUALS(1, 0, db->findScopeByName("InfiniteA")->functionList.size());
5243         }
5244     }
5245 
isPure()5246     void isPure() {
5247         GET_SYMBOL_DB("class C {\n"
5248                       "    void f() = 0;\n"
5249                       "    C(B b) = 0;\n"
5250                       "    C(C& c) = default;"
5251                       "    void g();\n"
5252                       "};");
5253         ASSERT(db && db->scopeList.back().functionList.size() == 4);
5254         std::list<Function>::const_iterator it = db->scopeList.back().functionList.begin();
5255         ASSERT((it++)->isPure());
5256         ASSERT((it++)->isPure());
5257         ASSERT(!(it++)->isPure());
5258         ASSERT(!(it++)->isPure());
5259     }
5260 
isFunction1()5261     void isFunction1() { // #5602 - UNKNOWN_MACRO(a,b) { .. }
5262         GET_SYMBOL_DB("TEST(a,b) {\n"
5263                       "  std::vector<int> messages;\n"
5264                       "  foo(messages[2].size());\n"
5265                       "}");
5266         const Variable * const var = db ? db->getVariableFromVarId(1U) : nullptr;
5267         ASSERT(db &&
5268                db->findScopeByName("TEST") &&
5269                var &&
5270                var->typeStartToken() &&
5271                var->typeStartToken()->str() == "std");
5272     }
5273 
isFunction2()5274     void isFunction2() {
5275         GET_SYMBOL_DB("void set_cur_cpu_spec()\n"
5276                       "{\n"
5277                       "    t = PTRRELOC(t);\n"
5278                       "}\n"
5279                       "\n"
5280                       "cpu_spec * __init setup_cpu_spec()\n"
5281                       "{\n"
5282                       "    t = PTRRELOC(t);\n"
5283                       "    *PTRRELOC(&x) = &y;\n"
5284                       "}");
5285         ASSERT(db != nullptr);
5286         ASSERT(db && !db->isFunction(Token::findsimplematch(tokenizer.tokens(), "PTRRELOC ( &"), &db->scopeList.back(), nullptr, nullptr, nullptr));
5287         ASSERT(db->findScopeByName("set_cur_cpu_spec") != nullptr);
5288         ASSERT(db->findScopeByName("setup_cpu_spec") != nullptr);
5289         ASSERT(db->findScopeByName("PTRRELOC") == nullptr);
5290     }
5291 
5292 
findFunction1()5293     void findFunction1() {
5294         GET_SYMBOL_DB("int foo(int x);\n" /* 1 */
5295                       "void foo();\n"     /* 2 */
5296                       "void bar() {\n"    /* 3 */
5297                       "    foo();\n"      /* 4 */
5298                       "    foo(1);\n"     /* 5 */
5299                       "}");               /* 6 */
5300         ASSERT_EQUALS("", errout.str());
5301         ASSERT(db);
5302         const Scope * bar = db->findScopeByName("bar");
5303         ASSERT(bar != nullptr);
5304         const unsigned int linenrs[2] = { 2, 1 };
5305         unsigned int index = 0;
5306         for (const Token * tok = bar->bodyStart->next(); tok != bar->bodyEnd; tok = tok->next()) {
5307             if (Token::Match(tok, "%name% (") && !tok->varId() && Token::simpleMatch(tok->linkAt(1), ") ;")) {
5308                 const Function * function = db->findFunction(tok);
5309                 ASSERT(function != nullptr);
5310                 if (function) {
5311                     std::stringstream expected;
5312                     expected << "Function call on line " << tok->linenr() << " calls function on line " << linenrs[index] << std::endl;
5313                     std::stringstream actual;
5314                     actual << "Function call on line " << tok->linenr() << " calls function on line " << function->tokenDef->linenr() << std::endl;
5315                     ASSERT_EQUALS(expected.str(), actual.str());
5316                 }
5317                 index++;
5318             }
5319         }
5320     }
5321 
findFunction2()5322     void findFunction2() {
5323         // The function does not match the function call.
5324         GET_SYMBOL_DB("void func(const int x, const Fred &fred);\n"
5325                       "void otherfunc() {\n"
5326                       "    float t;\n"
5327                       "    func(x, &t);\n"
5328                       "}");
5329         const Token *callfunc = Token::findsimplematch(tokenizer.tokens(), "func ( x , & t ) ;");
5330         ASSERT_EQUALS("", errout.str());
5331         ASSERT_EQUALS(true,  db != nullptr); // not null
5332         ASSERT_EQUALS(true,  callfunc != nullptr); // not null
5333         ASSERT_EQUALS(false, (callfunc && callfunc->function())); // callfunc->function() should be null
5334     }
5335 
findFunction3()5336     void findFunction3() {
5337         GET_SYMBOL_DB("struct base { void foo() { } };\n"
5338                       "struct derived : public base { void foo() { } };\n"
5339                       "void foo() {\n"
5340                       "    derived d;\n"
5341                       "    d.foo();\n"
5342                       "}");
5343 
5344         const Token *callfunc = Token::findsimplematch(tokenizer.tokens(), "d . foo ( ) ;");
5345         ASSERT_EQUALS("", errout.str());
5346         ASSERT_EQUALS(true, db != nullptr); // not null
5347         ASSERT_EQUALS(true, callfunc != nullptr); // not null
5348         ASSERT_EQUALS(true, callfunc && callfunc->tokAt(2)->function() && callfunc->tokAt(2)->function()->tokenDef->linenr() == 2); // should find function on line 2
5349     }
5350 
findFunction4()5351     void findFunction4() {
5352         GET_SYMBOL_DB("void foo(UNKNOWN) { }\n"
5353                       "void foo(int a) { }\n"
5354                       "void foo(unsigned int a) { }\n"
5355                       "void foo(unsigned long a) { }\n"
5356                       "void foo(unsigned long long a) { }\n"
5357                       "void foo(float a) { }\n"
5358                       "void foo(double a) { }\n"
5359                       "void foo(long double a) { }\n"
5360                       "int i;\n"
5361                       "unsigned int ui;\n"
5362                       "unsigned long ul;\n"
5363                       "unsigned long long ull;\n"
5364                       "float f;\n"
5365                       "double d;\n"
5366                       "long double ld;\n"
5367                       "int & ri = i;\n"
5368                       "unsigned int & rui = ui;\n"
5369                       "unsigned long & rul = ul;\n"
5370                       "unsigned long long & rull = ull;\n"
5371                       "float & rf = f;\n"
5372                       "double & rd = d;\n"
5373                       "long double & rld = ld;\n"
5374                       "const int & cri = i;\n"
5375                       "const unsigned int & crui = ui;\n"
5376                       "const unsigned long & crul = ul;\n"
5377                       "const unsigned long long & crull = ull;\n"
5378                       "const float & crf = f;\n"
5379                       "const double & crd = d;\n"
5380                       "const long double & crld = ld;\n"
5381                       "void foo() {\n"
5382                       "    foo(1);\n"
5383                       "    foo(1U);\n"
5384                       "    foo(1UL);\n"
5385                       "    foo(1ULL);\n"
5386                       "    foo(1.0F);\n"
5387                       "    foo(1.0);\n"
5388                       "    foo(1.0L);\n"
5389                       "    foo(i);\n"
5390                       "    foo(ui);\n"
5391                       "    foo(ul);\n"
5392                       "    foo(ull);\n"
5393                       "    foo(f);\n"
5394                       "    foo(d);\n"
5395                       "    foo(ld);\n"
5396                       "    foo(ri);\n"
5397                       "    foo(rui);\n"
5398                       "    foo(rul);\n"
5399                       "    foo(rull);\n"
5400                       "    foo(rf);\n"
5401                       "    foo(rd);\n"
5402                       "    foo(rld);\n"
5403                       "    foo(cri);\n"
5404                       "    foo(crui);\n"
5405                       "    foo(crul);\n"
5406                       "    foo(crull);\n"
5407                       "    foo(crf);\n"
5408                       "    foo(crd);\n"
5409                       "    foo(crld);\n"
5410                       "}");
5411 
5412         ASSERT_EQUALS("", errout.str());
5413 
5414         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 ) ;");
5415         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5416 
5417         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1U ) ;");
5418         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5419 
5420         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1UL ) ;");
5421         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5422 
5423         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1ULL ) ;");
5424         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
5425 
5426         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1.0F ) ;");
5427         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5428 
5429         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1.0 ) ;");
5430         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
5431 
5432         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 1.0L ) ;");
5433         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5434 
5435         f = Token::findsimplematch(tokenizer.tokens(), "foo ( i ) ;");
5436         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5437 
5438         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ui ) ;");
5439         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5440 
5441         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ul ) ;");
5442         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5443 
5444         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ull ) ;");
5445         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
5446 
5447         f = Token::findsimplematch(tokenizer.tokens(), "foo ( f ) ;");
5448         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5449 
5450         f = Token::findsimplematch(tokenizer.tokens(), "foo ( d ) ;");
5451         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
5452 
5453         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ld ) ;");
5454         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5455 
5456         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ri ) ;");
5457         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5458 
5459         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rui ) ;");
5460         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5461 
5462         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rul ) ;");
5463         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5464 
5465         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rull ) ;");
5466         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
5467 
5468         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rf ) ;");
5469         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5470 
5471         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rd ) ;");
5472         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
5473 
5474         f = Token::findsimplematch(tokenizer.tokens(), "foo ( rld ) ;");
5475         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5476 
5477         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cri ) ;");
5478         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5479 
5480         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crui ) ;");
5481         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5482 
5483         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crul ) ;");
5484         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5485 
5486         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crull ) ;");
5487         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
5488 
5489         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crf ) ;");
5490         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5491 
5492         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crd ) ;");
5493         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
5494 
5495         f = Token::findsimplematch(tokenizer.tokens(), "foo ( crld ) ;");
5496         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5497     }
5498 
findFunction5()5499     void findFunction5() {
5500         GET_SYMBOL_DB("struct Fred {\n"
5501                       "    void Sync(dsmp_t& type, int& len, int limit = 123);\n"
5502                       "    void Sync(int& syncpos, dsmp_t& type, int& len, int limit = 123);\n"
5503                       "    void FindSyncPoint();\n"
5504                       "};\n"
5505                       "void Fred::FindSyncPoint() {\n"
5506                       "    dsmp_t type;\n"
5507                       "    int syncpos, len;\n"
5508                       "    Sync(syncpos, type, len);\n"
5509                       "    Sync(type, len);\n"
5510                       "}");
5511         const Token *f = Token::findsimplematch(tokenizer.tokens(), "Sync ( syncpos");
5512         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5513 
5514         f = Token::findsimplematch(tokenizer.tokens(), "Sync ( type");
5515         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5516     }
5517 
findFunction6()5518     void findFunction6() { // avoid null pointer access
5519         GET_SYMBOL_DB("void addtoken(Token** rettail, const Token *tok);\n"
5520                       "void CheckMemoryLeakInFunction::getcode(const Token *tok ) {\n"
5521                       "   addtoken(&rettail, tok);\n"
5522                       "}");
5523         const Token *f = Token::findsimplematch(tokenizer.tokens(), "void addtoken ( Token * *");
5524         ASSERT_EQUALS(true, db && f && !f->function()); // regression value only
5525     }
5526 
findFunction7()5527     void findFunction7() {
5528         GET_SYMBOL_DB("class ResultEnsemble {\n"
5529                       "public:\n"
5530                       "    std::vector<int> &nodeResults() const;\n"
5531                       "    std::vector<int> &nodeResults();\n"
5532                       "};\n"
5533                       "class Simulator {\n"
5534                       "    int generatePinchResultEnsemble(const ResultEnsemble &power, const ResultEnsemble &ground) {\n"
5535                       "        power.nodeResults().size();\n"
5536                       "        assert(power.nodeResults().size()==ground.nodeResults().size());\n"
5537                       "    }\n"
5538                       "};");
5539         const Token *callfunc = Token::findsimplematch(tokenizer.tokens(), "power . nodeResults ( ) . size ( ) ;");
5540         ASSERT_EQUALS("", errout.str());
5541         ASSERT_EQUALS(true, db != nullptr); // not null
5542         ASSERT_EQUALS(true, callfunc != nullptr); // not null
5543         ASSERT_EQUALS(true, callfunc && callfunc->tokAt(2)->function() && callfunc->tokAt(2)->function()->tokenDef->linenr() == 3);
5544     }
5545 
findFunction8()5546     void findFunction8() {
5547         GET_SYMBOL_DB("struct S {\n"
5548                       "    void f()   { }\n"
5549                       "    void f() & { }\n"
5550                       "    void f() &&{ }\n"
5551                       "    void f() const   { }\n"
5552                       "    void f() const & { }\n"
5553                       "    void f() const &&{ }\n"
5554                       "    void g()   ;\n"
5555                       "    void g() & ;\n"
5556                       "    void g() &&;\n"
5557                       "    void g() const   ;\n"
5558                       "    void g() const & ;\n"
5559                       "    void g() const &&;\n"
5560                       "};\n"
5561                       "void S::g()   { }\n"
5562                       "void S::g() & { }\n"
5563                       "void S::g() &&{ }\n"
5564                       "void S::g() const   { }\n"
5565                       "void S::g() const & { }\n"
5566                       "void S::g() const &&{ }");
5567         ASSERT_EQUALS("", errout.str());
5568 
5569         const Token *f = Token::findsimplematch(tokenizer.tokens(), "f ( ) {");
5570         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5571 
5572         f = Token::findsimplematch(tokenizer.tokens(), "f ( ) & {");
5573         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5574 
5575         f = Token::findsimplematch(tokenizer.tokens(), "f ( ) && {");
5576         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5577 
5578         f = Token::findsimplematch(tokenizer.tokens(), "f ( ) const {");
5579         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
5580 
5581         f = Token::findsimplematch(tokenizer.tokens(), "f ( ) const & {");
5582         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5583 
5584         f = Token::findsimplematch(tokenizer.tokens(), "f ( ) const && {");
5585         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
5586 
5587         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) {");
5588         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8 && f->function()->token->linenr() == 15);
5589 
5590         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) & {");
5591         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 9 && f->function()->token->linenr() == 16);
5592 
5593         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) && {");
5594         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 10 && f->function()->token->linenr() == 17);
5595 
5596         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) const {");
5597         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 11 && f->function()->token->linenr() == 18);
5598 
5599         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) const & {");
5600         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 12 && f->function()->token->linenr() == 19);
5601 
5602         f = Token::findsimplematch(tokenizer.tokens(), "g ( ) const && {");
5603         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 13 && f->function()->token->linenr() == 20);
5604 
5605         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) {");
5606         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 8 && f->tokAt(2)->function()->token->linenr() == 15);
5607 
5608         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) & {");
5609         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 9 && f->tokAt(2)->function()->token->linenr() == 16);
5610 
5611         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) && {");
5612         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 10 && f->tokAt(2)->function()->token->linenr() == 17);
5613 
5614         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) const {");
5615         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 11 && f->tokAt(2)->function()->token->linenr() == 18);
5616 
5617         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) const & {");
5618         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 12 && f->tokAt(2)->function()->token->linenr() == 19);
5619 
5620         f = Token::findsimplematch(tokenizer.tokens(), "S :: g ( ) const && {");
5621         ASSERT_EQUALS(true, db && f && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 13 && f->tokAt(2)->function()->token->linenr() == 20);
5622     }
5623 
findFunction9()5624     void findFunction9() {
5625         GET_SYMBOL_DB("struct Fred {\n"
5626                       "    void foo(const int * p);\n"
5627                       "};\n"
5628                       "void Fred::foo(const int * const p) { }");
5629         ASSERT_EQUALS("", errout.str());
5630 
5631         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( const int * const p ) {");
5632         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5633     }
5634 
findFunction10()5635     void findFunction10() { // #7673
5636         GET_SYMBOL_DB("struct Fred {\n"
5637                       "    void foo(const int * p);\n"
5638                       "};\n"
5639                       "void Fred::foo(const int p []) { }");
5640         ASSERT_EQUALS("", errout.str());
5641 
5642         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( const int p [ ] ) {");
5643         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5644     }
5645 
findFunction11()5646     void findFunction11() {
5647         GET_SYMBOL_DB("class Fred : public QObject {\n"
5648                       "    Q_OBJECT\n"
5649                       "private slots:\n"
5650                       "    void foo();\n"
5651                       "};\n"
5652                       "void Fred::foo() { }");
5653         ASSERT_EQUALS("", errout.str());
5654 
5655         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( ) {");
5656         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5657     }
5658 
findFunction12()5659     void findFunction12() {
5660         GET_SYMBOL_DB("void foo(std::string a) { }\n"
5661                       "void foo(long long a) { }\n"
5662                       "void func(char* cp) {\n"
5663                       "    foo(0);\n"
5664                       "    foo(0L);\n"
5665                       "    foo(0.f);\n"
5666                       "    foo(bar());\n"
5667                       "    foo(cp);\n"
5668                       "    foo(\"\");\n"
5669                       "}");
5670 
5671         ASSERT_EQUALS("", errout.str());
5672 
5673         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0 ) ;");
5674         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5675 
5676         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0L ) ;");
5677         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5678 
5679         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0.f ) ;");
5680         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5681 
5682         f = Token::findsimplematch(tokenizer.tokens(), "foo ( bar ( ) ) ;");
5683         ASSERT_EQUALS(true, f && f->function() == nullptr);
5684 
5685         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;");
5686         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 1);
5687 
5688         f = Token::findsimplematch(tokenizer.tokens(), "foo ( \"\" ) ;");
5689         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 1);
5690     }
5691 
findFunction13()5692     void findFunction13() {
5693         GET_SYMBOL_DB("void foo(std::string a) { }\n"
5694                       "void foo(double a) { }\n"
5695                       "void foo(long long a) { }\n"
5696                       "void foo(int* a) { }\n"
5697                       "void foo(void* a) { }\n"
5698                       "void func(int i, const float f, int* ip, float* fp, char* cp) {\n"
5699                       "    foo(0);\n"
5700                       "    foo(0L);\n"
5701                       "    foo(0.f);\n"
5702                       "    foo(false);\n"
5703                       "    foo(bar());\n"
5704                       "    foo(i);\n"
5705                       "    foo(f);\n"
5706                       "    foo(&i);\n"
5707                       "    foo(&f);\n"
5708                       "    foo(ip);\n"
5709                       "    foo(fp);\n"
5710                       "    foo(cp);\n"
5711                       "    foo(\"\");\n"
5712                       "}");
5713 
5714         ASSERT_EQUALS("", errout.str());
5715 
5716         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0 ) ;");
5717         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5718 
5719         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0L ) ;");
5720         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5721 
5722         f = Token::findsimplematch(tokenizer.tokens(), "foo ( 0.f ) ;");
5723         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5724 
5725         f = Token::findsimplematch(tokenizer.tokens(), "foo ( false ) ;");
5726         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5727 
5728         f = Token::findsimplematch(tokenizer.tokens(), "foo ( bar ( ) ) ;");
5729         ASSERT_EQUALS(true, f && f->function() == nullptr);
5730 
5731         f = Token::findsimplematch(tokenizer.tokens(), "foo ( i ) ;");
5732         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5733 
5734         f = Token::findsimplematch(tokenizer.tokens(), "foo ( f ) ;");
5735         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5736 
5737         f = Token::findsimplematch(tokenizer.tokens(), "foo ( & i ) ;");
5738         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5739 
5740         f = Token::findsimplematch(tokenizer.tokens(), "foo ( & f ) ;");
5741         ASSERT_EQUALS(true, f && f->function() == nullptr);
5742 
5743         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ip ) ;");
5744         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5745 
5746         f = Token::findsimplematch(tokenizer.tokens(), "foo ( fp ) ;");
5747         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5);
5748 
5749         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;");
5750         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5);
5751 
5752         f = Token::findsimplematch(tokenizer.tokens(), "foo ( \"\" ) ;");
5753         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 1);
5754     }
5755 
findFunction14()5756     void findFunction14() {
5757         GET_SYMBOL_DB("void foo(int* a) { }\n"
5758                       "void foo(const int* a) { }\n"
5759                       "void foo(void* a) { }\n"
5760                       "void foo(const float a) { }\n"
5761                       "void foo(bool a) { }\n"
5762                       "void foo2(Foo* a) { }\n"
5763                       "void foo2(Foo a) { }\n"
5764                       "void func(int* ip, const int* cip, const char* ccp, char* cp, float f, bool b) {\n"
5765                       "    foo(ip);\n"
5766                       "    foo(cip);\n"
5767                       "    foo(cp);\n"
5768                       "    foo(ccp);\n"
5769                       "    foo(f);\n"
5770                       "    foo(b);\n"
5771                       "    foo2(0);\n"
5772                       "    foo2(nullptr);\n"
5773                       "    foo2(NULL);\n"
5774                       "}");
5775 
5776         ASSERT_EQUALS("", errout.str());
5777 
5778         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( ip ) ;");
5779         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
5780 
5781         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cip ) ;");
5782         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5783 
5784         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;");
5785         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5786 
5787         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ccp ) ;");
5788         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5);
5789 
5790         f = Token::findsimplematch(tokenizer.tokens(), "foo ( f ) ;");
5791         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5792 
5793         f = Token::findsimplematch(tokenizer.tokens(), "foo ( b ) ;");
5794         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5);
5795 
5796         f = Token::findsimplematch(tokenizer.tokens(), "foo2 ( 0 ) ;");
5797         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 6);
5798 
5799         f = Token::findsimplematch(tokenizer.tokens(), "foo2 ( nullptr ) ;");
5800         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 6);
5801 
5802         f = Token::findsimplematch(tokenizer.tokens(), "foo2 ( NULL ) ;");
5803         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 6);
5804     }
5805 
findFunction15()5806     void findFunction15() {
5807         GET_SYMBOL_DB("void foo1(int, char* a) { }\n"
5808                       "void foo1(int, char a) { }\n"
5809                       "void foo1(int, wchar_t a) { }\n"
5810                       "void foo1(int, char16_t a) { }\n"
5811                       "void foo2(int, float a) { }\n"
5812                       "void foo2(int, wchar_t a) { }\n"
5813                       "void foo3(int, float a) { }\n"
5814                       "void foo3(int, char a) { }\n"
5815                       "void func() {\n"
5816                       "    foo1(1, 'c');\n"
5817                       "    foo1(2, L'c');\n"
5818                       "    foo1(3, u'c');\n"
5819                       "    foo2(4, 'c');\n"
5820                       "    foo2(5, L'c');\n"
5821                       "    foo3(6, 'c');\n"
5822                       "    foo3(7, L'c');\n"
5823                       "}");
5824 
5825         ASSERT_EQUALS("", errout.str());
5826 
5827         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo1 ( 1");
5828         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5829 
5830         f = Token::findsimplematch(tokenizer.tokens(), "foo1 ( 2");
5831         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5832 
5833         f = Token::findsimplematch(tokenizer.tokens(), "foo1 ( 3");
5834         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
5835 
5836         f = Token::findsimplematch(tokenizer.tokens(), "foo2 ( 4");
5837         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5838 
5839         f = Token::findsimplematch(tokenizer.tokens(), "foo2 ( 5");
5840         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
5841 
5842         f = Token::findsimplematch(tokenizer.tokens(), "foo3 ( 6");
5843         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5844 
5845         // Error: ambiguous function call
5846         //f = Token::findsimplematch(tokenizer.tokens(), "foo3 ( 7");
5847         //ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
5848     }
5849 
findFunction16()5850     void findFunction16() {
5851         GET_SYMBOL_DB("struct C { int i; static int si; float f; int* ip; float* fp};\n"
5852                       "void foo(float a) { }\n"
5853                       "void foo(int a) { }\n"
5854                       "void foo(int* a) { }\n"
5855                       "void func(C c, C* cp) {\n"
5856                       "    foo(c.i);\n"
5857                       "    foo(cp->i);\n"
5858                       "    foo(c.f);\n"
5859                       "    foo(c.si);\n"
5860                       "    foo(C::si);\n"
5861                       "    foo(c.ip);\n"
5862                       "    foo(c.fp);\n"
5863                       "}");
5864 
5865         ASSERT_EQUALS("", errout.str());
5866 
5867         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( c . i ) ;");
5868         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3);
5869 
5870         f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp . i ) ;");
5871         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5872 
5873         f = Token::findsimplematch(tokenizer.tokens(), "foo ( c . f ) ;");
5874         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5875 
5876         f = Token::findsimplematch(tokenizer.tokens(), "foo ( c . si ) ;");
5877         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5878 
5879         f = Token::findsimplematch(tokenizer.tokens(), "foo ( C :: si ) ;");
5880         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5881 
5882         f = Token::findsimplematch(tokenizer.tokens(), "foo ( c . ip ) ;");
5883         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5884 
5885         f = Token::findsimplematch(tokenizer.tokens(), "foo ( c . fp ) ;");
5886         ASSERT_EQUALS(true, f && f->function() == nullptr);
5887     }
5888 
findFunction17()5889     void findFunction17() {
5890         GET_SYMBOL_DB("void foo(int a) { }\n"
5891                       "void foo(float a) { }\n"
5892                       "void foo(void* a) { }\n"
5893                       "void foo(bool a) { }\n"
5894                       "void func(int i, float f, bool b) {\n"
5895                       "    foo(i + i);\n"
5896                       "    foo(f + f);\n"
5897                       "    foo(!b);\n"
5898                       "    foo(i > 0);\n"
5899                       "    foo(f + i);\n"
5900                       "}");
5901 
5902         ASSERT_EQUALS("", errout.str());
5903 
5904         const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( i + i ) ;");
5905         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
5906 
5907         f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + f ) ;");
5908         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5909 
5910         f = Token::findsimplematch(tokenizer.tokens(), "foo ( ! b ) ;");
5911         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5912 
5913         f = Token::findsimplematch(tokenizer.tokens(), "foo ( i > 0 ) ;");
5914         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4);
5915 
5916         f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + i ) ;");
5917         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2);
5918     }
5919 
findFunction18()5920     void findFunction18() {
5921         GET_SYMBOL_DB("class Fred {\n"
5922                       "    void f(int i) { }\n"
5923                       "    void f(float f) const { }\n"
5924                       "    void a() { f(1); }\n"
5925                       "    void b() { f(1.f); }\n"
5926                       "};");
5927 
5928         ASSERT_EQUALS("", errout.str());
5929 
5930         const Token *f = Token::findsimplematch(tokenizer.tokens(), "f ( 1 ) ;");
5931         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
5932 
5933         f = Token::findsimplematch(tokenizer.tokens(), "f ( 1.f ) ;");
5934         ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
5935     }
5936 
findFunction19()5937     void findFunction19() {
5938         GET_SYMBOL_DB("class Fred {\n"
5939                       "    enum E1 { e1 };\n"
5940                       "    enum class E2 : unsigned short { e2 };\n"
5941                       "    bool               get(bool x) { return x; }\n"
5942                       "    char               get(char x) { return x; }\n"
5943                       "    short              get(short x) { return x; }\n"
5944                       "    int                get(int x) { return x; }\n"
5945                       "    long               get(long x) { return x; }\n"
5946                       "    long long          get(long long x) { return x; }\n"
5947                       "    unsigned char      get(unsigned char x) { return x; }\n"
5948                       "    signed char        get(signed char x) { return x; }\n"
5949                       "    unsigned short     get(unsigned short x) { return x; }\n"
5950                       "    unsigned int       get(unsigned int x) { return x; }\n"
5951                       "    unsigned long      get(unsigned long x) { return x; }\n"
5952                       "    unsigned long long get(unsigned long long x) { return x; }\n"
5953                       "    E1                 get(E1 x) { return x; }\n"
5954                       "    E2                 get(E2 x) { return x; }\n"
5955                       "    void foo() {\n"
5956                       "        bool               v1  = true;   v1  = get(get(v1));\n"
5957                       "        char               v2  = '1';    v2  = get(get(v2));\n"
5958                       "        short              v3  = 1;      v3  = get(get(v3));\n"
5959                       "        int                v4  = 1;      v4  = get(get(v4));\n"
5960                       "        long               v5  = 1;      v5  = get(get(v5));\n"
5961                       "        long long          v6  = 1;      v6  = get(get(v6));\n"
5962                       "        unsigned char      v7  = '1';    v7  = get(get(v7));\n"
5963                       "        signed char        v8  = '1';    v8  = get(get(v8));\n"
5964                       "        unsigned short     v9  = 1;      v9  = get(get(v9));\n"
5965                       "        unsigned int       v10 = 1;      v10 = get(get(v10));\n"
5966                       "        unsigned long      v11 = 1;      v11 = get(get(v11));\n"
5967                       "        unsigned long long v12 = 1;      v12 = get(get(v12));\n"
5968                       "        E1                 v13 = e1;     v13 = get(get(v13));\n"
5969                       "        E2                 v14 = E2::e2; v14 = get(get(v14));\n"
5970                       "    }\n"
5971                       "};");
5972 
5973         ASSERT_EQUALS("", errout.str());
5974         ASSERT(db);
5975 
5976         const Token *f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v1 ) ) ;");
5977         ASSERT(f);
5978         ASSERT(f->function());
5979         ASSERT_EQUALS(4, f->function()->tokenDef->linenr());
5980 
5981         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v2 ) ) ;");
5982         ASSERT(f);
5983         ASSERT(f->function());
5984         ASSERT_EQUALS(5, f->function()->tokenDef->linenr());
5985 
5986         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v3 ) ) ;");
5987         ASSERT(f);
5988         ASSERT(f->function());
5989         ASSERT_EQUALS(6, f->function()->tokenDef->linenr());
5990 
5991         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v4 ) ) ;");
5992         ASSERT(f);
5993         ASSERT(f->function());
5994         ASSERT_EQUALS(7, f->function()->tokenDef->linenr());
5995 
5996         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v5 ) ) ;");
5997         ASSERT(f);
5998         ASSERT(f->function());
5999         ASSERT_EQUALS(8, f->function()->tokenDef->linenr());
6000 
6001         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v6 ) ) ;");
6002         ASSERT(f);
6003         ASSERT(f->function());
6004         ASSERT_EQUALS(9, f->function()->tokenDef->linenr());
6005 
6006         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v7 ) ) ;");
6007         ASSERT(f);
6008         ASSERT(f->function());
6009         if (std::numeric_limits<char>::is_signed) {
6010             ASSERT_EQUALS(10, f->function()->tokenDef->linenr());
6011         } else {
6012             ASSERT_EQUALS(5, f->function()->tokenDef->linenr());
6013         }
6014 
6015         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v8 ) ) ;");
6016         ASSERT(f);
6017         ASSERT(f->function());
6018         if (std::numeric_limits<char>::is_signed) {
6019             ASSERT_EQUALS(5, f->function()->tokenDef->linenr());
6020         } else {
6021             ASSERT_EQUALS(11, f->function()->tokenDef->linenr());
6022         }
6023 
6024         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v9 ) ) ;");
6025         ASSERT(f);
6026         ASSERT(f->function());
6027         ASSERT_EQUALS(12, f->function()->tokenDef->linenr());
6028 
6029         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v10 ) ) ;");
6030         ASSERT(f);
6031         ASSERT(f->function());
6032         ASSERT_EQUALS(13, f->function()->tokenDef->linenr());
6033 
6034         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v11 ) ) ;");
6035         ASSERT(f);
6036         ASSERT(f->function());
6037         ASSERT_EQUALS(14, f->function()->tokenDef->linenr());
6038 
6039         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v12 ) ) ;");
6040         ASSERT(f);
6041         ASSERT(f->function());
6042         ASSERT_EQUALS(15, f->function()->tokenDef->linenr());
6043 
6044         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v13 ) ) ;");
6045         ASSERT(f);
6046         ASSERT(f->function());
6047         ASSERT_EQUALS(16, f->function()->tokenDef->linenr());
6048 
6049         f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v14 ) ) ;");
6050         ASSERT(f);
6051         ASSERT(f->function());
6052         ASSERT_EQUALS(17, f->function()->tokenDef->linenr());
6053     }
6054 
findFunction20()6055     void findFunction20() { // # 8280
6056         GET_SYMBOL_DB("class Foo {\n"
6057                       "public:\n"
6058                       "    Foo() : _x(0), _y(0) {}\n"
6059                       "    Foo(const Foo& f) {\n"
6060                       "        copy(&f);\n"
6061                       "    }\n"
6062                       "    void copy(const Foo* f) {\n"
6063                       "        _x=f->_x;\n"
6064                       "        copy(*f);\n"
6065                       "    }\n"
6066                       "private:\n"
6067                       "    void copy(const Foo& f) {\n"
6068                       "        _y=f._y;\n"
6069                       "    }\n"
6070                       "    int _x;\n"
6071                       "    int _y;\n"
6072                       "};");
6073 
6074         ASSERT_EQUALS("", errout.str());
6075 
6076         const Token *f = Token::findsimplematch(tokenizer.tokens(), "copy ( & f ) ;");
6077         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
6078 
6079         f = Token::findsimplematch(tokenizer.tokens(), "copy ( * f ) ;");
6080         ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 12);
6081     }
6082 
findFunction21()6083     void findFunction21() { // # 8558
6084         GET_SYMBOL_DB("struct foo {\n"
6085                       "    int GetThing( ) const { return m_thing; }\n"
6086                       "    int* GetThing( ) { return &m_thing; }\n"
6087                       "};\n"
6088                       "\n"
6089                       "void f(foo *myFoo) {\n"
6090                       "    int* myThing = myFoo->GetThing();\n"
6091                       "}");
6092 
6093         ASSERT(db != nullptr);
6094 
6095         const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "myFoo . GetThing ( ) ;");
6096 
6097         const Function *f = tok1 && tok1->tokAt(2) ? tok1->tokAt(2)->function() : nullptr;
6098         ASSERT(f != nullptr);
6099         ASSERT_EQUALS(true, f && !f->isConst());
6100     }
6101 
findFunction22()6102     void findFunction22() { // # 8558
6103         GET_SYMBOL_DB("struct foo {\n"
6104                       "    int GetThing( ) const { return m_thing; }\n"
6105                       "    int* GetThing( ) { return &m_thing; }\n"
6106                       "};\n"
6107                       "\n"
6108                       "void f(const foo *myFoo) {\n"
6109                       "    int* myThing = myFoo->GetThing();\n"
6110                       "}");
6111 
6112         ASSERT(db != nullptr);
6113 
6114         const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), ". GetThing ( ) ;")->next();
6115 
6116         const Function *f = tok1 ? tok1->function() : nullptr;
6117         ASSERT(f != nullptr);
6118         ASSERT_EQUALS(true, f && f->isConst());
6119     }
6120 
findFunction23()6121     void findFunction23() { // # 8558
6122         GET_SYMBOL_DB("struct foo {\n"
6123                       "    int GetThing( ) const { return m_thing; }\n"
6124                       "    int* GetThing( ) { return &m_thing; }\n"
6125                       "};\n"
6126                       "\n"
6127                       "void f(foo *myFoo) {\n"
6128                       "    int* myThing = ((const foo *)myFoo)->GetThing();\n"
6129                       "}");
6130 
6131         ASSERT(db != nullptr);
6132 
6133         const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), ". GetThing ( ) ;")->next();
6134 
6135         const Function *f = tok1 ? tok1->function() : nullptr;
6136         ASSERT(f != nullptr);
6137         ASSERT_EQUALS(true, f && f->isConst());
6138     }
6139 
findFunction24()6140     void findFunction24() { // smart pointers
6141         GET_SYMBOL_DB("struct foo {\n"
6142                       "  void dostuff();\n"
6143                       "}\n"
6144                       "\n"
6145                       "void f(std::shared_ptr<foo> p) {\n"
6146                       "  p->dostuff();\n"
6147                       "}");
6148         ASSERT(db != nullptr);
6149         const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), ". dostuff ( ) ;")->next();
6150         ASSERT(tok1->function());
6151     }
6152 
findFunction25()6153     void findFunction25() { // std::vector<std::shared_ptr<Fred>>
6154         GET_SYMBOL_DB("struct foo {\n"
6155                       "  void dostuff();\n"
6156                       "}\n"
6157                       "\n"
6158                       "void f1(std::vector<std::shared_ptr<foo>> v)\n"
6159                       "{\n"
6160                       "    for (auto p : v)\n"
6161                       "    {\n"
6162                       "        p->dostuff();\n"
6163                       "    }\n"
6164                       "}");
6165         ASSERT(db != nullptr);
6166         const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), ". dostuff ( ) ;")->next();
6167         ASSERT(tok1->function());
6168     }
6169 
findFunction26()6170     void findFunction26() {
6171         GET_SYMBOL_DB("void dostuff(const int *p) {}\n"
6172                       "void dostuff(float) {}\n"
6173                       "void f(int *p) {\n"
6174                       "  dostuff(p);\n"
6175                       "}");
6176         ASSERT(db != nullptr);
6177         const Token *dostuff1 = Token::findsimplematch(tokenizer.tokens(), "dostuff ( p ) ;");
6178         ASSERT(dostuff1->function());
6179         ASSERT(dostuff1->function() && dostuff1->function()->token);
6180         ASSERT(dostuff1->function() && dostuff1->function()->token && dostuff1->function()->token->linenr() == 1);
6181     }
6182 
findFunction27()6183     void findFunction27() {
6184         GET_SYMBOL_DB("namespace { void a(int); }\n"
6185                       "void f() { a(9); }");
6186         const Token *a = Token::findsimplematch(tokenizer.tokens(), "a ( 9 )");
6187         ASSERT(a);
6188         ASSERT(a->function());
6189     }
6190 
findFunction28()6191     void findFunction28() {
6192         GET_SYMBOL_DB("namespace { void a(int); }\n"
6193                       "struct S {\n"
6194                       "  void foo() { a(7); }\n"
6195                       "  void a(int);\n"
6196                       "};");
6197         const Token *a = Token::findsimplematch(tokenizer.tokens(), "a ( 7 )");
6198         ASSERT(a);
6199         ASSERT(a->function());
6200         ASSERT(a->function()->token);
6201         ASSERT_EQUALS(4, a->function()->token->linenr());
6202     }
6203 
findFunction29()6204     void findFunction29() {
6205         GET_SYMBOL_DB("struct A {\n"
6206                       "    int foo() const;\n"
6207                       "};\n"
6208                       "\n"
6209                       "struct B {\n"
6210                       "    A a;\n"
6211                       "};\n"
6212                       "\n"
6213                       "typedef std::shared_ptr<B> BPtr;\n"
6214                       "\n"
6215                       "void bar(BPtr b) {\n"
6216                       "    int x = b->a.foo();\n"
6217                       "}");
6218         const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( ) ;");
6219         ASSERT(foo);
6220         ASSERT(foo->function());
6221         ASSERT(foo->function()->token);
6222         ASSERT_EQUALS(2, foo->function()->token->linenr());
6223     }
6224 
findFunction30()6225     void findFunction30() {
6226         GET_SYMBOL_DB("struct A;\n"
6227                       "void foo(std::shared_ptr<A> ptr) {\n"
6228                       "    int x = ptr->bar();\n"
6229                       "}");
6230         const Token *bar = Token::findsimplematch(tokenizer.tokens(), "bar ( ) ;");
6231         ASSERT(bar);
6232         ASSERT(!bar->function());
6233     }
6234 
findFunction31()6235     void findFunction31() {
6236         GET_SYMBOL_DB("void foo(bool);\n"
6237                       "void foo(std::string s);\n"
6238                       "void bar() { foo(\"123\"); }");
6239         const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( \"123\" ) ;");
6240         ASSERT(foo);
6241         ASSERT(foo->function());
6242         ASSERT(foo->function()->tokenDef);
6243         ASSERT_EQUALS(1, foo->function()->tokenDef->linenr());
6244     }
6245 
findFunction32()6246     void findFunction32() {
6247         GET_SYMBOL_DB_C("void foo(char *p);\n"
6248                         "void bar() { foo(\"123\"); }");
6249         (void)db;
6250         const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( \"123\" ) ;");
6251         ASSERT(foo);
6252         ASSERT(foo->function());
6253         ASSERT(foo->function()->tokenDef);
6254         ASSERT_EQUALS(1, foo->function()->tokenDef->linenr());
6255     }
6256 
findFunction33()6257     void findFunction33() {
6258         {
6259             GET_SYMBOL_DB("class Base {\n"
6260                           "    int i{};\n"
6261                           "public:\n"
6262                           "    void foo(...) const { bar(); }\n"
6263                           "    int bar() const { return i; }\n"
6264                           "};\n"
6265                           "class Derived : public Base {\n"
6266                           "public:\n"
6267                           "    void doIt() const {\n"
6268                           "        foo();\n"
6269                           "    }\n"
6270                           "};");
6271             (void)db;
6272             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( ) ;");
6273             ASSERT(foo);
6274             ASSERT(foo->function());
6275             ASSERT(foo->function()->tokenDef);
6276             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6277         }
6278         {
6279             GET_SYMBOL_DB("class Base {\n"
6280                           "    int i{};\n"
6281                           "public:\n"
6282                           "    void foo(...) const { bar(); }\n"
6283                           "    int bar() const { return i; }\n"
6284                           "};\n"
6285                           "class Derived : public Base {\n"
6286                           "public:\n"
6287                           "    void doIt() const {\n"
6288                           "        foo(1);\n"
6289                           "    }\n"
6290                           "};");
6291             (void)db;
6292             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 ) ;");
6293             ASSERT(foo);
6294             ASSERT(foo->function());
6295             ASSERT(foo->function()->tokenDef);
6296             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6297         }
6298         {
6299             GET_SYMBOL_DB("class Base {\n"
6300                           "    int i{};\n"
6301                           "public:\n"
6302                           "    void foo(...) const { bar(); }\n"
6303                           "    int bar() const { return i; }\n"
6304                           "};\n"
6305                           "class Derived : public Base {\n"
6306                           "public:\n"
6307                           "    void doIt() const {\n"
6308                           "        foo(1,2);\n"
6309                           "    }\n"
6310                           "};");
6311             (void)db;
6312             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 ) ;");
6313             ASSERT(foo);
6314             ASSERT(foo->function());
6315             ASSERT(foo->function()->tokenDef);
6316             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6317         }
6318         {
6319             GET_SYMBOL_DB("class Base {\n"
6320                           "    int i{};\n"
6321                           "public:\n"
6322                           "    void foo(int, ...) const { bar(); }\n"
6323                           "    int bar() const { return i; }\n"
6324                           "};\n"
6325                           "class Derived : public Base {\n"
6326                           "public:\n"
6327                           "    void doIt() const {\n"
6328                           "        foo(1);\n"
6329                           "    }\n"
6330                           "};");
6331             (void)db;
6332             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 ) ;");
6333             ASSERT(foo);
6334             ASSERT(foo->function());
6335             ASSERT(foo->function()->tokenDef);
6336             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6337         }
6338         {
6339             GET_SYMBOL_DB("class Base {\n"
6340                           "    int i{};\n"
6341                           "public:\n"
6342                           "    void foo(int,...) const { bar(); }\n"
6343                           "    int bar() const { return i; }\n"
6344                           "};\n"
6345                           "class Derived : public Base {\n"
6346                           "public:\n"
6347                           "    void doIt() const {\n"
6348                           "        foo(1,2);\n"
6349                           "    }\n"
6350                           "};");
6351             (void)db;
6352             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 ) ;");
6353             ASSERT(foo);
6354             ASSERT(foo->function());
6355             ASSERT(foo->function()->tokenDef);
6356             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6357         }
6358         {
6359             GET_SYMBOL_DB("class Base {\n"
6360                           "    int i{};\n"
6361                           "public:\n"
6362                           "    void foo(int,...) const { bar(); }\n"
6363                           "    int bar() const { return i; }\n"
6364                           "};\n"
6365                           "class Derived : public Base {\n"
6366                           "public:\n"
6367                           "    void doIt() const {\n"
6368                           "        foo(1, 2, 3);\n"
6369                           "    }\n"
6370                           "};");
6371             (void)db;
6372             const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 , 3 ) ;");
6373             ASSERT(foo);
6374             ASSERT(foo->function());
6375             ASSERT(foo->function()->tokenDef);
6376             ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6377         }
6378     }
6379 
findFunction34()6380     void findFunction34() {
6381         GET_SYMBOL_DB("namespace cppcheck {\n"
6382                       "    class Platform {\n"
6383                       "    public:\n"
6384                       "        enum PlatformType { Unspecified };\n"
6385                       "    };\n"
6386                       "}\n"
6387                       "class ImportProject {\n"
6388                       "    void selectOneVsConfig(cppcheck::Platform::PlatformType);\n"
6389                       "};\n"
6390                       "class Settings : public cppcheck::Platform { };\n"
6391                       "void ImportProject::selectOneVsConfig(Settings::PlatformType) { }");
6392         (void)db;
6393         const Token *foo = Token::findsimplematch(tokenizer.tokens(), "selectOneVsConfig ( Settings :: PlatformType ) { }");
6394         ASSERT(foo);
6395         ASSERT(foo->function());
6396         ASSERT(foo->function()->tokenDef);
6397         ASSERT_EQUALS(8, foo->function()->tokenDef->linenr());
6398     }
6399 
findFunction35()6400     void findFunction35() {
6401         GET_SYMBOL_DB("namespace clangimport {\n"
6402                       "    class AstNode {\n"
6403                       "    public:\n"
6404                       "        AstNode();\n"
6405                       "        void createTokens();\n"
6406                       "    };\n"
6407                       "}\n"
6408                       "::clangimport::AstNode::AstNode() { }\n"
6409                       "void ::clangimport::AstNode::createTokens() { }");
6410         (void)db;
6411         const Token *foo = Token::findsimplematch(tokenizer.tokens(), "AstNode ( ) { }");
6412         ASSERT(foo);
6413         ASSERT(foo->function());
6414         ASSERT(foo->function()->tokenDef);
6415         ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
6416         foo = Token::findsimplematch(tokenizer.tokens(), "createTokens ( ) { }");
6417         ASSERT(foo);
6418         ASSERT(foo->function());
6419         ASSERT(foo->function()->tokenDef);
6420         ASSERT_EQUALS(5, foo->function()->tokenDef->linenr());
6421     }
6422 
findFunction36()6423     void findFunction36() { // #10122
6424         GET_SYMBOL_DB("namespace external {\n"
6425                       "    enum class T { };\n"
6426                       "}\n"
6427                       "namespace ns {\n"
6428                       "    class A {\n"
6429                       "    public:\n"
6430                       "        void f(external::T);\n"
6431                       "    };\n"
6432                       "}\n"
6433                       "namespace ns {\n"
6434                       "    void A::f(external::T link_type) { }\n"
6435                       "}");
6436         ASSERT_EQUALS("", errout.str());
6437         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( external :: T link_type )");
6438         ASSERT(functok);
6439         ASSERT(functok->function());
6440         ASSERT(functok->function()->name() == "f");
6441         ASSERT_EQUALS(7, functok->function()->tokenDef->linenr());
6442     }
6443 
findFunction37()6444     void findFunction37() { // #10124
6445         GET_SYMBOL_DB("namespace ns {\n"
6446                       "    class V { };\n"
6447                       "}\n"
6448                       "class A {\n"
6449                       "public:\n"
6450                       "    void f(const ns::V&);\n"
6451                       "};\n"
6452                       "using ::ns::V;\n"
6453                       "void A::f(const V&) { }");
6454         ASSERT_EQUALS("", errout.str());
6455         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( const :: ns :: V & )");
6456         ASSERT(functok);
6457         ASSERT(functok->function());
6458         ASSERT(functok->function()->name() == "f");
6459         ASSERT_EQUALS(6, functok->function()->tokenDef->linenr());
6460     }
6461 
findFunction38()6462     void findFunction38() { // #10125
6463         GET_SYMBOL_DB("namespace ns {\n"
6464                       "    class V { };\n"
6465                       "    using Var = V;\n"
6466                       "}\n"
6467                       "class A {\n"
6468                       "    void f(const ns::Var&);\n"
6469                       "};\n"
6470                       "using ::ns::Var;\n"
6471                       "void A::f(const Var&) {}");
6472         ASSERT_EQUALS("", errout.str());
6473         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( const :: ns :: V & )");
6474         ASSERT(functok);
6475         ASSERT(functok->function());
6476         ASSERT(functok->function()->name() == "f");
6477         ASSERT_EQUALS(6, functok->function()->tokenDef->linenr());
6478     }
6479 
findFunction39()6480     void findFunction39() { // #10127
6481         GET_SYMBOL_DB("namespace external {\n"
6482                       "    class V {\n"
6483                       "    public:\n"
6484                       "        using I = int;\n"
6485                       "    };\n"
6486                       "}\n"
6487                       "class A {\n"
6488                       "    void f(external::V::I);\n"
6489                       "};\n"
6490                       "using ::external::V;\n"
6491                       "void A::f(V::I) {}");
6492         ASSERT_EQUALS("", errout.str());
6493         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "f ( int )");
6494         ASSERT(functok);
6495         ASSERT(functok->function());
6496         ASSERT(functok->function()->name() == "f");
6497         ASSERT_EQUALS(8, functok->function()->tokenDef->linenr());
6498     }
6499 
findFunction40()6500     void findFunction40() { // #10135
6501         GET_SYMBOL_DB("class E : public std::exception {\n"
6502                       "public:\n"
6503                       "    const char* what() const noexcept override;\n"
6504                       "};\n"
6505                       "const char* E::what() const noexcept {\n"
6506                       "    return nullptr;\n"
6507                       "}");
6508         ASSERT_EQUALS("", errout.str());
6509         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "what ( ) const noexcept {");
6510         ASSERT(functok);
6511         ASSERT(functok->function());
6512         ASSERT(functok->function()->name() == "what");
6513         ASSERT_EQUALS(3, functok->function()->tokenDef->linenr());
6514     }
6515 
findFunction41()6516     void findFunction41() { // #10202
6517         {
6518             GET_SYMBOL_DB("struct A {};\n"
6519                           "const int* g(const A&);\n"
6520                           "int* g(A&);\n"
6521                           "void f(A& x) {\n"
6522                           "    int* y = g(x);\n"
6523                           "    *y = 0;\n"
6524                           "}\n");
6525             ASSERT_EQUALS("", errout.str());
6526             const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( x )");
6527             ASSERT(functok);
6528             ASSERT(functok->function());
6529             ASSERT(functok->function()->name() == "g");
6530             ASSERT_EQUALS(3, functok->function()->tokenDef->linenr());
6531         }
6532         {
6533             GET_SYMBOL_DB("struct A {};\n"
6534                           "const int* g(const A&);\n"
6535                           "int* g(A&);\n"
6536                           "void f(const A& x) {\n"
6537                           "    int* y = g(x);\n"
6538                           "    *y = 0;\n"
6539                           "}\n");
6540             ASSERT_EQUALS("", errout.str());
6541             const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( x )");
6542             ASSERT(functok);
6543             ASSERT(functok->function());
6544             ASSERT(functok->function()->name() == "g");
6545             ASSERT_EQUALS(2, functok->function()->tokenDef->linenr());
6546         }
6547     }
6548 
findFunction42()6549     void findFunction42() {
6550         GET_SYMBOL_DB("void a(const std::string &, const std::string &);\n"
6551                       "void a(long, long);\n"
6552                       "void b() { a(true, false); }\n");
6553         ASSERT_EQUALS("", errout.str());
6554         const Token *functok = Token::findsimplematch(tokenizer.tokens(), "a ( true , false )");
6555         ASSERT(functok);
6556         ASSERT(functok->function());
6557         ASSERT(functok->function()->name() == "a");
6558         ASSERT_EQUALS(2, functok->function()->tokenDef->linenr());
6559     }
6560 
findFunction43()6561     void findFunction43() { // #10087
6562         {
6563             GET_SYMBOL_DB("struct A {};\n"
6564                           "const A* g(const std::string&);\n"
6565                           "const A& g(std::vector<A>::size_type i);\n"
6566                           "const A& f(std::vector<A>::size_type i) { return g(i); }\n");
6567             ASSERT_EQUALS("", errout.str());
6568             const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( i )");
6569             ASSERT(functok);
6570             ASSERT(functok->function());
6571             ASSERT(functok->function()->name() == "g");
6572             ASSERT_EQUALS(3, functok->function()->tokenDef->linenr());
6573         }
6574         {
6575             GET_SYMBOL_DB("struct A {};\n"
6576                           "const A& g(std::vector<A>::size_type i);\n"
6577                           "const A* g(const std::string&);\n"
6578                           "const A& f(std::vector<A>::size_type i) { return g(i); }\n");
6579             ASSERT_EQUALS("", errout.str());
6580             const Token *functok = Token::findsimplematch(tokenizer.tokens(), "g ( i )");
6581             ASSERT(functok);
6582             ASSERT(functok->function());
6583             ASSERT(functok->function()->name() == "g");
6584             ASSERT_EQUALS(2, functok->function()->tokenDef->linenr());
6585         }
6586     }
6587 
6588 
findFunctionContainer()6589     void findFunctionContainer() {
6590         {
6591             GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"
6592                           "void f(std::vector<int> v) {\n"
6593                           "  dostuff(v);\n"
6594                           "}");
6595             (void)db;
6596             const Token *dostuff = Token::findsimplematch(tokenizer.tokens(), "dostuff ( v ) ;");
6597             ASSERT(dostuff->function());
6598             ASSERT(dostuff->function() && dostuff->function()->tokenDef);
6599             ASSERT(dostuff->function() && dostuff->function()->tokenDef && dostuff->function()->tokenDef->linenr() == 1);
6600         }
6601         {
6602             GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"
6603                           "void dostuff(int *i);\n"
6604                           "void f(std::vector<char> v) {\n"
6605                           "  dostuff(v);\n"
6606                           "}");
6607             (void)db;
6608             const Token *dostuff = Token::findsimplematch(tokenizer.tokens(), "dostuff ( v ) ;");
6609             ASSERT(!dostuff->function());
6610         }
6611     }
6612 
findFunctionExternC()6613     void findFunctionExternC() {
6614         GET_SYMBOL_DB("extern \"C\" { void foo(int); }\n"
6615                       "void bar() {\n"
6616                       "    foo(42);\n"
6617                       "}");
6618         const Token *a = Token::findsimplematch(tokenizer.tokens(), "foo ( 42 )");
6619         ASSERT(a);
6620         ASSERT(a->function());
6621     }
6622 
findFunctionGlobalScope()6623     void findFunctionGlobalScope() {
6624         GET_SYMBOL_DB("struct S {\n"
6625                       "    void foo();\n"
6626                       "    int x;\n"
6627                       "};\n"
6628                       "\n"
6629                       "int bar(int x);\n"
6630                       "\n"
6631                       "void S::foo() {\n"
6632                       "    x = ::bar(x);\n"
6633                       "}");
6634         const Token *bar = Token::findsimplematch(tokenizer.tokens(), "bar ( x )");
6635         ASSERT(bar);
6636         ASSERT(bar->function());
6637     }
6638 
overloadedFunction1()6639     void overloadedFunction1() {
6640         GET_SYMBOL_DB("struct S {\n"
6641                       "    int operator()(int);\n"
6642                       "};\n"
6643                       "\n"
6644                       "void foo(S x) {\n"
6645                       "    x(123);\n"
6646                       "}");
6647         const Token *tok = Token::findsimplematch(tokenizer.tokens(), "x . operator() ( 123 )");
6648         ASSERT(tok);
6649         ASSERT(tok->tokAt(2)->function());
6650     }
6651 
valueTypeMatchParameter()6652     void valueTypeMatchParameter() {
6653         ValueType vt_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0);
6654         ValueType vt_const_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0, 1);
6655         ASSERT_EQUALS((int)ValueType::MatchResult::SAME, (int)ValueType::matchParameter(&vt_int, &vt_int));
6656         ASSERT_EQUALS((int)ValueType::MatchResult::SAME, (int)ValueType::matchParameter(&vt_const_int, &vt_int));
6657         ASSERT_EQUALS((int)ValueType::MatchResult::SAME, (int)ValueType::matchParameter(&vt_int, &vt_const_int));
6658 
6659         ValueType vt_char_pointer(ValueType::Sign::SIGNED, ValueType::Type::CHAR, 1);
6660         ValueType vt_void_pointer(ValueType::Sign::SIGNED, ValueType::Type::VOID, 1); // compatible
6661         ValueType vt_int_pointer(ValueType::Sign::SIGNED, ValueType::Type::INT, 1); // not compatible
6662         ASSERT_EQUALS((int)ValueType::MatchResult::FALLBACK1, (int)ValueType::matchParameter(&vt_char_pointer, &vt_void_pointer));
6663         ASSERT_EQUALS((int)ValueType::MatchResult::NOMATCH, (int)ValueType::matchParameter(&vt_char_pointer, &vt_int_pointer));
6664 
6665         ValueType vt_char_pointer2(ValueType::Sign::SIGNED, ValueType::Type::CHAR, 2);
6666         ASSERT_EQUALS((int)ValueType::MatchResult::FALLBACK1, (int)ValueType::matchParameter(&vt_char_pointer2, &vt_void_pointer));
6667 
6668         ValueType vt_const_float_pointer(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 1, 1);
6669         ValueType vt_long_long(ValueType::Sign::SIGNED, ValueType::Type::LONGLONG, 0, 0);
6670         ASSERT_EQUALS((int)ValueType::MatchResult::NOMATCH, (int)ValueType::matchParameter(&vt_const_float_pointer, &vt_long_long));
6671     }
6672 
6673 #define FUNC(x) do { \
6674         const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
6675         ASSERT_EQUALS(true, x != nullptr);                                  \
6676         ASSERT_EQUALS(true, x->isNoExcept()); \
6677 } while (false)
6678 
noexceptFunction1()6679     void noexceptFunction1() {
6680         GET_SYMBOL_DB("void func1() noexcept;\n"
6681                       "void func2() noexcept { }\n"
6682                       "void func3() noexcept(true);\n"
6683                       "void func4() noexcept(true) { }");
6684         ASSERT_EQUALS("", errout.str());
6685         ASSERT_EQUALS(true,  db != nullptr); // not null
6686 
6687         FUNC(func1);
6688         FUNC(func2);
6689         FUNC(func3);
6690         FUNC(func4);
6691     }
6692 
noexceptFunction2()6693     void noexceptFunction2() {
6694         GET_SYMBOL_DB("template <class T> void self_assign(T& t) noexcept(noexcept(t = t)) {t = t; }");
6695 
6696         ASSERT_EQUALS("", errout.str());
6697         ASSERT_EQUALS(true,  db != nullptr); // not null
6698 
6699         FUNC(self_assign);
6700     }
6701 
6702 #define CLASS_FUNC(x, y, z) do { \
6703         const Function *x = findFunctionByName(#x, y); \
6704         ASSERT_EQUALS(true, x != nullptr);             \
6705         ASSERT_EQUALS(z, x->isNoExcept()); \
6706 } while (false)
6707 
noexceptFunction3()6708     void noexceptFunction3() {
6709         GET_SYMBOL_DB("struct Fred {\n"
6710                       "    void func1() noexcept;\n"
6711                       "    void func2() noexcept { }\n"
6712                       "    void func3() noexcept(true);\n"
6713                       "    void func4() noexcept(true) { }\n"
6714                       "    void func5() const noexcept;\n"
6715                       "    void func6() const noexcept { }\n"
6716                       "    void func7() const noexcept(true);\n"
6717                       "    void func8() const noexcept(true) { }\n"
6718                       "    void func9() noexcept = 0;\n"
6719                       "    void func10() noexcept = 0;\n"
6720                       "    void func11() const noexcept(true) = 0;\n"
6721                       "    void func12() const noexcept(true) = 0;\n"
6722                       "    void func13() const noexcept(false) = 0;\n"
6723                       "};");
6724         ASSERT_EQUALS("", errout.str());
6725         ASSERT_EQUALS(true,  db != nullptr); // not null
6726 
6727         const Scope *fred = db->findScopeByName("Fred");
6728         ASSERT_EQUALS(true, fred != nullptr);
6729         CLASS_FUNC(func1, fred, true);
6730         CLASS_FUNC(func2, fred, true);
6731         CLASS_FUNC(func3, fred, true);
6732         CLASS_FUNC(func4, fred, true);
6733         CLASS_FUNC(func5, fred, true);
6734         CLASS_FUNC(func6, fred, true);
6735         CLASS_FUNC(func7, fred, true);
6736         CLASS_FUNC(func8, fred, true);
6737         CLASS_FUNC(func9, fred, true);
6738         CLASS_FUNC(func10, fred, true);
6739         CLASS_FUNC(func11, fred, true);
6740         CLASS_FUNC(func12, fred, true);
6741         CLASS_FUNC(func13, fred, false);
6742     }
6743 
noexceptFunction4()6744     void noexceptFunction4() {
6745         GET_SYMBOL_DB("class A {\n"
6746                       "public:\n"
6747                       "   A(A&& a) {\n"
6748                       "      throw std::runtime_error(\"err\");\n"
6749                       "   }\n"
6750                       "};\n"
6751                       "class B {\n"
6752                       "   A a;\n"
6753                       "   B(B&& b) noexcept\n"
6754                       "   :a(std::move(b.a)) { }\n"
6755                       "};");
6756         ASSERT_EQUALS("", errout.str());
6757         ASSERT(db != nullptr); // not null
6758         const Scope *b = db->findScopeByName("B");
6759         ASSERT(b != nullptr);
6760         CLASS_FUNC(B, b, true);
6761     }
6762 
6763 #define FUNC_THROW(x) do { \
6764         const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
6765         ASSERT_EQUALS(true, x != nullptr);                                  \
6766         ASSERT_EQUALS(true, x->isThrow()); \
6767 } while (false)
6768 
throwFunction1()6769     void throwFunction1() {
6770         GET_SYMBOL_DB("void func1() throw();\n"
6771                       "void func2() throw() { }\n"
6772                       "void func3() throw(int);\n"
6773                       "void func4() throw(int) { }");
6774         ASSERT_EQUALS("", errout.str());
6775         ASSERT(db != nullptr); // not null
6776 
6777         FUNC_THROW(func1);
6778         FUNC_THROW(func2);
6779         FUNC_THROW(func3);
6780         FUNC_THROW(func4);
6781     }
6782 
6783 #define CLASS_FUNC_THROW(x, y) do { \
6784         const Function *x = findFunctionByName(#x, y); \
6785         ASSERT_EQUALS(true, x != nullptr);             \
6786         ASSERT_EQUALS(true, x->isThrow()); \
6787 } while (false)
throwFunction2()6788     void throwFunction2() {
6789         GET_SYMBOL_DB("struct Fred {\n"
6790                       "    void func1() throw();\n"
6791                       "    void func2() throw() { }\n"
6792                       "    void func3() throw(int);\n"
6793                       "    void func4() throw(int) { }\n"
6794                       "    void func5() const throw();\n"
6795                       "    void func6() const throw() { }\n"
6796                       "    void func7() const throw(int);\n"
6797                       "    void func8() const throw(int) { }\n"
6798                       "    void func9() throw() = 0;\n"
6799                       "    void func10() throw(int) = 0;\n"
6800                       "    void func11() const throw() = 0;\n"
6801                       "    void func12() const throw(int) = 0;\n"
6802                       "};");
6803         ASSERT_EQUALS("", errout.str());
6804         ASSERT_EQUALS(true,  db != nullptr); // not null
6805 
6806         const Scope *fred = db->findScopeByName("Fred");
6807         ASSERT_EQUALS(true, fred != nullptr);
6808         CLASS_FUNC_THROW(func1, fred);
6809         CLASS_FUNC_THROW(func2, fred);
6810         CLASS_FUNC_THROW(func3, fred);
6811         CLASS_FUNC_THROW(func4, fred);
6812         CLASS_FUNC_THROW(func5, fred);
6813         CLASS_FUNC_THROW(func6, fred);
6814         CLASS_FUNC_THROW(func7, fred);
6815         CLASS_FUNC_THROW(func8, fred);
6816         CLASS_FUNC_THROW(func9, fred);
6817         CLASS_FUNC_THROW(func10, fred);
6818         CLASS_FUNC_THROW(func11, fred);
6819         CLASS_FUNC_THROW(func12, fred);
6820     }
6821 
nothrowAttributeFunction()6822     void nothrowAttributeFunction() {
6823         GET_SYMBOL_DB("void func() __attribute__((nothrow));\n"
6824                       "void func() { }");
6825         ASSERT_EQUALS("", errout.str());
6826         ASSERT_EQUALS(true,  db != nullptr); // not null
6827 
6828         const Function *func = findFunctionByName("func", &db->scopeList.front());
6829         ASSERT_EQUALS(true, func != nullptr);
6830         ASSERT_EQUALS(true, func->isAttributeNothrow());
6831     }
6832 
nothrowDeclspecFunction()6833     void nothrowDeclspecFunction() {
6834         GET_SYMBOL_DB("void __declspec(nothrow) func() { }");
6835         ASSERT_EQUALS("", errout.str());
6836         ASSERT_EQUALS(true,  db != nullptr); // not null
6837 
6838         const Function *func = findFunctionByName("func", &db->scopeList.front());
6839         ASSERT_EQUALS(true, func != nullptr);
6840         ASSERT_EQUALS(true, func->isAttributeNothrow());
6841     }
6842 
noreturnAttributeFunction()6843     void noreturnAttributeFunction() {
6844         GET_SYMBOL_DB("[[noreturn]] void func1();\n"
6845                       "void func1() { }\n"
6846                       "[[noreturn]] void func2();\n"
6847                       "[[noreturn]] void func3() { }\n"
6848                       "template <class T> [[noreturn]] void func4() { }");
6849         ASSERT_EQUALS("", errout.str());
6850         ASSERT_EQUALS(true,  db != nullptr); // not null
6851 
6852         const Function *func = findFunctionByName("func1", &db->scopeList.front());
6853         ASSERT_EQUALS(true, func != nullptr);
6854         ASSERT_EQUALS(true, func->isAttributeNoreturn());
6855 
6856         func = findFunctionByName("func2", &db->scopeList.front());
6857         ASSERT_EQUALS(true, func != nullptr);
6858         ASSERT_EQUALS(true, func->isAttributeNoreturn());
6859 
6860         func = findFunctionByName("func3", &db->scopeList.front());
6861         ASSERT_EQUALS(true, func != nullptr);
6862         ASSERT_EQUALS(true, func->isAttributeNoreturn());
6863 
6864         func = findFunctionByName("func4", &db->scopeList.front());
6865         ASSERT_EQUALS(true, func != nullptr);
6866         ASSERT_EQUALS(true, func->isAttributeNoreturn());
6867 
6868     }
6869 
nodiscardAttributeFunction()6870     void nodiscardAttributeFunction() {
6871         GET_SYMBOL_DB("[[nodiscard]] int func1();\n"
6872                       "int func1() { }\n"
6873                       "[[nodiscard]] int func2();\n"
6874                       "[[nodiscard]] int func3() { }\n"
6875                       "template <class T> [[nodiscard]] int func4() { }"
6876                       "std::pair<bool, char> [[nodiscard]] func5();\n"
6877                       "[[nodiscard]] std::pair<bool, char> func6();\n"
6878                       );
6879         ASSERT_EQUALS("", errout.str());
6880         ASSERT_EQUALS(true,  db != nullptr); // not null
6881 
6882         const Function *func = findFunctionByName("func1", &db->scopeList.front());
6883         ASSERT_EQUALS(true, func != nullptr);
6884         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6885 
6886         func = findFunctionByName("func2", &db->scopeList.front());
6887         ASSERT_EQUALS(true, func != nullptr);
6888         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6889 
6890         func = findFunctionByName("func3", &db->scopeList.front());
6891         ASSERT_EQUALS(true, func != nullptr);
6892         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6893 
6894         func = findFunctionByName("func4", &db->scopeList.front());
6895         ASSERT_EQUALS(true, func != nullptr);
6896         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6897 
6898         func = findFunctionByName("func5", &db->scopeList.front());
6899         ASSERT_EQUALS(true, func != nullptr);
6900         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6901 
6902         func = findFunctionByName("func6", &db->scopeList.front());
6903         ASSERT_EQUALS(true, func != nullptr);
6904         ASSERT_EQUALS(true, func->isAttributeNodiscard());
6905     }
6906 
varTypesIntegral()6907     void varTypesIntegral() {
6908         GET_SYMBOL_DB("void f() { bool b; char c; unsigned char uc; short s; unsigned short us; int i; unsigned u; unsigned int ui; long l; unsigned long ul; long long ll; }");
6909         const Variable *b = db->getVariableFromVarId(1);
6910         ASSERT(b != nullptr);
6911         ASSERT_EQUALS("b", b->nameToken()->str());
6912         ASSERT_EQUALS(false, b->isFloatingType());
6913 
6914         const Variable *c = db->getVariableFromVarId(2);
6915         ASSERT(c != nullptr);
6916         ASSERT_EQUALS("c", c->nameToken()->str());
6917         ASSERT_EQUALS(false, c->isFloatingType());
6918 
6919         const Variable *uc = db->getVariableFromVarId(3);
6920         ASSERT(uc != nullptr);
6921         ASSERT_EQUALS("uc", uc->nameToken()->str());
6922         ASSERT_EQUALS(false, uc->isFloatingType());
6923 
6924         const Variable *s = db->getVariableFromVarId(4);
6925         ASSERT(s != nullptr);
6926         ASSERT_EQUALS("s", s->nameToken()->str());
6927         ASSERT_EQUALS(false, s->isFloatingType());
6928 
6929         const Variable *us = db->getVariableFromVarId(5);
6930         ASSERT(us != nullptr);
6931         ASSERT_EQUALS("us", us->nameToken()->str());
6932         ASSERT_EQUALS(false, us->isFloatingType());
6933 
6934         const Variable *i = db->getVariableFromVarId(6);
6935         ASSERT(i != nullptr);
6936         ASSERT_EQUALS("i", i->nameToken()->str());
6937         ASSERT_EQUALS(false, i->isFloatingType());
6938 
6939         const Variable *u = db->getVariableFromVarId(7);
6940         ASSERT(u != nullptr);
6941         ASSERT_EQUALS("u", u->nameToken()->str());
6942         ASSERT_EQUALS(false, u->isFloatingType());
6943 
6944         const Variable *ui = db->getVariableFromVarId(8);
6945         ASSERT(ui != nullptr);
6946         ASSERT_EQUALS("ui", ui->nameToken()->str());
6947         ASSERT_EQUALS(false, ui->isFloatingType());
6948 
6949         const Variable *l = db->getVariableFromVarId(9);
6950         ASSERT(l != nullptr);
6951         ASSERT_EQUALS("l", l->nameToken()->str());
6952         ASSERT_EQUALS(false, l->isFloatingType());
6953 
6954         const Variable *ul = db->getVariableFromVarId(10);
6955         ASSERT(ul != nullptr);
6956         ASSERT_EQUALS("ul", ul->nameToken()->str());
6957         ASSERT_EQUALS(false, ul->isFloatingType());
6958 
6959         const Variable *ll = db->getVariableFromVarId(11);
6960         ASSERT(ll != nullptr);
6961         ASSERT_EQUALS("ll", ll->nameToken()->str());
6962         ASSERT_EQUALS(false, ll->isFloatingType());
6963     }
6964 
varTypesFloating()6965     void varTypesFloating() {
6966         {
6967             GET_SYMBOL_DB("void f() { float f; double d; long double ld; }");
6968             const Variable *f = db->getVariableFromVarId(1);
6969             ASSERT(f != nullptr);
6970             ASSERT_EQUALS("f", f->nameToken()->str());
6971             ASSERT_EQUALS(true, f->isFloatingType());
6972 
6973             const Variable *d = db->getVariableFromVarId(2);
6974             ASSERT(d != nullptr);
6975             ASSERT_EQUALS("d", d->nameToken()->str());
6976             ASSERT_EQUALS(true, d->isFloatingType());
6977 
6978             const Variable *ld = db->getVariableFromVarId(3);
6979             ASSERT(ld != nullptr);
6980             ASSERT_EQUALS("ld", ld->nameToken()->str());
6981             ASSERT_EQUALS(true, ld->isFloatingType());
6982         }
6983         {
6984             GET_SYMBOL_DB("void f() { float * f; static const float * scf; }");
6985             const Variable *f = db->getVariableFromVarId(1);
6986             ASSERT(f != nullptr);
6987             ASSERT_EQUALS("f", f->nameToken()->str());
6988             ASSERT_EQUALS(true, f->isFloatingType());
6989             ASSERT_EQUALS(true, f->isArrayOrPointer());
6990 
6991             const Variable *scf = db->getVariableFromVarId(2);
6992             ASSERT(scf != nullptr);
6993             ASSERT_EQUALS("scf", scf->nameToken()->str());
6994             ASSERT_EQUALS(true, scf->isFloatingType());
6995             ASSERT_EQUALS(true, scf->isArrayOrPointer());
6996         }
6997         {
6998             GET_SYMBOL_DB("void f() { float fa[42]; }");
6999             const Variable *fa = db->getVariableFromVarId(1);
7000             ASSERT(fa != nullptr);
7001             ASSERT_EQUALS("fa", fa->nameToken()->str());
7002             ASSERT_EQUALS(true, fa->isFloatingType());
7003             ASSERT_EQUALS(true, fa->isArrayOrPointer());
7004         }
7005     }
7006 
varTypesOther()7007     void varTypesOther() {
7008         GET_SYMBOL_DB("void f() { class A {} a; void *b;  }");
7009         const Variable *a = db->getVariableFromVarId(1);
7010         ASSERT(a != nullptr);
7011         ASSERT_EQUALS("a", a->nameToken()->str());
7012         ASSERT_EQUALS(false, a->isFloatingType());
7013 
7014         const Variable *b = db->getVariableFromVarId(2);
7015         ASSERT(b != nullptr);
7016         ASSERT_EQUALS("b", b->nameToken()->str());
7017         ASSERT_EQUALS(false, b->isFloatingType());
7018     }
7019 
functionPrototype()7020     void functionPrototype() {
7021         check("int foo(int x) {\n"
7022               "    extern int func1();\n"
7023               "    extern int func2(int);\n"
7024               "    int func3();\n"
7025               "    int func4(int);\n"
7026               "    return func4(x);\n"
7027               "}\n", true);
7028         ASSERT_EQUALS("", errout.str());
7029     }
7030 
lambda()7031     void lambda() {
7032         GET_SYMBOL_DB("void func() {\n"
7033                       "    float y = 0.0f;\n"
7034                       "    auto lambda = [&]()\n"
7035                       "    {\n"
7036                       "        float x = 1.0f;\n"
7037                       "        y += 10.0f - x;\n"
7038                       "    }\n"
7039                       "    lambda();\n"
7040                       "}");
7041 
7042         ASSERT(db && db->scopeList.size() == 3);
7043         std::list<Scope>::const_iterator scope = db->scopeList.begin();
7044         ASSERT_EQUALS(Scope::eGlobal, scope->type);
7045         ++scope;
7046         ASSERT_EQUALS(Scope::eFunction, scope->type);
7047         ++scope;
7048         ASSERT_EQUALS(Scope::eLambda, scope->type);
7049     }
7050 
lambda2()7051     void lambda2() {
7052         GET_SYMBOL_DB("void func() {\n"
7053                       "    float y = 0.0f;\n"
7054                       "    auto lambda = [&]() -> bool\n"
7055                       "    {\n"
7056                       "        float x = 1.0f;\n"
7057                       "    }\n"
7058                       "    lambda();\n"
7059                       "}");
7060 
7061         ASSERT(db && db->scopeList.size() == 3);
7062         std::list<Scope>::const_iterator scope = db->scopeList.begin();
7063         ASSERT_EQUALS(Scope::eGlobal, scope->type);
7064         ++scope;
7065         ASSERT_EQUALS(Scope::eFunction, scope->type);
7066         ++scope;
7067         ASSERT_EQUALS(Scope::eLambda, scope->type);
7068     }
7069 
7070 
lambda3()7071     void lambda3() {
7072         GET_SYMBOL_DB("void func() {\n"
7073                       "    auto f = []() mutable {}\n"
7074                       "}");
7075 
7076         ASSERT(db && db->scopeList.size() == 3);
7077         std::list<Scope>::const_iterator scope = db->scopeList.begin();
7078         ASSERT_EQUALS(Scope::eGlobal, scope->type);
7079         ++scope;
7080         ASSERT_EQUALS(Scope::eFunction, scope->type);
7081         ++scope;
7082         ASSERT_EQUALS(Scope::eLambda, scope->type);
7083     }
7084 
7085     // #6298 "stack overflow in Scope::findFunctionInBase (endless recursion)"
circularDependencies()7086     void circularDependencies() {
7087         check("template<template<class> class E,class D> class C : E<D> {\n"
7088               "	public:\n"
7089               "		int f();\n"
7090               "};\n"
7091               "class E : C<D,int> {\n"
7092               "	public:\n"
7093               "		int f() { return C< ::D,int>::f(); }\n"
7094               "};\n"
7095               "int main() {\n"
7096               "	E c;\n"
7097               "	c.f();\n"
7098               "}");
7099     }
7100 
executableScopeWithUnknownFunction()7101     void executableScopeWithUnknownFunction() {
7102         GET_SYMBOL_DB("class Fred {\n"
7103                       "    void foo(const std::string & a = \"\");\n"
7104                       "};\n"
7105                       "Fred::foo(const std::string & b) { }");
7106 
7107         ASSERT(db && db->scopeList.size() == 3);
7108         std::list<Scope>::const_iterator scope = db->scopeList.begin();
7109         ASSERT_EQUALS(Scope::eGlobal, scope->type);
7110         ++scope;
7111         ASSERT_EQUALS(Scope::eClass, scope->type);
7112         const Scope * class_scope = &*scope;
7113         ++scope;
7114         ASSERT(class_scope->functionList.size() == 1);
7115         ASSERT(class_scope->functionList.begin()->hasBody());
7116         ASSERT(class_scope->functionList.begin()->functionScope == &*scope);
7117     }
7118 
typeOf(const char code[],const char pattern[],const char filename[]="test.cpp",const Settings * settings=nullptr)7119     std::string typeOf(const char code[], const char pattern[], const char filename[] = "test.cpp", const Settings *settings = nullptr) {
7120         Tokenizer tokenizer(settings ? settings : &settings2, this);
7121         std::istringstream istr(code);
7122         tokenizer.tokenize(istr, filename);
7123         const Token* tok;
7124         for (tok = tokenizer.list.back(); tok; tok = tok->previous())
7125             if (Token::simpleMatch(tok, pattern, strlen(pattern)))
7126                 break;
7127         return tok->valueType() ? tok->valueType()->str() : std::string();
7128     }
7129 
valuetype()7130     void valuetype() {
7131         // stringification
7132         ASSERT_EQUALS("", ValueType().str());
7133 
7134         Settings s;
7135         s.int_bit = 16;
7136         s.long_bit = 32;
7137         s.long_long_bit = 64;
7138 
7139         Settings sSameSize;
7140         sSameSize.int_bit = 32;
7141         sSameSize.long_bit = 64;
7142         sSameSize.long_long_bit = 64;
7143 
7144         // numbers
7145         ASSERT_EQUALS("signed int", typeOf("1;", "1", "test.c", &s));
7146         ASSERT_EQUALS("signed int", typeOf("(-1);", "-1", "test.c", &s));
7147         ASSERT_EQUALS("signed int", typeOf("32767;", "32767", "test.c", &s));
7148         ASSERT_EQUALS("signed int", typeOf("(-32767);", "-32767", "test.c", &s));
7149         ASSERT_EQUALS("signed long", typeOf("32768;", "32768", "test.c", &s));
7150         ASSERT_EQUALS("signed long", typeOf("(-32768);", "-32768", "test.c", &s));
7151         ASSERT_EQUALS("signed long", typeOf("32768l;", "32768l", "test.c", &s));
7152         ASSERT_EQUALS("unsigned int", typeOf("32768U;", "32768U", "test.c", &s));
7153         ASSERT_EQUALS("signed long long", typeOf("2147483648;", "2147483648", "test.c", &s));
7154         ASSERT_EQUALS("unsigned long", typeOf("2147483648u;", "2147483648u", "test.c", &s));
7155         ASSERT_EQUALS("signed long long", typeOf("2147483648L;", "2147483648L", "test.c", &s));
7156         ASSERT_EQUALS("unsigned long long", typeOf("18446744069414584320;", "18446744069414584320", "test.c", &s));
7157         ASSERT_EQUALS("signed int", typeOf("0xFF;", "0xFF", "test.c", &s));
7158         ASSERT_EQUALS("unsigned int", typeOf("0xFFU;", "0xFFU", "test.c", &s));
7159         ASSERT_EQUALS("unsigned int", typeOf("0xFFFF;", "0xFFFF", "test.c", &s));
7160         ASSERT_EQUALS("signed long", typeOf("0xFFFFFF;", "0xFFFFFF", "test.c", &s));
7161         ASSERT_EQUALS("unsigned long", typeOf("0xFFFFFFU;", "0xFFFFFFU", "test.c", &s));
7162         ASSERT_EQUALS("unsigned long", typeOf("0xFFFFFFFF;", "0xFFFFFFFF", "test.c", &s));
7163         ASSERT_EQUALS("signed long long", typeOf("0xFFFFFFFFFFFF;", "0xFFFFFFFFFFFF", "test.c", &s));
7164         ASSERT_EQUALS("unsigned long long", typeOf("0xFFFFFFFFFFFFU;", "0xFFFFFFFFFFFFU", "test.c", &s));
7165         ASSERT_EQUALS("unsigned long long", typeOf("0xFFFFFFFF00000000;", "0xFFFFFFFF00000000", "test.c", &s));
7166 
7167         ASSERT_EQUALS("signed long", typeOf("2147483648;", "2147483648", "test.c", &sSameSize));
7168         ASSERT_EQUALS("unsigned long", typeOf("0xc000000000000000;", "0xc000000000000000", "test.c", &sSameSize));
7169 
7170         ASSERT_EQUALS("unsigned int", typeOf("1U;", "1U"));
7171         ASSERT_EQUALS("signed long", typeOf("1L;", "1L"));
7172         ASSERT_EQUALS("unsigned long", typeOf("1UL;", "1UL"));
7173         ASSERT_EQUALS("signed long long", typeOf("1LL;", "1LL"));
7174         ASSERT_EQUALS("unsigned long long", typeOf("1ULL;", "1ULL"));
7175         ASSERT_EQUALS("unsigned long long", typeOf("1LLU;", "1LLU"));
7176         ASSERT_EQUALS("signed long long", typeOf("1i64;", "1i64"));
7177         ASSERT_EQUALS("unsigned long long", typeOf("1ui64;", "1ui64"));
7178         ASSERT_EQUALS("unsigned int", typeOf("1u;", "1u"));
7179         ASSERT_EQUALS("signed long", typeOf("1l;", "1l"));
7180         ASSERT_EQUALS("unsigned long", typeOf("1ul;", "1ul"));
7181         ASSERT_EQUALS("signed long long", typeOf("1ll;", "1ll"));
7182         ASSERT_EQUALS("unsigned long long", typeOf("1ull;", "1ull"));
7183         ASSERT_EQUALS("unsigned long long", typeOf("1llu;", "1llu"));
7184         ASSERT_EQUALS("signed int", typeOf("01;", "01"));
7185         ASSERT_EQUALS("unsigned int", typeOf("01U;", "01U"));
7186         ASSERT_EQUALS("signed long", typeOf("01L;", "01L"));
7187         ASSERT_EQUALS("unsigned long", typeOf("01UL;", "01UL"));
7188         ASSERT_EQUALS("signed long long", typeOf("01LL;", "01LL"));
7189         ASSERT_EQUALS("unsigned long long", typeOf("01ULL;", "01ULL"));
7190         ASSERT_EQUALS("signed int", typeOf("0B1;", "0B1"));
7191         ASSERT_EQUALS("signed int", typeOf("0b1;", "0b1"));
7192         ASSERT_EQUALS("unsigned int", typeOf("0b1U;", "0b1U"));
7193         ASSERT_EQUALS("signed long", typeOf("0b1L;", "0b1L"));
7194         ASSERT_EQUALS("unsigned long", typeOf("0b1UL;", "0b1UL"));
7195         ASSERT_EQUALS("signed long long", typeOf("0b1LL;", "0b1LL"));
7196         ASSERT_EQUALS("unsigned long long", typeOf("0b1ULL;", "0b1ULL"));
7197         ASSERT_EQUALS("float", typeOf("1.0F;", "1.0F"));
7198         ASSERT_EQUALS("float", typeOf("1.0f;", "1.0f"));
7199         ASSERT_EQUALS("double", typeOf("1.0;", "1.0"));
7200         ASSERT_EQUALS("double", typeOf("1E3;", "1E3"));
7201         ASSERT_EQUALS("double", typeOf("0x1.2p3;", "0x1.2p3"));
7202         ASSERT_EQUALS("long double", typeOf("1.23L;", "1.23L"));
7203         ASSERT_EQUALS("long double", typeOf("1.23l;", "1.23l"));
7204 
7205         // Constant calculations
7206         ASSERT_EQUALS("signed int", typeOf("1 + 2;", "+"));
7207         ASSERT_EQUALS("signed long", typeOf("1L + 2;", "+"));
7208         ASSERT_EQUALS("signed long long", typeOf("1LL + 2;", "+"));
7209         ASSERT_EQUALS("float", typeOf("1.2f + 3;", "+"));
7210         ASSERT_EQUALS("float", typeOf("1 + 2.3f;", "+"));
7211 
7212         // promotions
7213         ASSERT_EQUALS("signed int", typeOf("(char)1 +  (char)2;", "+"));
7214         ASSERT_EQUALS("signed int", typeOf("(short)1 + (short)2;", "+"));
7215         ASSERT_EQUALS("signed int", typeOf("(signed int)1 + (signed char)2;", "+"));
7216         ASSERT_EQUALS("signed int", typeOf("(signed int)1 + (unsigned char)2;", "+"));
7217         ASSERT_EQUALS("unsigned int", typeOf("(unsigned int)1 + (signed char)2;", "+"));
7218         ASSERT_EQUALS("unsigned int", typeOf("(unsigned int)1 + (unsigned char)2;", "+"));
7219         ASSERT_EQUALS("unsigned int", typeOf("(unsigned int)1 + (signed int)2;", "+"));
7220         ASSERT_EQUALS("unsigned int", typeOf("(unsigned int)1 + (unsigned int)2;", "+"));
7221         ASSERT_EQUALS("signed long", typeOf("(signed long)1 + (unsigned int)2;", "+"));
7222         ASSERT_EQUALS("unsigned long", typeOf("(unsigned long)1 + (signed int)2;", "+"));
7223 
7224         // char
7225         ASSERT_EQUALS("char", typeOf("'a';", "'a'", "test.cpp"));
7226         ASSERT_EQUALS("signed int", typeOf("'a';", "'a'", "test.c"));
7227         ASSERT_EQUALS("wchar_t", typeOf("L'a';", "L'a'", "test.cpp"));
7228         ASSERT_EQUALS("wchar_t", typeOf("L'a';", "L'a'", "test.c"));
7229         ASSERT_EQUALS("signed int", typeOf("'aaa';", "'aaa'", "test.cpp"));
7230         ASSERT_EQUALS("signed int", typeOf("'aaa';", "'aaa'", "test.c"));
7231 
7232         // char *
7233         ASSERT_EQUALS("const char *", typeOf("\"hello\" + 1;", "+"));
7234         ASSERT_EQUALS("const char",  typeOf("\"hello\"[1];", "["));
7235         ASSERT_EQUALS("const char",  typeOf(";*\"hello\";", "*"));
7236         ASSERT_EQUALS("const wchar_t *", typeOf("L\"hello\" + 1;", "+"));
7237 
7238         // Variable calculations
7239         ASSERT_EQUALS("void *", typeOf("void *p; a = p + 1;", "+"));
7240         ASSERT_EQUALS("signed int", typeOf("int x; a = x + 1;", "+"));
7241         ASSERT_EQUALS("signed int", typeOf("int x; a = x | 1;", "|"));
7242         ASSERT_EQUALS("float", typeOf("float x; a = x + 1;", "+"));
7243         ASSERT_EQUALS("signed int", typeOf("signed x; a = x + 1;", "x +"));
7244         ASSERT_EQUALS("unsigned int", typeOf("unsigned x; a = x + 1;", "x +"));
7245         ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 + 1;",  "u1 +"));
7246         ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 + 1U;", "u1 +"));
7247         ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 + u2;", "u1 +"));
7248         ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 * 2;",  "u1 *"));
7249         ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 * u2;", "u1 *"));
7250         ASSERT_EQUALS("signed int *", typeOf("int x; a = &x;", "&"));
7251         ASSERT_EQUALS("signed int *", typeOf("int x; a = &x;", "&"));
7252         ASSERT_EQUALS("long double", typeOf("long double x; dostuff(x,1);", "x ,"));
7253         ASSERT_EQUALS("long double *", typeOf("long double x; dostuff(&x,1);", "& x ,"));
7254         ASSERT_EQUALS("signed int", typeOf("struct X {int i;}; void f(struct X x) { x.i }", "."));
7255         ASSERT_EQUALS("signed int *", typeOf("int *p; a = p++;", "++"));
7256         ASSERT_EQUALS("signed int", typeOf("int x; a = x++;", "++"));
7257         ASSERT_EQUALS("signed int *", typeOf("enum AB {A,B}; AB *ab; x=ab+2;", "+"));
7258         ASSERT_EQUALS("signed int *", typeOf("enum AB {A,B}; enum AB *ab; x=ab+2;", "+"));
7259         ASSERT_EQUALS("AB *", typeOf("struct AB {int a; int b;}; AB ab; x=&ab;", "&"));
7260         ASSERT_EQUALS("AB *", typeOf("struct AB {int a; int b;}; struct AB ab; x=&ab;", "&"));
7261         ASSERT_EQUALS("A::BC *", typeOf("namespace A { struct BC { int b; int c; }; }; struct A::BC abc; x=&abc;", "&"));
7262         ASSERT_EQUALS("A::BC *", typeOf("namespace A { struct BC { int b; int c; }; }; struct A::BC *abc; x=abc+1;", "+"));
7263         ASSERT_EQUALS("signed int", typeOf("auto a(int& x, int& y) { return x + y; }", "+"));
7264         ASSERT_EQUALS("signed int", typeOf("auto a(int& x) { return x << 1; }", "<<"));
7265         ASSERT_EQUALS("signed int", typeOf("void a(int& x, int& y) { x = y; }", "=")); //Debatably this should be a signed int & but we'll stick with the current behavior for now
7266         ASSERT_EQUALS("signed int", typeOf("auto a(int* y) { return *y; }", "*")); //Debatably this should be a signed int & but we'll stick with the current behavior for now
7267 
7268         // Unary arithmetic/bit operators
7269         ASSERT_EQUALS("signed int", typeOf("int x; a = -x;", "-"));
7270         ASSERT_EQUALS("signed int", typeOf("int x; a = ~x;", "~"));
7271         ASSERT_EQUALS("double", typeOf("double x; a = -x;", "-"));
7272 
7273         // Ternary operator
7274         ASSERT_EQUALS("signed int", typeOf("int x; a = (b ? x : x);", "?"));
7275         ASSERT_EQUALS("", typeOf("int x; a = (b ? x : y);", "?"));
7276         ASSERT_EQUALS("double", typeOf("int x; double y; a = (b ? x : y);", "?"));
7277         ASSERT_EQUALS("const char *", typeOf("int x; double y; a = (b ? \"a\" : \"b\");", "?"));
7278         ASSERT_EQUALS("", typeOf("int x; double y; a = (b ? \"a\" : std::string(\"b\"));", "?"));
7279         ASSERT_EQUALS("bool", typeOf("int x; a = (b ? false : true);", "?"));
7280 
7281         // Boolean operators/literals
7282         ASSERT_EQUALS("bool", typeOf("a > b;", ">"));
7283         ASSERT_EQUALS("bool", typeOf(";!b;", "!"));
7284         ASSERT_EQUALS("bool", typeOf("c = a && b;", "&&"));
7285         ASSERT_EQUALS("bool", typeOf("a = false;", "false"));
7286         ASSERT_EQUALS("bool", typeOf("a = true;", "true"));
7287 
7288         // shift => result has same type as lhs
7289         ASSERT_EQUALS("signed int", typeOf("int x; a = x << 1U;", "<<"));
7290         ASSERT_EQUALS("signed int", typeOf("int x; a = x >> 1U;", ">>"));
7291         ASSERT_EQUALS("",           typeOf("a = 12 >> x;", ">>", "test.cpp")); // >> might be overloaded
7292         ASSERT_EQUALS("signed int", typeOf("a = 12 >> x;", ">>", "test.c"));
7293         ASSERT_EQUALS("",           typeOf("a = 12 << x;", "<<", "test.cpp")); // << might be overloaded
7294         ASSERT_EQUALS("signed int", typeOf("a = 12 << x;", "<<", "test.c"));
7295         ASSERT_EQUALS("signed int", typeOf("a = true << 1U;", "<<"));
7296 
7297         // assignment => result has same type as lhs
7298         ASSERT_EQUALS("unsigned short", typeOf("unsigned short x; x = 3;", "="));
7299 
7300         // array..
7301         ASSERT_EQUALS("void * *", typeOf("void * x[10]; a = x + 0;", "+"));
7302         ASSERT_EQUALS("signed int *", typeOf("int x[10]; a = x + 1;", "+"));
7303         ASSERT_EQUALS("signed int",  typeOf("int x[10]; a = x[0] + 1;", "+"));
7304         ASSERT_EQUALS("",            typeOf("a = x[\"hello\"];", "[", "test.cpp"));
7305         ASSERT_EQUALS("const char",  typeOf("a = x[\"hello\"];", "[", "test.c"));
7306 
7307         // cast..
7308         ASSERT_EQUALS("void *", typeOf("a = (void *)0;", "("));
7309         ASSERT_EQUALS("char", typeOf("a = (char)32;", "("));
7310         ASSERT_EQUALS("signed long", typeOf("a = (long)32;", "("));
7311         ASSERT_EQUALS("signed long", typeOf("a = (long int)32;", "("));
7312         ASSERT_EQUALS("signed long long", typeOf("a = (long long)32;", "("));
7313         ASSERT_EQUALS("long double", typeOf("a = (long double)32;", "("));
7314         ASSERT_EQUALS("char", typeOf("a = static_cast<char>(32);", "("));
7315         ASSERT_EQUALS("", typeOf("a = (unsigned x)0;", "("));
7316         ASSERT_EQUALS("unsigned int", typeOf("a = unsigned(123);", "("));
7317 
7318         // sizeof..
7319         ASSERT_EQUALS("char", typeOf("sizeof(char);", "char"));
7320 
7321         // const..
7322         ASSERT_EQUALS("const char *", typeOf("a = \"123\";", "\"123\""));
7323         ASSERT_EQUALS("const signed int *", typeOf("const int *a; x = a + 1;", "a +"));
7324         ASSERT_EQUALS("signed int * const", typeOf("int * const a; x = a + 1;", "+"));
7325         ASSERT_EQUALS("const signed int *", typeOf("const int a[20]; x = a + 1;", "+"));
7326         ASSERT_EQUALS("const signed int *", typeOf("const int x; a = &x;", "&"));
7327         ASSERT_EQUALS("signed int", typeOf("int * const a; x = *a;", "*"));
7328         ASSERT_EQUALS("const signed int", typeOf("const int * const a; x = *a;", "*"));
7329 
7330         // function call..
7331         ASSERT_EQUALS("signed int", typeOf("int a(int); a(5);", "( 5"));
7332         ASSERT_EQUALS("signed int", typeOf("auto a(int) -> int; a(5);", "( 5"));
7333         ASSERT_EQUALS("unsigned long", typeOf("sizeof(x);", "("));
7334         ASSERT_EQUALS("signed int", typeOf("int (*a)(int); a(5);", "( 5"));
7335         ASSERT_EQUALS("s", typeOf("struct s { s foo(); s(int, int); }; s s::foo() { return s(1, 2); } ", "( 1 , 2 )"));
7336         // Some standard template functions.. TODO library configuration
7337         ASSERT_EQUALS("signed int &&", typeOf("std::move(5);", "( 5 )"));
7338 
7339         // struct member..
7340         ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } ab; x = ab.a;", "."));
7341         ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } *ab; x = ab[1].a;", "."));
7342 
7343         // Overloaded operators
7344         ASSERT_EQUALS("Fred &", typeOf("class Fred { Fred& operator<(int); }; void f() { Fred fred; x=fred<123; }", "<"));
7345 
7346         // Static members
7347         ASSERT_EQUALS("signed int", typeOf("struct AB { static int a; }; x = AB::a;", "::"));
7348 
7349         // Pointer to unknown type
7350         ASSERT_EQUALS("*", typeOf("Bar* b;", "b"));
7351 
7352         // Enum
7353         ASSERT_EQUALS("char", typeOf("enum E : char { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7354         ASSERT_EQUALS("signed char", typeOf("enum E : signed char { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7355         ASSERT_EQUALS("unsigned char", typeOf("enum E : unsigned char { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7356         ASSERT_EQUALS("signed short", typeOf("enum E : short { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7357         ASSERT_EQUALS("unsigned short", typeOf("enum E : unsigned short { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7358         ASSERT_EQUALS("signed int", typeOf("enum E : int { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7359         ASSERT_EQUALS("unsigned int", typeOf("enum E : unsigned int { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7360         ASSERT_EQUALS("signed long", typeOf("enum E : long { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7361         ASSERT_EQUALS("unsigned long", typeOf("enum E : unsigned long { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7362         ASSERT_EQUALS("signed long long", typeOf("enum E : long long { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7363         ASSERT_EQUALS("unsigned long long", typeOf("enum E : unsigned long long { }; void foo() { E e[3]; bar(e[0]); }", "[ 0"));
7364 
7365 #define CHECK_LIBRARY_FUNCTION_RETURN_TYPE(type) do { \
7366         Settings sF; \
7367         const char xmldata[] = "<?xml version=\"1.0\"?>\n" \
7368                                "<def>\n" \
7369                                "<function name=\"g\">\n" \
7370                                "<returnValue type=\"" #type "\"/>\n" \
7371                                "</function>\n" \
7372                                "</def>"; \
7373         tinyxml2::XMLDocument doc; \
7374         doc.Parse(xmldata, sizeof(xmldata)); \
7375         sF.library.load(doc); \
7376         ASSERT_EQUALS(#type, typeOf("void f() { auto x = g(); }", "x", "test.cpp", &sF)); \
7377 } while (false)
7378         // *INDENT-OFF*
7379         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(bool);
7380         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed char);
7381         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned char);
7382         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed short);
7383         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned short);
7384         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed int);
7385         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned int);
7386         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed long);
7387         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned long);
7388         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed long long);
7389         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned long long);
7390         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(void *);
7391         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(void * *);
7392         CHECK_LIBRARY_FUNCTION_RETURN_TYPE(const void *);
7393         // *INDENT-ON*
7394 #undef CHECK_LIBRARY_FUNCTION_RETURN_TYPE
7395 
7396         // Library types
7397         {
7398             // Char types
7399             Settings settings;
7400             const Library::PodType char8 = { 1, 'u' };
7401             const Library::PodType char16 = { 2, 'u' };
7402             const Library::PodType char32 = { 4, 'u' };
7403             settings.library.mPodTypes["char8_t"] = char8;
7404             settings.library.mPodTypes["char16_t"] = char16;
7405             settings.library.mPodTypes["char32_t"] = char32;
7406             settings.sizeof_short = 2;
7407             settings.sizeof_int = 4;
7408 
7409             ASSERT_EQUALS("unsigned char", typeOf("u8'a';", "u8'a'", "test.cpp", &settings));
7410             ASSERT_EQUALS("unsigned short", typeOf("u'a';", "u'a'", "test.cpp", &settings));
7411             ASSERT_EQUALS("unsigned int", typeOf("U'a';", "U'a'", "test.cpp", &settings));
7412             ASSERT_EQUALS("const unsigned char *", typeOf("u8\"a\";", "u8\"a\"", "test.cpp", &settings));
7413             ASSERT_EQUALS("const unsigned short *", typeOf("u\"a\";", "u\"a\"", "test.cpp", &settings));
7414             ASSERT_EQUALS("const unsigned int *", typeOf("U\"a\";", "U\"a\"", "test.cpp", &settings));
7415         }
7416         {
7417             // PodType
7418             Settings settingsWin64;
7419             settingsWin64.platformType = Settings::Win64;
7420             const Library::PodType u32 = { 4, 'u' };
7421             const Library::PodType podtype2 = { 0, 'u', Library::PodType::Type::INT };
7422             settingsWin64.library.mPodTypes["u32"] = u32;
7423             settingsWin64.library.mPodTypes["xyz::x"] = u32;
7424             settingsWin64.library.mPodTypes["podtype2"] = podtype2;
7425             ValueType vt;
7426             ASSERT_EQUALS(true, vt.fromLibraryType("u32", &settingsWin64));
7427             ASSERT_EQUALS(true, vt.fromLibraryType("xyz::x", &settingsWin64));
7428             ASSERT_EQUALS(ValueType::Type::INT, vt.type);
7429             ValueType vt2;
7430             ASSERT_EQUALS(true, vt2.fromLibraryType("podtype2", &settingsWin64));
7431             ASSERT_EQUALS(ValueType::Type::INT, vt2.type);
7432             ASSERT_EQUALS("unsigned int *", typeOf(";void *data = new u32[10];", "new", "test.cpp", &settingsWin64));
7433             ASSERT_EQUALS("unsigned int *", typeOf(";void *data = new xyz::x[10];", "new", "test.cpp", &settingsWin64));
7434             ASSERT_EQUALS("unsigned int", typeOf("; x = (xyz::x)12;", "(", "test.cpp", &settingsWin64));
7435             ASSERT_EQUALS("unsigned int", typeOf(";u32(12);", "(", "test.cpp", &settingsWin64));
7436             ASSERT_EQUALS("unsigned int", typeOf("x = u32(y[i]);", "(", "test.cpp", &settingsWin64));
7437         }
7438         {
7439             // PlatformType
7440             Settings settingsUnix32;
7441             settingsUnix32.platformType = Settings::Unix32;
7442             Library::PlatformType s32;
7443             s32.mType = "int";
7444             settingsUnix32.library.mPlatforms[settingsUnix32.platformString()].mPlatformTypes["s32"] = s32;
7445             ValueType vt;
7446             ASSERT_EQUALS(true, vt.fromLibraryType("s32", &settingsUnix32));
7447             ASSERT_EQUALS(ValueType::Type::INT, vt.type);
7448         }
7449         {
7450             // PlatformType - wchar_t
7451             Settings settingsWin64;
7452             settingsWin64.platformType = Settings::Win64;
7453             Library::PlatformType lpctstr;
7454             lpctstr.mType = "wchar_t";
7455             settingsWin64.library.mPlatforms[settingsWin64.platformString()].mPlatformTypes["LPCTSTR"] = lpctstr;
7456             ValueType vt;
7457             ASSERT_EQUALS(true, vt.fromLibraryType("LPCTSTR", &settingsWin64));
7458             ASSERT_EQUALS(ValueType::Type::WCHAR_T, vt.type);
7459         }
7460         {
7461             // Container
7462             Settings sC;
7463             Library::Container c;
7464             c.startPattern = "C";
7465             c.startPattern2 = "C !!::";
7466             sC.library.containers["C"] = c;
7467             ASSERT_EQUALS("container(C) *", typeOf("C*c=new C;","new","test.cpp",&sC));
7468             ASSERT_EQUALS("container(C) *", typeOf("x=(C*)c;","(","test.cpp",&sC));
7469             ASSERT_EQUALS("container(C)", typeOf("C c = C();","(","test.cpp",&sC));
7470         }
7471         {
7472             // Container (vector)
7473             Settings set;
7474             Library::Container vector;
7475             vector.startPattern = "Vector <";
7476             vector.startPattern2 = "Vector !!::";
7477             vector.type_templateArgNo = 0;
7478             vector.arrayLike_indexOp = true;
7479             vector.functions["front"] =
7480                 Library::Container::Function{Library::Container::Action::NO_ACTION, Library::Container::Yield::ITEM};
7481             vector.functions["data"] =
7482                 Library::Container::Function{Library::Container::Action::NO_ACTION, Library::Container::Yield::BUFFER};
7483             vector.functions["begin"] = Library::Container::Function{Library::Container::Action::NO_ACTION,
7484                                                                      Library::Container::Yield::START_ITERATOR};
7485             set.library.containers["Vector"] = vector;
7486             Library::Container string;
7487             string.startPattern = "test :: string";
7488             string.startPattern2 = "test :: string !!::";
7489             string.arrayLike_indexOp = string.stdStringLike = true;
7490             set.library.containers["test::string"] = string;
7491             ASSERT_EQUALS("signed int", typeOf("Vector<int> v; v[0]=3;", "[", "test.cpp", &set));
7492             ASSERT_EQUALS("container(test :: string)", typeOf("{return test::string();}", "(", "test.cpp", &set));
7493             ASSERT_EQUALS(
7494                 "container(test :: string)",
7495                 typeOf("void foo(Vector<test::string> v) { for (auto s: v) { x=s+s; } }", "s", "test.cpp", &set));
7496             ASSERT_EQUALS(
7497                 "container(test :: string)",
7498                 typeOf("void foo(Vector<test::string> v) { for (auto s: v) { x=s+s; } }", "+", "test.cpp", &set));
7499             ASSERT_EQUALS("container(test :: string) &",
7500                           typeOf("Vector<test::string> v; x = v.front();", "(", "test.cpp", &set));
7501             ASSERT_EQUALS("container(test :: string) *",
7502                           typeOf("Vector<test::string> v; x = v.data();", "(", "test.cpp", &set));
7503             ASSERT_EQUALS("signed int &", typeOf("Vector<int> v; x = v.front();", "(", "test.cpp", &set));
7504             ASSERT_EQUALS("signed int *", typeOf("Vector<int> v; x = v.data();", "(", "test.cpp", &set));
7505             ASSERT_EQUALS("signed int * *", typeOf("Vector<int*> v; x = v.data();", "(", "test.cpp", &set));
7506             ASSERT_EQUALS("iterator(Vector <)", typeOf("Vector<int> v; x = v.begin();", "(", "test.cpp", &set));
7507             ASSERT_EQUALS("signed int &", typeOf("Vector<int> v; x = *v.begin();", "*", "test.cpp", &set));
7508             ASSERT_EQUALS("container(test :: string)",
7509                           typeOf("void foo(){test::string s; return \"x\"+s;}", "+", "test.cpp", &set));
7510             ASSERT_EQUALS("container(test :: string)",
7511                           typeOf("void foo(){test::string s; return s+\"x\";}", "+", "test.cpp", &set));
7512             ASSERT_EQUALS("container(test :: string)",
7513                           typeOf("void foo(){test::string s; return 'x'+s;}", "+", "test.cpp", &set));
7514             ASSERT_EQUALS("container(test :: string)",
7515                           typeOf("void foo(){test::string s; return s+'x';}", "+", "test.cpp", &set));
7516         }
7517 
7518         // new
7519         ASSERT_EQUALS("C *", typeOf("class C {}; x = new C();", "new"));
7520 
7521         // auto variables
7522         ASSERT_EQUALS("signed int", typeOf("; auto x = 3;", "x"));
7523         ASSERT_EQUALS("signed int *", typeOf("; auto *p = (int *)0;", "p"));
7524         ASSERT_EQUALS("signed int *", typeOf("; auto data = new int[100];", "data"));
7525         ASSERT_EQUALS("signed int", typeOf("; auto data = new X::Y; int x=1000; x=x/5;", "/")); // #7970
7526         ASSERT_EQUALS("signed int *", typeOf("; auto data = new (nothrow) int[100];", "data"));
7527         ASSERT_EQUALS("signed int *", typeOf("; auto data = new (std::nothrow) int[100];", "data"));
7528         ASSERT_EQUALS("const signed short", typeOf("short values[10]; void f() { for (const auto *x : values); }", "x"));
7529         ASSERT_EQUALS("const signed int", typeOf("; const auto x = 3;", "x"));
7530 
7531         // Variable declaration
7532         ASSERT_EQUALS("char *", typeOf("; char abc[] = \"abc\";", "["));
7533         ASSERT_EQUALS("", typeOf("; int x[10] = { [3]=1 };", "[ 3 ]"));
7534 
7535         // std::make_shared
7536         {
7537             Settings set;
7538             Library::SmartPointer sharedPtr;
7539             sharedPtr.name = "std::shared_ptr";
7540             set.library.smartPointers["std::shared_ptr"] = sharedPtr;
7541             ASSERT_EQUALS("smart-pointer(std::shared_ptr)",
7542                           typeOf("class C {}; x = std::make_shared<C>();", "(", "test.cpp", &set));
7543         }
7544 
7545         // return
7546         {
7547             // Container
7548             Settings sC;
7549             Library::Container c;
7550             c.startPattern = "C";
7551             c.startPattern2 = "C !!::";
7552             sC.library.containers["C"] = c;
7553             ASSERT_EQUALS("container(C)", typeOf("C f(char *p) { char data[10]; return data; }", "return", "test.cpp", &sC));
7554         }
7555         // Smart pointer
7556         {
7557             Settings set;
7558             Library::SmartPointer myPtr;
7559             myPtr.name = "MyPtr";
7560             set.library.smartPointers["MyPtr"] = myPtr;
7561             ASSERT_EQUALS("smart-pointer(MyPtr)",
7562                           typeOf("void f() { MyPtr<int> p; return p; }", "p ;", "test.cpp", &set));
7563             ASSERT_EQUALS("signed int", typeOf("void f() { MyPtr<int> p; return *p; }", "* p ;", "test.cpp", &set));
7564             ASSERT_EQUALS("smart-pointer(MyPtr)", typeOf("void f() {return MyPtr<int>();}", "(", "test.cpp", &set));
7565         }
7566     }
7567 
variadic1()7568     void variadic1() { // #7453
7569         {
7570             GET_SYMBOL_DB("CBase* create(const char *c1, ...);\n"
7571                           "int    create(COther& ot, const char *c1, ...);\n"
7572                           "int foo(COther & ot)\n"
7573                           "{\n"
7574                           "   CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
7575                           "   CBase* cp2 = create(ot, \"AAAA\", 44, (char*)0);\n"
7576                           "}");
7577 
7578             const Token *f = Token::findsimplematch(tokenizer.tokens(), "create ( \"AAAA\"");
7579             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
7580             f = Token::findsimplematch(tokenizer.tokens(), "create ( ot");
7581             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
7582         }
7583         {
7584             GET_SYMBOL_DB("int    create(COther& ot, const char *c1, ...);\n"
7585                           "CBase* create(const char *c1, ...);\n"
7586                           "int foo(COther & ot)\n"
7587                           "{\n"
7588                           "   CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
7589                           "   CBase* cp2 = create(ot, \"AAAA\", 44, (char*)0);\n"
7590                           "}");
7591 
7592             const Token *f = Token::findsimplematch(tokenizer.tokens(), "create ( \"AAAA\"");
7593             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
7594             f = Token::findsimplematch(tokenizer.tokens(), "create ( ot");
7595             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
7596         }
7597     }
7598 
variadic2()7599     void variadic2() { // #7649
7600         {
7601             GET_SYMBOL_DB("CBase* create(const char *c1, ...);\n"
7602                           "CBase* create(const wchar_t *c1, ...);\n"
7603                           "int foo(COther & ot)\n"
7604                           "{\n"
7605                           "   CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
7606                           "   CBase* cp2 = create(L\"AAAA\", 44, (char*)0);\n"
7607                           "}");
7608 
7609             const Token *f = Token::findsimplematch(tokenizer.tokens(), "cp1 = create (");
7610             ASSERT_EQUALS(true, db && f && f->tokAt(2) && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 1);
7611             f = Token::findsimplematch(tokenizer.tokens(), "cp2 = create (");
7612             ASSERT_EQUALS(true, db && f && f->tokAt(2) && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 2);
7613         }
7614         {
7615             GET_SYMBOL_DB("CBase* create(const wchar_t *c1, ...);\n"
7616                           "CBase* create(const char *c1, ...);\n"
7617                           "int foo(COther & ot)\n"
7618                           "{\n"
7619                           "   CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
7620                           "   CBase* cp2 = create(L\"AAAA\", 44, (char*)0);\n"
7621                           "}");
7622 
7623             const Token *f = Token::findsimplematch(tokenizer.tokens(), "cp1 = create (");
7624             ASSERT_EQUALS(true, db && f && f->tokAt(2) && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 2);
7625             f = Token::findsimplematch(tokenizer.tokens(), "cp2 = create (");
7626             ASSERT_EQUALS(true, db && f && f->tokAt(2) && f->tokAt(2)->function() && f->tokAt(2)->function()->tokenDef->linenr() == 1);
7627         }
7628     }
7629 
variadic3()7630     void variadic3() { // #7387
7631         {
7632             GET_SYMBOL_DB("int zdcalc(const XYZ & per, short rs = 0);\n"
7633                           "double zdcalc(long& length, const XYZ * per);\n"
7634                           "long mycalc( ) {\n"
7635                           "    long length;\n"
7636                           "    XYZ per;\n"
7637                           "    zdcalc(length, &per);\n"
7638                           "}");
7639 
7640             const Token *f = Token::findsimplematch(tokenizer.tokens(), "zdcalc ( length");
7641             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
7642         }
7643         {
7644             GET_SYMBOL_DB("double zdcalc(long& length, const XYZ * per);\n"
7645                           "int zdcalc(const XYZ & per, short rs = 0);\n"
7646                           "long mycalc( ) {\n"
7647                           "    long length;\n"
7648                           "    XYZ per;\n"
7649                           "    zdcalc(length, &per);\n"
7650                           "}");
7651 
7652             const Token *f = Token::findsimplematch(tokenizer.tokens(), "zdcalc ( length");
7653             ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
7654         }
7655     }
7656 
noReturnType()7657     void noReturnType() {
7658         GET_SYMBOL_DB_C("func() { }");
7659 
7660         ASSERT(db && db->functionScopes.size() == 1);
7661         ASSERT(db->functionScopes[0]->function != nullptr);
7662         const Token *retDef = db->functionScopes[0]->function->retDef;
7663         ASSERT_EQUALS("func", retDef ? retDef->str() : "");
7664     }
7665 
auto1()7666     void auto1() {
7667         GET_SYMBOL_DB("; auto x = \"abc\";");
7668         const Token *autotok = tokenizer.tokens()->next();
7669         ASSERT(autotok && autotok->isStandardType());
7670         const Variable *var = db ? db->getVariableFromVarId(1) : nullptr;
7671         ASSERT(var && var->isPointer() && !var->isConst());
7672     }
7673 
auto2()7674     void auto2() {
7675         GET_SYMBOL_DB("struct S { int i; };\n"
7676                       "int foo() {\n"
7677                       "    auto a = new S;\n"
7678                       "    auto * b = new S;\n"
7679                       "    auto c = new S[10];\n"
7680                       "    auto * d = new S[10];\n"
7681                       "    return a->i + b->i + c[0]->i + d[0]->i;\n"
7682                       "}");
7683         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto");
7684         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() == nullptr);
7685 
7686         autotok = Token::findsimplematch(autotok->next(), "auto");
7687         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S");
7688 
7689         autotok = Token::findsimplematch(autotok->next(), "auto");
7690         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() == nullptr);
7691 
7692         autotok = Token::findsimplematch(autotok->next(), "auto");
7693         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S");
7694 
7695         vartok = Token::findsimplematch(tokenizer.tokens(), "a =");
7696         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7697 
7698         vartok = Token::findsimplematch(vartok->next(), "b =");
7699         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7700 
7701         vartok = Token::findsimplematch(vartok->next(), "c =");
7702         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7703 
7704         vartok = Token::findsimplematch(vartok->next(), "d =");
7705         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7706 
7707         vartok = Token::findsimplematch(tokenizer.tokens(), "return");
7708 
7709         vartok = Token::findsimplematch(vartok, "a");
7710         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7711 
7712         vartok = Token::findsimplematch(vartok->next(), "b");
7713         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7714 
7715         vartok = Token::findsimplematch(vartok->next(), "c");
7716         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7717 
7718         vartok = Token::findsimplematch(vartok->next(), "d");
7719         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7720 
7721         vartok = Token::findsimplematch(tokenizer.tokens(), "return");
7722 
7723         vartok = Token::findsimplematch(vartok, "i");
7724         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7725 
7726         vartok = Token::findsimplematch(vartok->next(), "i");
7727         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7728 
7729         vartok = Token::findsimplematch(vartok->next(), "i");
7730         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7731 
7732         vartok = Token::findsimplematch(vartok->next(), "i");
7733         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7734     }
7735 
auto3()7736     void auto3() {
7737         GET_SYMBOL_DB("enum E : unsigned short { A, B, C };\n"
7738                       "int foo() {\n"
7739                       "    auto a = new E;\n"
7740                       "    auto * b = new E;\n"
7741                       "    auto c = new E[10];\n"
7742                       "    auto * d = new E[10];\n"
7743                       "    return *a + *b + c[0] + d[0];\n"
7744                       "}");
7745         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto");
7746         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() == nullptr);
7747 
7748         autotok = Token::findsimplematch(autotok->next(), "auto");
7749         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E");
7750 
7751         autotok = Token::findsimplematch(autotok->next(), "auto");
7752         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() == nullptr);
7753 
7754         autotok = Token::findsimplematch(autotok->next(), "auto");
7755         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E");
7756 
7757         vartok = Token::findsimplematch(tokenizer.tokens(), "a =");
7758         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7759 
7760         vartok = Token::findsimplematch(vartok->next(), "b =");
7761         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7762 
7763         vartok = Token::findsimplematch(vartok->next(), "c =");
7764         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7765 
7766         vartok = Token::findsimplematch(vartok->next(), "d =");
7767         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7768 
7769         vartok = Token::findsimplematch(tokenizer.tokens(), "return");
7770 
7771         vartok = Token::findsimplematch(vartok, "a");
7772         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7773 
7774         vartok = Token::findsimplematch(vartok->next(), "b");
7775         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7776 
7777         vartok = Token::findsimplematch(vartok->next(), "c");
7778         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7779 
7780         vartok = Token::findsimplematch(vartok->next(), "d");
7781         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
7782     }
7783 
auto4()7784     void auto4() {
7785         GET_SYMBOL_DB("struct S { int i; };\n"
7786                       "int foo() {\n"
7787                       "    S array[10];\n"
7788                       "    for (auto a : array)\n"
7789                       "        a.i = 0;\n"
7790                       "    for (auto & b : array)\n"
7791                       "        b.i = 1;\n"
7792                       "    for (const auto & c : array)\n"
7793                       "        auto ci = c.i;\n"
7794                       "    for (auto * d : array)\n"
7795                       "        d->i = 0;\n"
7796                       "    for (const auto * e : array)\n"
7797                       "        auto ei = e->i;\n"
7798                       "    return array[0].i;\n"
7799                       "}");
7800         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto a");
7801         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7802         ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
7803 
7804         autotok = Token::findsimplematch(autotok->next(), "auto & b");
7805         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7806         ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
7807 
7808         autotok = Token::findsimplematch(autotok->next(), "auto & c");
7809         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7810         ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
7811 
7812         autotok = Token::findsimplematch(autotok->next(), "auto * d");
7813         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7814         ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
7815 
7816         autotok = Token::findsimplematch(autotok->next(), "auto * e");
7817         ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7818         ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
7819 
7820         vartok = Token::findsimplematch(tokenizer.tokens(), "a :");
7821         ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7822         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && !vartok->variable()->isPointer());
7823         ASSERT(db && vartok && vartok->variable() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7824 
7825         vartok = Token::findsimplematch(vartok->next(), "b :");
7826         ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7827         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && !vartok->variable()->isConst());
7828 
7829         vartok = Token::findsimplematch(vartok->next(), "c :");
7830         ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7831         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && vartok->variable()->isConst());
7832 
7833         vartok = Token::findsimplematch(vartok->next(), "d :");
7834         ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7835         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && !vartok->variable()->isConst());
7836 
7837         vartok = Token::findsimplematch(vartok->next(), "e :");
7838         ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7839         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && vartok->variable()->isConst());
7840 
7841         vartok = Token::findsimplematch(tokenizer.tokens(), "a . i");
7842         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7843 
7844         vartok = Token::findsimplematch(vartok, "i");
7845         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7846 
7847         vartok = Token::findsimplematch(vartok->next(), "b . i");
7848         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7849 
7850         vartok = Token::findsimplematch(vartok->next(), "i");
7851         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7852 
7853         vartok = Token::findsimplematch(vartok->next(), "c . i");
7854         ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7855 
7856         vartok = Token::findsimplematch(vartok->next(), "i");
7857         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7858 
7859         vartok = Token::findsimplematch(vartok->next(), "d . i");
7860         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7861 
7862         vartok = Token::findsimplematch(vartok->next(), "i");
7863         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7864 
7865         vartok = Token::findsimplematch(vartok->next(), "e . i");
7866         ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7867 
7868         vartok = Token::findsimplematch(vartok->next(), "i");
7869         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7870 
7871         vartok = Token::findsimplematch(vartok->next(), "i");
7872         ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7873     }
7874 
auto5()7875     void auto5() {
7876         GET_SYMBOL_DB("struct S { int i; };\n"
7877                       "int foo() {\n"
7878                       "    std::vector<S> vec(10);\n"
7879                       "    for (auto a : vec)\n"
7880                       "        a.i = 0;\n"
7881                       "    for (auto & b : vec)\n"
7882                       "        b.i = 0;\n"
7883                       "    for (const auto & c : vec)\n"
7884                       "        auto ci = c.i;\n"
7885                       "    for (auto * d : vec)\n"
7886                       "        d.i = 0;\n"
7887                       "    for (const auto * e : vec)\n"
7888                       "        auto ei = e->i;\n"
7889                       "    return vec[0].i;\n"
7890                       "}");
7891         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto a");
7892         ASSERT(autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7893         ASSERT(autotok && autotok->type() && autotok->type()->name() == "S");
7894 
7895         autotok = Token::findsimplematch(autotok->next(), "auto & b");
7896         ASSERT(autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7897         ASSERT(autotok && autotok->type() && autotok->type()->name() == "S");
7898 
7899         autotok = Token::findsimplematch(autotok->next(), "auto & c");
7900         ASSERT(autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7901         ASSERT(autotok && autotok->type() && autotok->type()->name() == "S");
7902 
7903         autotok = Token::findsimplematch(autotok->next(), "auto * d");
7904         ASSERT(autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7905         ASSERT(autotok && autotok->type() && autotok->type()->name() == "S");
7906 
7907         autotok = Token::findsimplematch(autotok->next(), "auto * e");
7908         ASSERT(autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
7909         ASSERT(autotok && autotok->type() && autotok->type()->name() == "S");
7910 
7911         vartok = Token::findsimplematch(tokenizer.tokens(), "a :");
7912         ASSERT(vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7913         ASSERT(vartok && vartok->variable() && !vartok->variable()->isReference() && !vartok->variable()->isPointer());
7914         ASSERT(vartok && vartok->variable() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7915 
7916         vartok = Token::findsimplematch(vartok->next(), "b :");
7917         ASSERT(vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7918         ASSERT(vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && !vartok->variable()->isConst());
7919 
7920         vartok = Token::findsimplematch(vartok->next(), "c :");
7921         ASSERT(vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7922         ASSERT(vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && vartok->variable()->isConst());
7923 
7924         vartok = Token::findsimplematch(vartok->next(), "d :");
7925         ASSERT(vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7926         ASSERT(vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && !vartok->variable()->isConst());
7927 
7928         vartok = Token::findsimplematch(vartok->next(), "e :");
7929         ASSERT(vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
7930         ASSERT(vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && vartok->variable()->isConst());
7931 
7932 
7933         vartok = Token::findsimplematch(tokenizer.tokens(), "a . i");
7934         ASSERT(vartok && vartok->variable() && !vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7935 
7936         vartok = Token::findsimplematch(vartok, "i");
7937         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7938 
7939         vartok = Token::findsimplematch(vartok->next(), "b . i");
7940         ASSERT(vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7941 
7942         vartok = Token::findsimplematch(vartok->next(), "i");
7943         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7944 
7945         vartok = Token::findsimplematch(vartok->next(), "c . i");
7946         ASSERT(vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7947 
7948         vartok = Token::findsimplematch(vartok->next(), "i");
7949         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7950 
7951         vartok = Token::findsimplematch(vartok->next(), "d . i");
7952         ASSERT(vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7953 
7954         vartok = Token::findsimplematch(vartok->next(), "i");
7955         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7956 
7957         vartok = Token::findsimplematch(vartok->next(), "e . i");
7958         ASSERT(vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
7959 
7960         vartok = Token::findsimplematch(vartok->next(), "i");
7961         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7962 
7963         vartok = Token::findsimplematch(vartok->next(), "i");
7964         ASSERT(vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
7965     }
7966 
auto6()7967     void auto6() {  // #7963 (segmentation fault)
7968         GET_SYMBOL_DB("class WebGLTransformFeedback final\n"
7969                       ": public nsWrapperCache\n"
7970                       ", public WebGLRefCountedObject < WebGLTransformFeedback >\n"
7971                       ", public LinkedListElement < WebGLTransformFeedback >\n"
7972                       "{\n"
7973                       "private :\n"
7974                       "std :: vector < IndexedBufferBinding > mIndexedBindings ;\n"
7975                       "} ;\n"
7976                       "struct IndexedBufferBinding\n"
7977                       "{\n"
7978                       "IndexedBufferBinding ( ) ;\n"
7979                       "} ;\n"
7980                       "const decltype ( WebGLTransformFeedback :: mBuffersForTF ) &\n"
7981                       "WebGLTransformFeedback :: BuffersForTF ( ) const\n"
7982                       "{\n"
7983                       "mBuffersForTF . clear ( ) ;\n"
7984                       "for ( const auto & cur : mIndexedBindings ) {}\n"
7985                       "return mBuffersForTF ;\n"
7986                       "}");
7987     }
7988 
auto7()7989     void auto7() {
7990         GET_SYMBOL_DB("struct Foo { int a; int b[10]; };\n"
7991                       "class Bar {\n"
7992                       "    Foo foo1;\n"
7993                       "    Foo foo2[10];\n"
7994                       "public:\n"
7995                       "    const Foo & getFoo1() { return foo1; }\n"
7996                       "    const Foo * getFoo2() { return foo2; }\n"
7997                       "};\n"
7998                       "int main() {\n"
7999                       "    Bar bar;\n"
8000                       "    auto v1 = bar.getFoo1().a;\n"
8001                       "    auto v2 = bar.getFoo1().b[0];\n"
8002                       "    auto v3 = bar.getFoo1().b;\n"
8003                       "    const auto v4 = bar.getFoo1().b;\n"
8004                       "    const auto * v5 = bar.getFoo1().b;\n"
8005                       "    auto v6 = bar.getFoo2()[0].a;\n"
8006                       "    auto v7 = bar.getFoo2()[0].b[0];\n"
8007                       "    auto v8 = bar.getFoo2()[0].b;\n"
8008                       "    const auto v9 = bar.getFoo2()[0].b;\n"
8009                       "    const auto * v10 = bar.getFoo2()[0].b;\n"
8010                       "    auto v11 = v1 + v2 + v3[0] + v4[0] + v5[0] + v6 + v7 + v8[0] + v9[0] + v10[0];\n"
8011                       "    return v11;\n"
8012                       "}");
8013         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto v1");
8014 
8015         // auto = int, v1 = int
8016         ASSERT(autotok);
8017         ASSERT(autotok->valueType());
8018         ASSERT_EQUALS(0, autotok->valueType()->constness);
8019         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8020         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8021         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8022         vartok = Token::findsimplematch(autotok, "v1 =");
8023         ASSERT(autotok);
8024         ASSERT(autotok->valueType());
8025         ASSERT_EQUALS(0, vartok->valueType()->constness);
8026         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8027         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8028         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8029 
8030         // auto = int, v2 = int
8031         autotok = Token::findsimplematch(autotok, "auto v2");
8032         ASSERT(autotok);
8033         ASSERT(autotok->valueType());
8034         ASSERT_EQUALS(0, autotok->valueType()->constness);
8035         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8036         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8037         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8038         vartok = Token::findsimplematch(autotok, "v2 =");
8039         ASSERT(autotok);
8040         ASSERT(autotok->valueType());
8041         ASSERT_EQUALS(0, vartok->valueType()->constness);
8042         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8043         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8044         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8045 
8046         // auto = const int *, v3 = const int * (const int[10])
8047         autotok = Token::findsimplematch(autotok, "auto v3");
8048         ASSERT(autotok);
8049         ASSERT(autotok->valueType());
8050         ASSERT_EQUALS(1, autotok->valueType()->constness);
8051         ASSERT_EQUALS(1, autotok->valueType()->pointer);
8052         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8053         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8054         vartok = Token::findsimplematch(autotok, "v3 =");
8055         ASSERT(autotok);
8056         ASSERT(autotok->valueType());
8057         ASSERT_EQUALS(1, vartok->valueType()->constness);
8058         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8059         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8060         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8061 
8062         // auto = int *, v4 = const int * (const int[10])
8063         autotok = Token::findsimplematch(autotok, "auto v4");
8064         ASSERT(autotok);
8065         ASSERT(autotok->valueType());
8066         TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
8067         ASSERT_EQUALS(1, autotok->valueType()->pointer);
8068         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8069         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8070         vartok = Token::findsimplematch(autotok, "v4 =");
8071         ASSERT(autotok);
8072         ASSERT(autotok->valueType());
8073         ASSERT_EQUALS(1, vartok->valueType()->constness);
8074         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8075         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8076         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8077 
8078         // auto = int, v5 = const int * (const int[10])
8079         autotok = Token::findsimplematch(autotok, "auto * v5");
8080         ASSERT(autotok);
8081         ASSERT(autotok->valueType());
8082         TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
8083         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8084         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8085         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8086         vartok = Token::findsimplematch(autotok, "v5 =");
8087         ASSERT(autotok);
8088         ASSERT(autotok->valueType());
8089         ASSERT_EQUALS(1, vartok->valueType()->constness);
8090         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8091         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8092         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8093 
8094         // auto = int, v6 = int
8095         autotok = Token::findsimplematch(autotok, "auto v6");
8096         ASSERT(autotok);
8097         ASSERT(autotok->valueType());
8098         ASSERT_EQUALS(0, autotok->valueType()->constness);
8099         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8100         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8101         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8102         vartok = Token::findsimplematch(autotok, "v6 =");
8103         ASSERT(autotok);
8104         ASSERT(autotok->valueType());
8105         ASSERT_EQUALS(0, vartok->valueType()->constness);
8106         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8107         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8108         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8109 
8110         // auto = int, v7 = int
8111         autotok = Token::findsimplematch(autotok, "auto v7");
8112         ASSERT(autotok);
8113         ASSERT(autotok->valueType());
8114         ASSERT_EQUALS(0, autotok->valueType()->constness);
8115         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8116         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8117         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8118         vartok = Token::findsimplematch(autotok, "v7 =");
8119         ASSERT(autotok);
8120         ASSERT(autotok->valueType());
8121         ASSERT_EQUALS(0, vartok->valueType()->constness);
8122         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8123         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8124         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8125 
8126         // auto = const int *, v8 = const int * (const int[10])
8127         autotok = Token::findsimplematch(autotok, "auto v8");
8128         ASSERT(autotok);
8129         ASSERT(autotok->valueType());
8130         ASSERT_EQUALS(1, autotok->valueType()->constness);
8131         ASSERT_EQUALS(1, autotok->valueType()->pointer);
8132         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8133         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8134         vartok = Token::findsimplematch(autotok, "v8 =");
8135         ASSERT(autotok);
8136         ASSERT(autotok->valueType());
8137         ASSERT_EQUALS(1, vartok->valueType()->constness);
8138         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8139         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8140         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8141 
8142         // auto = int *, v9 = const int * (const int[10])
8143         autotok = Token::findsimplematch(autotok, "auto v9");
8144         ASSERT(autotok);
8145         ASSERT(autotok->valueType());
8146         TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
8147         ASSERT_EQUALS(1, autotok->valueType()->pointer);
8148         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8149         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8150         vartok = Token::findsimplematch(autotok, "v9 =");
8151         ASSERT(autotok);
8152         ASSERT(autotok->valueType());
8153         ASSERT_EQUALS(1, vartok->valueType()->constness);
8154         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8155         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8156         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8157 
8158         // auto = int, v10 = const int * (const int[10])
8159         autotok = Token::findsimplematch(autotok, "auto * v10");
8160         ASSERT(autotok);
8161         ASSERT(autotok->valueType());
8162         TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
8163         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8164         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8165         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8166         vartok = Token::findsimplematch(autotok, "v10 =");
8167         ASSERT(autotok);
8168         ASSERT(autotok->valueType());
8169         ASSERT_EQUALS(1, vartok->valueType()->constness);
8170         ASSERT_EQUALS(1, vartok->valueType()->pointer);
8171         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8172         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8173 
8174         // auto = int, v11 = int
8175         autotok = Token::findsimplematch(autotok, "auto v11");
8176         ASSERT(autotok);
8177         ASSERT(autotok->valueType());
8178         ASSERT_EQUALS(0, autotok->valueType()->constness);
8179         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8180         ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
8181         ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
8182 
8183         vartok = autotok->next();
8184         ASSERT(autotok);
8185         ASSERT(autotok->valueType());
8186         ASSERT_EQUALS(0, vartok->valueType()->constness);
8187         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8188         ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
8189         ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
8190     }
8191 
auto8()8192     void auto8() {
8193         GET_SYMBOL_DB("std::vector<int> vec;\n"
8194                       "void foo() {\n"
8195                       "    for (auto it = vec.begin(); it != vec.end(); ++it) { }\n"
8196                       "}");
8197         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto it");
8198 
8199         ASSERT(autotok);
8200         ASSERT(autotok->valueType());
8201         ASSERT_EQUALS(0, autotok->valueType()->constness);
8202         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8203         ASSERT_EQUALS(ValueType::UNKNOWN_SIGN, autotok->valueType()->sign);
8204         ASSERT_EQUALS(ValueType::ITERATOR, autotok->valueType()->type);
8205 
8206         vartok = Token::findsimplematch(autotok, "it =");
8207         ASSERT(vartok);
8208         ASSERT(vartok->valueType());
8209         ASSERT_EQUALS(0, vartok->valueType()->constness);
8210         ASSERT_EQUALS(0, vartok->valueType()->pointer);
8211         ASSERT_EQUALS(ValueType::UNKNOWN_SIGN, vartok->valueType()->sign);
8212         ASSERT_EQUALS(ValueType::ITERATOR, vartok->valueType()->type);
8213     }
8214 
auto9()8215     void auto9() { // #8044 (segmentation fault)
8216         GET_SYMBOL_DB("class DHTTokenTracker {\n"
8217                       "  static const size_t SECRET_SIZE = 4;\n"
8218                       "  unsigned char secret_[2][SECRET_SIZE];\n"
8219                       "  void validateToken();\n"
8220                       "};\n"
8221                       "template <typename T> struct DerefEqual<T> derefEqual(const T& t) {\n"
8222                       "  return DerefEqual<T>(t);\n"
8223                       "}\n"
8224                       "template <typename T>\n"
8225                       "struct RefLess {\n"
8226                       "  bool operator()(const std::shared_ptr<T>& lhs,\n"
8227                       "                  const std::shared_ptr<T>& rhs)\n"
8228                       "  {\n"
8229                       "    return lhs.get() < rhs.get();\n"
8230                       "  }\n"
8231                       "};\n"
8232                       "void DHTTokenTracker::validateToken()\n"
8233                       "{\n"
8234                       "  for (auto& elem : secret_) {\n"
8235                       "  }\n"
8236                       "}");
8237     }
8238 
auto10()8239     void auto10() { // #8020
8240         GET_SYMBOL_DB("void f() {\n"
8241                       "    std::vector<int> ints(4);\n"
8242                       "    auto iter = ints.begin() + (ints.size() - 1);\n"
8243                       "}");
8244         const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto iter");
8245 
8246         ASSERT(autotok);
8247         ASSERT(autotok->valueType());
8248         ASSERT_EQUALS(0, autotok->valueType()->constness);
8249         ASSERT_EQUALS(0, autotok->valueType()->pointer);
8250         ASSERT_EQUALS(ValueType::UNKNOWN_SIGN, autotok->valueType()->sign);
8251         ASSERT_EQUALS(ValueType::ITERATOR, autotok->valueType()->type);
8252     }
8253 
auto11()8254     void auto11() {
8255         GET_SYMBOL_DB("void f() {\n"
8256                       "  const auto v1 = 3;\n"
8257                       "  const auto *v2 = 0;\n"
8258                       "}");
8259 
8260         const Token *v1tok = Token::findsimplematch(tokenizer.tokens(), "v1");
8261         ASSERT(v1tok && v1tok->variable() && v1tok->variable()->isConst());
8262 
8263         const Token *v2tok = Token::findsimplematch(tokenizer.tokens(), "v2");
8264         ASSERT(v2tok && v2tok->variable() && !v2tok->variable()->isConst());
8265     }
8266 
auto12()8267     void auto12() {
8268         GET_SYMBOL_DB("void f(const std::string &x) {\n"
8269                       "  auto y = x;\n"
8270                       "  if (y.empty()) {}\n"
8271                       "}");
8272 
8273         const Token *tok;
8274 
8275         tok = Token::findsimplematch(tokenizer.tokens(), "y =");
8276         ASSERT(tok && tok->valueType() && tok->valueType()->container);
8277 
8278         tok = Token::findsimplematch(tokenizer.tokens(), "y .");
8279         ASSERT(tok && tok->valueType() && tok->valueType()->container);
8280     }
8281 
auto13()8282     void auto13() {
8283         GET_SYMBOL_DB("uint8_t *get();\n"
8284                       "\n"
8285                       "uint8_t *test()\n"
8286                       "{\n"
8287                       "    auto *next = get();\n"
8288                       "    return next;\n"
8289                       "}");
8290 
8291         const Token *tok;
8292 
8293         tok = Token::findsimplematch(tokenizer.tokens(), "return")->next();
8294         ASSERT(tok);
8295         ASSERT(tok->valueType());
8296         ASSERT(tok->valueType()->pointer);
8297         ASSERT(tok->variable()->valueType());
8298         ASSERT(tok->variable()->valueType()->pointer);
8299     }
8300 
auto14()8301     void auto14() { // #9892 - crash in Token::declType
8302         GET_SYMBOL_DB("static void foo() {\n"
8303                       "    auto combo = widget->combo = new Combo{};\n"
8304                       "    combo->addItem();\n"
8305                       "}");
8306 
8307         const Token *tok;
8308 
8309         tok = Token::findsimplematch(tokenizer.tokens(), "combo =");
8310         ASSERT(tok && !tok->valueType());
8311     }
8312 
auto15()8313     void auto15() {
8314         GET_SYMBOL_DB("auto var1{3};\n"
8315                       "auto var2{4.0};");
8316         ASSERT_EQUALS(3, db->variableList().size());
8317         const Variable *var1 = db->variableList()[1];
8318         ASSERT(var1->valueType());
8319         ASSERT_EQUALS(ValueType::Type::INT, var1->valueType()->type);
8320         const Variable *var2 = db->variableList()[2];
8321         ASSERT(var2->valueType());
8322         ASSERT_EQUALS(ValueType::Type::DOUBLE, var2->valueType()->type);
8323     }
8324 
unionWithConstructor()8325     void unionWithConstructor() {
8326         GET_SYMBOL_DB("union Fred {\n"
8327                       "    Fred(int x) : i(x) { }\n"
8328                       "    Fred(float x) : f(x) { }\n"
8329                       "    int i;\n"
8330                       "    float f;\n"
8331                       "};");
8332 
8333         ASSERT_EQUALS("", errout.str());
8334 
8335         const Token *f = Token::findsimplematch(tokenizer.tokens(), "Fred ( int");
8336         ASSERT(f && f->function() && f->function()->tokenDef->linenr() == 2);
8337 
8338         f = Token::findsimplematch(tokenizer.tokens(), "Fred ( float");
8339         ASSERT(f && f->function() && f->function()->tokenDef->linenr() == 3);
8340     }
8341 
incomplete_type()8342     void incomplete_type() {
8343         GET_SYMBOL_DB("template<class _Ty,\n"
8344                       "  class _Alloc = std::allocator<_Ty>>\n"
8345                       "  class SLSurfaceLayerData\n"
8346                       "  : public _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>\n"
8347                       "{     // varying size array of values\n"
8348                       "\n"
8349                       "  using reverse_iterator = _STD reverse_iterator<iterator>;\n"
8350                       "  using const_reverse_iterator = _STD reverse_iterator<const_iterator>;\n"
8351                       "  const_reverse_iterator crend() const noexcept\n"
8352                       "  {   // return iterator for end of reversed nonmutable sequence\n"
8353                       "    return (rend());\n"
8354                       "  }\n"
8355                       "};");
8356 
8357         ASSERT_EQUALS("", errout.str());
8358     }
8359 };
8360 
8361 REGISTER_TEST(TestSymbolDatabase)
8362