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 = ⁢ 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 = ⁢ 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