1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
|
// Cppcheck - A tool for static C/C++ code analysis
// Copyright (C) 2007-2024 Cppcheck team.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "clangimport.h"
#include "platform.h"
#include "settings.h"
#include "symboldatabase.h"
#include "token.h"
#include "tokenize.h"
#include "fixture.h"
#include <cstdint>
#include <list>
#include <sstream>
#include <string>
#include <vector>
class TestClangImport : public TestFixture {
public:
TestClangImport()
: TestFixture("TestClangImport") {}
private:
void run() override {
TEST_CASE(breakStmt);
TEST_CASE(callExpr);
TEST_CASE(caseStmt1);
TEST_CASE(characterLiteral);
TEST_CASE(class1);
TEST_CASE(classTemplateDecl1);
TEST_CASE(classTemplateDecl2);
TEST_CASE(conditionalExpr);
TEST_CASE(compoundAssignOperator);
TEST_CASE(continueStmt);
TEST_CASE(cstyleCastExpr);
TEST_CASE(cxxBoolLiteralExpr);
TEST_CASE(cxxConstructorDecl1);
TEST_CASE(cxxConstructorDecl2);
TEST_CASE(cxxConstructExpr1);
TEST_CASE(cxxConstructExpr2);
TEST_CASE(cxxConstructExpr3);
TEST_CASE(cxxDeleteExpr);
TEST_CASE(cxxDestructorDecl);
TEST_CASE(cxxForRangeStmt1);
TEST_CASE(cxxForRangeStmt2);
TEST_CASE(cxxFunctionalCastExpr);
TEST_CASE(cxxMemberCall);
TEST_CASE(cxxMethodDecl1);
TEST_CASE(cxxMethodDecl2);
TEST_CASE(cxxMethodDecl3);
TEST_CASE(cxxMethodDecl4);
TEST_CASE(cxxNewExpr1);
TEST_CASE(cxxNewExpr2);
TEST_CASE(cxxNullPtrLiteralExpr);
TEST_CASE(cxxOperatorCallExpr);
TEST_CASE(cxxRecordDecl1);
TEST_CASE(cxxRecordDecl2);
TEST_CASE(cxxRecordDeclDerived);
TEST_CASE(cxxStaticCastExpr1);
TEST_CASE(cxxStaticCastExpr2);
TEST_CASE(cxxStaticCastExpr3);
TEST_CASE(cxxStdInitializerListExpr);
TEST_CASE(cxxThrowExpr);
TEST_CASE(defaultStmt);
TEST_CASE(doStmt);
TEST_CASE(enumDecl1);
TEST_CASE(enumDecl2);
TEST_CASE(enumDecl3);
TEST_CASE(enumDecl4);
TEST_CASE(forStmt);
TEST_CASE(funcdecl1);
TEST_CASE(funcdecl2);
TEST_CASE(funcdecl3);
TEST_CASE(funcdecl4);
TEST_CASE(funcdecl5);
TEST_CASE(funcdecl6);
TEST_CASE(functionTemplateDecl1);
TEST_CASE(functionTemplateDecl2);
TEST_CASE(initListExpr);
TEST_CASE(ifelse);
TEST_CASE(ifStmt);
TEST_CASE(labelStmt);
TEST_CASE(memberExpr);
TEST_CASE(namespaceDecl1);
TEST_CASE(namespaceDecl2);
TEST_CASE(recordDecl1);
TEST_CASE(recordDecl2);
TEST_CASE(switchStmt);
TEST_CASE(typedefDeclPrologue);
TEST_CASE(unaryExprOrTypeTraitExpr1);
TEST_CASE(unaryExprOrTypeTraitExpr2);
TEST_CASE(unaryOperator);
TEST_CASE(vardecl1);
TEST_CASE(vardecl2);
TEST_CASE(vardecl3);
TEST_CASE(vardecl4);
TEST_CASE(vardecl5);
TEST_CASE(vardecl6);
TEST_CASE(vardecl7);
TEST_CASE(whileStmt1);
TEST_CASE(whileStmt2);
TEST_CASE(tokenIndex);
TEST_CASE(symbolDatabaseEnum1);
TEST_CASE(symbolDatabaseFunction1);
TEST_CASE(symbolDatabaseFunction2);
TEST_CASE(symbolDatabaseFunction3);
TEST_CASE(symbolDatabaseFunctionConst);
TEST_CASE(symbolDatabaseVariableRef);
TEST_CASE(symbolDatabaseVariableRRef);
TEST_CASE(symbolDatabaseVariablePointerRef);
TEST_CASE(symbolDatabaseNodeType1);
TEST_CASE(symbolDatabaseForVariable);
TEST_CASE(stdinLoc);
TEST_CASE(valueFlow1);
TEST_CASE(valueFlow2);
TEST_CASE(valueType1);
TEST_CASE(valueType2);
TEST_CASE(crash);
}
std::string parse(const char clang[]) {
const Settings settings = settingsBuilder().clang().build();
Tokenizer tokenizer(settings, *this);
std::istringstream istr(clang);
clangimport::parseClangAstDump(tokenizer, istr);
if (!tokenizer.tokens()) {
return std::string();
}
return tokenizer.tokens()->stringifyList(true, false, false, false, false);
}
void breakStmt() {
const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x2c31c40 <col:12, col:34>\n"
" `-WhileStmt 0x2c31c20 <col:14, col:24>\n"
" |-<<<NULL>>>\n"
" |-IntegerLiteral 0x2c31bf8 <col:21> 'int' 0\n"
" `-BreakStmt 0x3687c18 <col:24>";
ASSERT_EQUALS("void foo ( ) { while ( 0 ) { break ; } }", parse(clang));
}
void callExpr() {
const char clang[] = "`-FunctionDecl 0x2444b60 <1.c:1:1, line:8:1> line:1:6 foo 'void (int)'\n"
" |-ParmVarDecl 0x2444aa0 <col:10, col:14> col:14 used x 'int'\n"
" `-CompoundStmt 0x2444e00 <col:17, line:8:1>\n"
" `-CallExpr 0x7f5a6c04b158 <line:1:16, col:60> 'bool'\n"
" |-ImplicitCastExpr 0x7f5a6c04b140 <col:16, col:23> 'bool (*)(const Token *, const char *, int)' <FunctionToPointerDecay>\n"
" | `-DeclRefExpr 0x7f5a6c04b0a8 <col:16, col:23> 'bool (const Token *, const char *, int)' lvalue CXXMethod 0x43e5600 'Match' 'bool (const Token *, const char *, int)'\n"
" |-ImplicitCastExpr 0x7f5a6c04b1c8 <col:29> 'const Token *' <NoOp>\n"
" | `-ImplicitCastExpr 0x7f5a6c04b1b0 <col:29> 'Token *' <LValueToRValue>\n"
" | `-DeclRefExpr 0x7f5a6c04b0e0 <col:29> 'Token *' lvalue Var 0x7f5a6c045968 'tokAfterCondition' 'Token *'\n"
" |-ImplicitCastExpr 0x7f5a6c04b1e0 <col:48> 'const char *' <ArrayToPointerDecay>\n"
" | `-StringLiteral 0x7f5a6c04b108 <col:48> 'const char [11]' lvalue \"%name% : {\"\n"
" `-CXXDefaultArgExpr 0x7f5a6c04b1f8 <<invalid sloc>> 'int'\n";
ASSERT_EQUALS("void foo ( int x@1 ) { Match ( tokAfterCondition , \"%name% : {\" ) ; }", parse(clang));
}
void caseStmt1() {
const char clang[] = "`-FunctionDecl 0x2444b60 <1.c:1:1, line:8:1> line:1:6 foo 'void (int)'\n"
" |-ParmVarDecl 0x2444aa0 <col:10, col:14> col:14 used x 'int'\n"
" `-CompoundStmt 0x2444e00 <col:17, line:8:1>\n"
" `-SwitchStmt 0x2444c88 <line:2:5, line:7:5>\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" |-ImplicitCastExpr 0x2444c70 <line:2:13> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x2444c48 <col:13> 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n"
" `-CompoundStmt 0x2444de0 <col:16, line:7:5>\n"
" |-CaseStmt 0x2444cd8 <line:3:9, line:5:15>\n"
" | |-IntegerLiteral 0x2444cb8 <line:3:14> 'int' 16\n"
" | |-<<<NULL>>>\n"
" | `-CaseStmt 0x2444d30 <line:4:9, line:5:15>\n"
" | |-IntegerLiteral 0x2444d10 <line:4:14> 'int' 32\n"
" | |-<<<NULL>>>\n"
" | `-BinaryOperator 0x2444db0 <line:5:13, col:15> 'int' '='\n"
" | |-DeclRefExpr 0x2444d68 <col:13> 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n"
" | `-IntegerLiteral 0x2444d90 <col:15> 'int' 123\n"
" `-BreakStmt 0x2444dd8 <line:6:13>";
ASSERT_EQUALS("void foo ( int x@1 ) { switch ( x@1 ) { case 16 : case 32 : x@1 = 123 ; break ; } }", parse(clang));
}
void characterLiteral() {
const char clang[] = "`-VarDecl 0x3df8608 <a.cpp:1:1, col:10> col:6 c 'char' cinit\n"
" `-CharacterLiteral 0x3df86a8 <col:10> 'char' 120";
ASSERT_EQUALS("char c@1 = 'x' ;", parse(clang));
}
void class1() {
const char clang[] = "`-CXXRecordDecl 0x274c638 <a.cpp:1:1, col:25> col:7 class C definition\n"
" |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
" | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n"
" | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
" | |-MoveConstructor exists simple trivial needs_implicit\n"
" | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n"
" | |-MoveAssignment exists simple trivial needs_implicit\n"
" | `-Destructor simple irrelevant trivial needs_implicit\n"
" |-CXXRecordDecl 0x274c758 <col:1, col:7> col:7 implicit class C\n"
" `-CXXMethodDecl 0x274c870 <col:11, col:23> col:16 foo 'void ()'\n"
" `-CompoundStmt 0x274c930 <col:22, col:23>";
ASSERT_EQUALS("class C { void foo ( ) { } } ;", parse(clang));
}
void classTemplateDecl1() {
const char clang[] = "`-ClassTemplateDecl 0x29d1748 <a.cpp:1:1, col:59> col:25 C\n"
" |-TemplateTypeParmDecl 0x29d15f8 <col:10, col:16> col:16 referenced class depth 0 index 0 T\n"
" `-CXXRecordDecl 0x29d16b0 <col:19, col:59> col:25 class C definition\n"
" |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
" | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n"
" | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
" | |-MoveConstructor exists simple trivial needs_implicit\n"
" | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n"
" | |-MoveAssignment exists simple trivial needs_implicit\n"
" | `-Destructor simple irrelevant trivial needs_implicit\n"
" |-CXXRecordDecl 0x29d19b0 <col:19, col:25> col:25 implicit class C\n"
" |-AccessSpecDecl 0x29d1a48 <col:29, col:35> col:29 public\n"
" `-CXXMethodDecl 0x29d1b20 <col:37, col:57> col:39 foo 'T ()'\n"
" `-CompoundStmt 0x29d1c18 <col:45, col:57>\n"
" `-ReturnStmt 0x29d1c00 <col:47, col:54>\n"
" `-IntegerLiteral 0x29d1be0 <col:54> 'int' 0";
ASSERT_EQUALS("", parse(clang));
}
void classTemplateDecl2() {
const char clang[] = "|-ClassTemplateDecl 0x244e748 <a.cpp:1:1, col:59> col:25 C\n"
"| |-TemplateTypeParmDecl 0x244e5f8 <col:10, col:16> col:16 referenced class depth 0 index 0 T\n"
"| |-CXXRecordDecl 0x244e6b0 <col:19, col:59> col:25 class C definition\n"
"| | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
"| | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n"
"| | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | | |-MoveConstructor exists simple trivial needs_implicit\n"
"| | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | | |-MoveAssignment exists simple trivial needs_implicit\n"
"| | | `-Destructor simple irrelevant trivial needs_implicit\n"
"| | |-CXXRecordDecl 0x244e9b0 <col:19, col:25> col:25 implicit class C\n"
"| | |-AccessSpecDecl 0x244ea48 <col:29, col:35> col:29 public\n"
"| | `-CXXMethodDecl 0x244eb20 <col:37, col:57> col:39 foo 'T ()'\n"
"| | `-CompoundStmt 0x244ec18 <col:45, col:57>\n"
"| | `-ReturnStmt 0x244ec00 <col:47, col:54>\n"
"| | `-IntegerLiteral 0x244ebe0 <col:54> 'int' 0\n"
"| `-ClassTemplateSpecializationDecl 0x244ed78 <col:1, col:59> col:25 class C definition\n"
"| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
"| | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr\n"
"| | |-CopyConstructor simple trivial has_const_param implicit_has_const_param\n"
"| | |-MoveConstructor exists simple trivial\n"
"| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveAssignment exists simple trivial needs_implicit\n"
"| | `-Destructor simple irrelevant trivial needs_implicit\n"
"| |-TemplateArgument type 'int'\n"
"| |-CXXRecordDecl 0x244eff0 prev 0x244ed78 <col:19, col:25> col:25 implicit class C\n"
"| |-AccessSpecDecl 0x244f088 <col:29, col:35> col:29 public\n"
"| |-CXXMethodDecl 0x244f160 <col:37, col:57> col:39 used foo 'int ()'\n"
"| | `-CompoundStmt 0x247cb40 <col:45, col:57>\n"
"| | `-ReturnStmt 0x247cb28 <col:47, col:54>\n"
"| | `-IntegerLiteral 0x244ebe0 <col:54> 'int' 0\n"
"| |-CXXConstructorDecl 0x247c540 <col:25> col:25 implicit used constexpr C 'void () noexcept' inline default trivial\n"
"| | `-CompoundStmt 0x247ca00 <col:25>\n"
"| |-CXXConstructorDecl 0x247c658 <col:25> col:25 implicit constexpr C 'void (const C<int> &)' inline default trivial noexcept-unevaluated 0x247c658\n"
"| | `-ParmVarDecl 0x247c790 <col:25> col:25 'const C<int> &'\n"
"| `-CXXConstructorDecl 0x247c828 <col:25> col:25 implicit constexpr C 'void (C<int> &&)' inline default trivial noexcept-unevaluated 0x247c828\n"
"| `-ParmVarDecl 0x247c960 <col:25> col:25 'C<int> &&'\n";
ASSERT_EQUALS("class C { int foo ( ) { return 0 ; } C ( ) { } C ( const C<int> & ) = default ; C ( C<int> && ) = default ; } ;", parse(clang));
}
void conditionalExpr() {
const char clang[] = "`-VarDecl 0x257cc88 <a.cpp:4:1, col:13> col:5 x 'int' cinit\n"
" `-ConditionalOperator 0x257cda8 <col:9, col:13> 'int'\n"
" |-ImplicitCastExpr 0x257cd60 <col:9> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x257cce8 <col:9> 'int' lvalue Var 0x257cae0 'a' 'int'\n"
" |-ImplicitCastExpr 0x257cd78 <col:11> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x257cd10 <col:11> 'int' lvalue Var 0x257cb98 'b' 'int'\n"
" `-ImplicitCastExpr 0x257cd90 <col:13> 'int' <LValueToRValue>\n"
" `-DeclRefExpr 0x257cd38 <col:13> 'int' lvalue Var 0x257cc10 'c' 'int'";
ASSERT_EQUALS("int x@1 = a ? b : c ;", parse(clang));
}
void compoundAssignOperator() {
const char clang[] = "`-FunctionDecl 0x3570690 <1.cpp:2:1, col:25> col:6 f 'void ()'\n"
" `-CompoundStmt 0x3570880 <col:10, col:25>\n"
" `-CompoundAssignOperator 0x3570848 <col:19, col:22> 'int' lvalue '+=' ComputeLHSTy='int' ComputeResultTy='int'\n"
" |-DeclRefExpr 0x3570800 <col:19> 'int' lvalue Var 0x3570788 'x' 'int'\n"
" `-IntegerLiteral 0x3570828 <col:22> 'int' 1";
ASSERT_EQUALS("void f ( ) { x += 1 ; }", parse(clang));
}
void continueStmt() {
const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x2c31c40 <col:12, col:34>\n"
" `-WhileStmt 0x2c31c20 <col:14, col:24>\n"
" |-<<<NULL>>>\n"
" |-IntegerLiteral 0x2c31bf8 <col:21> 'int' 0\n"
" `-ContinueStmt 0x2c31c18 <col:24>";
ASSERT_EQUALS("void foo ( ) { while ( 0 ) { continue ; } }", parse(clang));
}
void cstyleCastExpr() {
const char clang[] = "`-VarDecl 0x2336aa0 <1.c:1:1, col:14> col:5 x 'int' cinit\n"
" `-CStyleCastExpr 0x2336b70 <col:9, col:14> 'int' <NoOp>\n"
" `-CharacterLiteral 0x2336b40 <col:14> 'int' 97";
ASSERT_EQUALS("int x@1 = ( int ) 'a' ;", parse(clang));
}
void cxxBoolLiteralExpr() {
const char clang[] = "`-VarDecl 0x3940608 <a.cpp:1:1, col:10> col:6 x 'bool' cinit\n"
" `-CXXBoolLiteralExpr 0x39406a8 <col:10> 'bool' true";
ASSERT_EQUALS("bool x@1 = true ;", parse(clang));
}
void cxxConstructorDecl1() {
const char clang[] = "|-CXXConstructorDecl 0x428e890 <a.cpp:11:1, col:24> col:11 C 'void ()'\n"
"| `-CompoundStmt 0x428ea58 <col:15, col:24>\n"
"| `-BinaryOperator 0x428ea30 <col:17, col:21> 'int' lvalue '='\n"
"| |-MemberExpr 0x428e9d8 <col:17> 'int' lvalue ->x 0x428e958\n"
"| | `-CXXThisExpr 0x428e9c0 <col:17> 'C *' this\n"
"| `-IntegerLiteral 0x428ea10 <col:21> 'int' 0\n"
"`-FieldDecl 0x428e958 <col:26, col:30> col:30 referenced x 'int'";
ASSERT_EQUALS("C ( ) { this . x@1 = 0 ; } int x@1", parse(clang));
}
void cxxConstructorDecl2() {
const char clang[] = "`-CXXConstructorDecl 0x1c208c0 <a.cpp:1:11> col:11 implicit constexpr basic_string 'void (std::basic_string<char> &&)' inline default trivial noexcept-unevaluated 0x1c208c0\n"
" `-ParmVarDecl 0x1c209f0 <col:11> col:11 'std::basic_string<char> &&'";
ASSERT_EQUALS("basic_string ( std::basic_string<char> && ) = default ;", parse(clang));
}
void cxxConstructExpr1() {
const char clang[] = "`-FunctionDecl 0x2dd7940 <a.cpp:2:1, col:30> col:5 f 'Foo (Foo)'\n"
" |-ParmVarDecl 0x2dd7880 <col:7, col:11> col:11 used foo 'Foo'\n"
" `-CompoundStmt 0x2dd80c0 <col:16, col:30>\n"
" `-ReturnStmt 0x2dd80a8 <col:18, col:25>\n"
" `-CXXConstructExpr 0x2dd8070 <col:25> 'Foo' 'void (Foo &&) noexcept'\n"
" `-ImplicitCastExpr 0x2dd7f28 <col:25> 'Foo' xvalue <NoOp>\n"
" `-DeclRefExpr 0x2dd7a28 <col:25> 'Foo' lvalue ParmVar 0x2dd7880 'foo' 'Foo'";
ASSERT_EQUALS("Foo f ( Foo foo@1 ) { return foo@1 ; }", parse(clang));
}
void cxxConstructExpr2() {
const char clang[] = "`-FunctionDecl 0x3e44180 <1.cpp:2:1, col:30> col:13 f 'std::string ()'\n"
" `-CompoundStmt 0x3e4cb80 <col:17, col:30>\n"
" `-ReturnStmt 0x3e4cb68 <col:19, col:27>\n"
" `-CXXConstructExpr 0x3e4cb38 <col:26, col:27> 'std::string':'std::__cxx11::basic_string<char>' '....' list";
ASSERT_EQUALS("std :: string f ( ) { return std :: string ( ) ; }", parse(clang));
}
void cxxConstructExpr3() {
const char clang[] = "`-FunctionDecl 0x2c585b8 <1.cpp:4:1, col:39> col:6 f 'void ()'\n"
" `-CompoundStmt 0x2c589d0 <col:10, col:39>\n"
" |-DeclStmt 0x2c586d0 <col:12, col:19>\n"
" | `-VarDecl 0x2c58670 <col:12, col:18> col:18 used p 'char *'\n"
" `-DeclStmt 0x2c589b8 <col:21, col:37>\n"
" `-VarDecl 0x2c58798 <col:21, col:36> col:33 s 'std::string':'std::__cxx11::basic_string<char>' callinit\n"
" `-ExprWithCleanups 0x2c589a0 <col:33, col:36> 'std::string':'std::__cxx11::basic_string<char>'\n"
" `-CXXConstructExpr 0x2c58960 <col:33, col:36> 'std::string':'std::__cxx11::basic_string<char>' 'void (const char *, const std::allocator<char> &)'\n"
" |-ImplicitCastExpr 0x2c58870 <col:35> 'const char *' <NoOp>\n"
" | `-ImplicitCastExpr 0x2c58858 <col:35> 'char *' <LValueToRValue>\n"
" | `-DeclRefExpr 0x2c58750 <col:35> 'char *' lvalue Var 0x2c58670 'p' 'char *'\n"
" `-CXXDefaultArgExpr 0x2c58940 <<invalid sloc>> 'const std::allocator<char>':'const std::allocator<char>' lvalue\n";
ASSERT_EQUALS("void f ( ) { char * p@1 ; std :: string s@2 ( p@1 ) ; }", parse(clang));
}
void cxxDeleteExpr() {
const char clang[] = "|-FunctionDecl 0x2e0e740 <1.cpp:1:1, col:28> col:6 f 'void (int *)'\n"
"| |-ParmVarDecl 0x2e0e680 <col:8, col:13> col:13 used p 'int *'\n"
"| `-CompoundStmt 0x2e0ee70 <col:16, col:28>\n"
"| `-CXXDeleteExpr 0x2e0ee48 <col:18, col:25> 'void' Function 0x2e0ebb8 'operator delete' 'void (void *) noexcept'\n"
"| `-ImplicitCastExpr 0x2e0e850 <col:25> 'int *' <LValueToRValue>\n"
"| `-DeclRefExpr 0x2e0e828 <col:25> 'int *' lvalue ParmVar 0x2e0e680 'p' 'int *'";
ASSERT_EQUALS("void f ( int * p@1 ) { delete p@1 ; }", parse(clang));
}
void cxxDestructorDecl() {
const char clang[] = "`-CXXRecordDecl 0x8ecd60 <1.cpp:1:1, line:4:1> line:1:8 struct S definition\n"
" `-CXXDestructorDecl 0x8ed088 <line:3:3, col:9> col:3 ~S 'void () noexcept'\n"
" `-CompoundStmt 0x8ed1a8 <col:8, col:9>";
ASSERT_EQUALS("struct S { ~S ( ) { } } ;", parse(clang));
}
void cxxForRangeStmt1() {
const char clang[] = "`-FunctionDecl 0x4280820 <a.cpp:4:1, line:8:1> line:4:6 foo 'void ()'\n"
" `-CompoundStmt 0x42810f0 <col:12, line:8:1>\n"
" `-CXXForRangeStmt 0x4281090 <line:5:3, line:7:3>\n"
" |-DeclStmt 0x4280c30 <line:5:17>\n"
" | `-VarDecl 0x42809c8 <col:17> col:17 implicit referenced __range1 'char const (&)[6]' cinit\n"
" | `-DeclRefExpr 0x42808c0 <col:17> 'const char [6]' lvalue Var 0x4280678 'hello' 'const char [6]'\n"
" |-DeclStmt 0x4280ef8 <col:15>\n"
" | `-VarDecl 0x4280ca8 <col:15> col:15 implicit used __begin1 'const char *':'const char *' cinit\n"
" | `-ImplicitCastExpr 0x4280e10 <col:15> 'const char *' <ArrayToPointerDecay>\n"
" | `-DeclRefExpr 0x4280c48 <col:15> 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n"
" |-DeclStmt 0x4280f10 <col:15>\n"
" | `-VarDecl 0x4280d18 <col:15, col:17> col:15 implicit used __end1 'const char *':'const char *' cinit\n"
" | `-BinaryOperator 0x4280e60 <col:15, col:17> 'const char *' '+'\n"
" | |-ImplicitCastExpr 0x4280e48 <col:15> 'const char *' <ArrayToPointerDecay>\n"
" | | `-DeclRefExpr 0x4280c70 <col:15> 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n"
" | `-IntegerLiteral 0x4280e28 <col:17> 'long' 6\n"
" |-BinaryOperator 0x4280fa8 <col:15> 'bool' '!='\n"
" | |-ImplicitCastExpr 0x4280f78 <col:15> 'const char *':'const char *' <LValueToRValue>\n"
" | | `-DeclRefExpr 0x4280f28 <col:15> 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n"
" | `-ImplicitCastExpr 0x4280f90 <col:15> 'const char *':'const char *' <LValueToRValue>\n"
" | `-DeclRefExpr 0x4280f50 <col:15> 'const char *':'const char *' lvalue Var 0x4280d18 '__end1' 'const char *':'const char *'\n"
" |-UnaryOperator 0x4280ff8 <col:15> 'const char *':'const char *' lvalue prefix '++'\n"
" | `-DeclRefExpr 0x4280fd0 <col:15> 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n"
" |-DeclStmt 0x4280958 <col:8, col:22>\n"
" | `-VarDecl 0x42808f8 <col:8, col:15> col:13 c1 'char' cinit\n"
" | `-ImplicitCastExpr 0x4281078 <col:15> 'char' <LValueToRValue>\n"
" | `-UnaryOperator 0x4281058 <col:15> 'const char' lvalue prefix '*' cannot overflow\n"
" | `-ImplicitCastExpr 0x4281040 <col:15> 'const char *':'const char *' <LValueToRValue>\n"
" | `-DeclRefExpr 0x4281018 <col:15> 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n"
" `-CompoundStmt 0x42810e0 <col:24, line:7:3>";
ASSERT_EQUALS("void foo ( ) { for ( char c1@1 : hello ) { } }",
parse(clang));
}
void cxxForRangeStmt2() {
// clang 9
const char clang[] = "`-FunctionDecl 0xc15d98 <a.cpp:3:1, col:36> col:6 foo 'void ()'\n"
" `-CompoundStmt 0xc16668 <col:12, col:36>\n"
" `-CXXForRangeStmt 0xc165f8 <col:14, col:34>\n"
" |-<<<NULL>>>\n"
" |-DeclStmt 0xc161c0 <col:25>\n"
" | `-VarDecl 0xc15f48 <col:25> col:25 implicit referenced __range1 'int const (&)[4]' cinit\n"
" | `-DeclRefExpr 0xc15e38 <col:25> 'const int [4]' lvalue Var 0xc15ac0 'values' 'const int [4]'\n"
" |-DeclStmt 0xc16498 <col:24>\n"
" | `-VarDecl 0xc16228 <col:24> col:24 implicit used __begin1 'const int *':'const int *' cinit\n"
" | `-ImplicitCastExpr 0xc163b0 <col:24> 'const int *' <ArrayToPointerDecay>\n"
" | `-DeclRefExpr 0xc161d8 <col:24> 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n"
" |-DeclStmt 0xc164b0 <col:24>\n"
" | `-VarDecl 0xc162a0 <col:24, col:25> col:24 implicit used __end1 'const int *':'const int *' cinit\n"
" | `-BinaryOperator 0xc16400 <col:24, col:25> 'const int *' '+'\n"
" | |-ImplicitCastExpr 0xc163e8 <col:24> 'const int *' <ArrayToPointerDecay>\n"
" | | `-DeclRefExpr 0xc161f8 <col:24> 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n"
" | `-IntegerLiteral 0xc163c8 <col:25> 'long' 4\n"
" |-BinaryOperator 0xc16538 <col:24> 'bool' '!='\n"
" | |-ImplicitCastExpr 0xc16508 <col:24> 'const int *':'const int *' <LValueToRValue>\n"
" | | `-DeclRefExpr 0xc164c8 <col:24> 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" | `-ImplicitCastExpr 0xc16520 <col:24> 'const int *':'const int *' <LValueToRValue>\n"
" | `-DeclRefExpr 0xc164e8 <col:24> 'const int *':'const int *' lvalue Var 0xc162a0 '__end1' 'const int *':'const int *'\n"
" |-UnaryOperator 0xc16578 <col:24> 'const int *':'const int *' lvalue prefix '++'\n"
" | `-DeclRefExpr 0xc16558 <col:24> 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" |-DeclStmt 0xc15ed8 <col:19, col:31>\n"
" | `-VarDecl 0xc15e70 <col:19, col:24> col:23 v 'int' cinit\n"
" | `-ImplicitCastExpr 0xc165e0 <col:24> 'int' <LValueToRValue>\n"
" | `-UnaryOperator 0xc165c8 <col:24> 'const int' lvalue prefix '*' cannot overflow\n"
" | `-ImplicitCastExpr 0xc165b0 <col:24> 'const int *':'const int *' <LValueToRValue>\n"
" | `-DeclRefExpr 0xc16590 <col:24> 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" `-CompoundStmt 0xc16658 <col:33, col:34>";
ASSERT_EQUALS("void foo ( ) { for ( int v@1 : values ) { } }",
parse(clang));
}
void cxxFunctionalCastExpr() {
const char clang[] = "`-FunctionDecl 0x156fe98 <a.cpp:1:1, line:3:1> line:1:5 main 'int (int, char **)'\n"
" |-ParmVarDecl 0x156fd00 <col:10, col:14> col:14 argc 'int'\n"
" |-ParmVarDecl 0x156fdb8 <col:20, col:27> col:27 argv 'char **'\n"
" `-CompoundStmt 0x1596410 <line:2:1, line:2:1>\n"
" |-DeclStmt 0x15946a8 <line:2:15, line:2:29>\n"
" | `-VarDecl 0x1570118 <line:2:15, line:2:28> col:11 used setCode 'MyVar<int>':'MyVar<int>' cinit\n"
" | `-ExprWithCleanups 0x1594690 <line:2:15, line:3:28> 'MyVar<int>':'MyVar<int>'\n"
" | `-CXXConstructExpr 0x1594660 <line:2:15, line:3:28> 'MyVar<int>':'MyVar<int>' 'void (MyVar<int> &&) noexcept' elidable\n"
" | `-MaterializeTemporaryExpr 0x1592b68 <line:2:15, line:3:28> 'MyVar<int>':'MyVar<int>' xvalue\n"
" | `-CXXFunctionalCastExpr 0x1592b40 <line:2:15, line:3:28> 'MyVar<int>':'MyVar<int>' functional cast to MyVar<int> <ConstructorConversion>\n"
" | `-CXXConstructExpr 0x15929f0 <line:2:15, line:3:28> 'MyVar<int>':'MyVar<int>' 'void (int)'\n"
" | `-IntegerLiteral 0x1570248 <col:27> 'int' 5\n";
ASSERT_EQUALS("int main ( int argc@1 , char * * argv@2 ) { MyVar<int> setCode@3 = MyVar<int> ( 5 ) ; }",
parse(clang));
}
void cxxMemberCall() {
const char clang[] = "`-FunctionDecl 0x320dc80 <a.cpp:2:1, col:33> col:6 bar 'void ()'\n"
" `-CompoundStmt 0x323bb08 <col:12, col:33>\n"
" |-DeclStmt 0x323ba40 <col:14, col:22>\n"
" | `-VarDecl 0x320df28 <col:14, col:21> col:21 used c 'C<int>':'C<int>' callinit\n"
" | `-CXXConstructExpr 0x323ba10 <col:21> 'C<int>':'C<int>' 'void () noexcept'\n"
" `-CXXMemberCallExpr 0x323bab8 <col:24, col:30> 'int':'int'\n"
" `-MemberExpr 0x323ba80 <col:24, col:26> '<bound member function type>' .foo 0x320e160\n"
" `-DeclRefExpr 0x323ba58 <col:24> 'C<int>':'C<int>' lvalue Var 0x320df28 'c' 'C<int>':'C<int>'";
ASSERT_EQUALS("void bar ( ) { C<int> c@1 ( C<int> ( ) ) ; c@1 . foo ( ) ; }", parse(clang));
}
void cxxMethodDecl1() {
const char clang[] = "|-CXXMethodDecl 0x55c786f5ad60 <a.cpp:56:5, col:179> col:10 analyzeFile '_Bool (const std::string &, const std::string &, const std::string &, unsigned long long, std::list<ErrorLogger::ErrorMessage> *)'\n"
"| |-ParmVarDecl 0x55c786f5a4c8 <col:22, col:41> col:41 buildDir 'const std::string &'\n"
"| |-ParmVarDecl 0x55c786f5a580 <col:51, col:70> col:70 sourcefile 'const std::string &'\n"
"| |-ParmVarDecl 0x55c786f5a638 <col:82, col:101> col:101 cfg 'const std::string &'\n"
"| |-ParmVarDecl 0x55c786f5a6a8 <col:106, col:125> col:125 checksum 'unsigned long long'\n"
"| |-ParmVarDecl 0x55c786f5ac00 <col:135, col:173> col:173 errors 'std::list<ErrorLogger::ErrorMessage> *'\n"
" `-CompoundStmt 0x0 <>";
ASSERT_EQUALS("_Bool analyzeFile ( const std :: string & buildDir@1 , const std :: string & sourcefile@2 , const std :: string & cfg@3 , unsigned long long checksum@4 , std::list<ErrorLogger::ErrorMessage> * errors@5 ) { }", parse(clang));
}
void cxxMethodDecl2() { // "unexpanded" template method
const char clang[] = "`-CXXMethodDecl 0x220ecb0 parent 0x21e4c28 prev 0x21e5338 <a.cpp:11:1, line:18:1> line:14:1 find 'const typename char_traits<_CharT>::char_type *(const char_traits::char_type *, int, const char_traits::char_type &)'\n"
" `-CompoundStmt 0x220ede0 <line:15:1, line:18:1>\n"
" `-ReturnStmt 0x220edd0 <line:17:5, col:12>\n"
" `-IntegerLiteral 0x220edb0 <col:12> 'int' 0";
ASSERT_EQUALS("", parse(clang));
}
void cxxMethodDecl3() {
const char clang[] = "|-CXXRecordDecl 0x21cca40 <2.cpp:2:1, line:4:1> line:2:7 class Fred definition\n"
"| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
"| | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n"
"| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveConstructor exists simple trivial needs_implicit\n"
"| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveAssignment exists simple trivial needs_implicit\n"
"| | `-Destructor simple irrelevant trivial needs_implicit\n"
"| |-CXXRecordDecl 0x21ccb58 <col:1, col:7> col:7 implicit class Fred\n"
"| `-CXXMethodDecl 0x21ccc68 <line:3:1, col:10> col:6 foo 'void ()'\n"
"`-CXXMethodDecl 0x21ccd60 parent 0x21cca40 prev 0x21ccc68 <line:6:1, col:19> col:12 foo 'void ()'\n"
" `-CompoundStmt 0x21cce50 <col:18, col:19>";
ASSERT_EQUALS("class Fred { void foo ( ) ; } ; void Fred :: foo ( ) { }", parse(clang));
}
void cxxMethodDecl4() {
const char clang[] = "|-ClassTemplateSpecializationDecl 0x15d82f8 <a.cpp:7:3, line:18:3> line:8:12 struct char_traits definition\n"
"| |-TemplateArgument type 'char'\n"
"| | `-BuiltinType 0x15984c0 'char'\n"
"| |-CXXRecordDecl 0x15d8520 <col:5, col:12> col:12 implicit struct char_traits\n"
"| |-CXXMethodDecl 0x15d8738 <line:12:7, line:16:7> line:13:7 move 'char *(char *)' static\n"
"| | |-ParmVarDecl 0x15d8630 <col:12, col:18> col:18 used __s1 'char *'\n"
"| | `-CompoundStmt 0x15d88e8 <line:14:7, line:16:7>\n";
ASSERT_EQUALS("struct char_traits<char> { static char * move ( char * __s1@1 ) { } } ;",
parse(clang));
}
void cxxNewExpr1() {
const char clang[] = "|-VarDecl 0x3a97680 <1.cpp:2:1, col:14> col:6 i 'int *' cinit\n"
"| `-CXXNewExpr 0x3a97d18 <col:10, col:14> 'int *' Function 0x3a97778 'operator new' 'void *(unsigned long)'\n"
"`-VarDecl 0x3a97d80 <line:3:1, col:21> col:6 j 'int *' cinit\n"
" `-CXXNewExpr 0x3a97e68 <col:10, col:21> 'int *' array Function 0x3a978c0 'operator new[]' 'void *(unsigned long)'\n"
" `-ImplicitCastExpr 0x3a97e18 <col:18> 'unsigned long' <IntegralCast>\n"
" `-IntegerLiteral 0x3a97de0 <col:18> 'int' 100";
ASSERT_EQUALS("int * i@1 = new int ; int * j@2 = new int [ 100 ] ;",
parse(clang));
}
void cxxNewExpr2() {
const char clang[] = "|-FunctionDecl 0x59a188 <a.cpp:7:1, line:9:1> line:7:11 f 'struct S *()'\n"
"| `-CompoundStmt 0x5c4318 <col:15, line:9:1>\n"
"| `-ReturnStmt 0x5c4308 <line:8:3, col:14>\n"
"| `-CXXNewExpr 0x5c42c8 <col:10, col:14> 'S *' Function 0x59a378 'operator new' 'void *(unsigned long)'\n"
"| `-CXXConstructExpr 0x5c42a0 <col:14> 'S' 'void () noexcept'";
ASSERT_EQUALS("struct S * f ( ) { return new S ( ) ; }",
parse(clang));
}
void cxxNullPtrLiteralExpr() {
const char clang[] = "`-VarDecl 0x2a7d650 <1.cpp:1:1, col:17> col:13 p 'const char *' cinit\n"
" `-ImplicitCastExpr 0x2a7d708 <col:17> 'const char *' <NullToPointer>\n"
" `-CXXNullPtrLiteralExpr 0x2a7d6f0 <col:17> 'nullptr_t'";
ASSERT_EQUALS("const char * p@1 = nullptr ;", parse(clang));
}
void cxxOperatorCallExpr() {
const char clang[] = "`-FunctionDecl 0x3c099f0 <a.cpp:2:1, col:24> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x3c37308 <col:12, col:24>\n"
" |-DeclStmt 0x3c0a060 <col:14, col:17>\n"
" | `-VarDecl 0x3c09ae0 <col:14, col:16> col:16 used c 'C' callinit\n"
" | `-CXXConstructExpr 0x3c0a030 <col:16> 'C' 'void () noexcept'\n"
" `-CXXOperatorCallExpr 0x3c372c0 <col:19, col:21> 'void'\n"
" |-ImplicitCastExpr 0x3c372a8 <col:20> 'void (*)(int)' <FunctionToPointerDecay>\n"
" | `-DeclRefExpr 0x3c37250 <col:20> 'void (int)' lvalue CXXMethod 0x3c098c0 'operator=' 'void (int)'\n"
" |-DeclRefExpr 0x3c0a078 <col:19> 'C' lvalue Var 0x3c09ae0 'c' 'C'\n"
" `-IntegerLiteral 0x3c0a0a0 <col:21> 'int' 4";
ASSERT_EQUALS("void foo ( ) { C c@1 ( C ( ) ) ; c@1 . operator= ( 4 ) ; }", parse(clang));
}
void cxxRecordDecl1() {
const char* clang = "`-CXXRecordDecl 0x34cc5f8 <1.cpp:2:1, col:7> col:7 class Foo";
ASSERT_EQUALS("class Foo ;", parse(clang));
clang = "`-CXXRecordDecl 0x34cc5f8 <C:\\Foo\\Bar Baz\\1.cpp:2:1, col:7> col:7 class Foo";
ASSERT_EQUALS("class Foo ;", parse(clang));
clang = "`-CXXRecordDecl 0x34cc5f8 <C:/Foo/Bar Baz/1.cpp:2:1, col:7> col:7 class Foo";
ASSERT_EQUALS("class Foo ;", parse(clang));
}
void cxxRecordDecl2() {
const char clang[] = "`-CXXRecordDecl 0x34cc5f8 <1.cpp:2:1, col:7> col:7 struct Foo definition";
ASSERT_EQUALS("struct Foo { } ;", parse(clang));
}
void cxxRecordDeclDerived() {
const char clang[] = "|-CXXRecordDecl 0x19ccd38 <e.cpp:4:1, line:6:1> line:4:8 referenced struct base definition\n"
"| `-VarDecl 0x19ccf00 <line:5:5, col:35> col:27 value 'const bool' static constexpr cinit\n"
"| |-value: Int 0\n"
"| `-CXXBoolLiteralExpr 0x19ccf68 <col:35> 'bool' false\n"
"`-CXXRecordDecl 0x19ccfe8 <line:8:1, col:32> col:8 struct derived definition\n"
" |-public 'base'\n"
" `-CXXRecordDecl 0x19cd150 <col:1, col:8> col:8 implicit struct derived";
ASSERT_EQUALS("struct base { static const bool value@1 = false ; } ; struct derived : public base { } ;", parse(clang));
}
void cxxStaticCastExpr1() {
const char clang[] = "`-VarDecl 0x2e0e650 <a.cpp:2:1, col:27> col:5 a 'int' cinit\n"
" `-CXXStaticCastExpr 0x2e0e728 <col:9, col:27> 'int' static_cast<int> <NoOp>\n"
" `-IntegerLiteral 0x2e0e6f0 <col:26> 'int' 0";
ASSERT_EQUALS("int a@1 = static_cast<int> ( 0 ) ;", parse(clang));
}
void cxxStaticCastExpr2() {
const char clang[] = "`-VarDecl 0x2e0e650 <a.cpp:2:1, col:27> col:5 a 'int' cinit\n"
" `-CXXStaticCastExpr 0x3e453e8 <col:12> 'std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, Library::AllocFunc> >' xvalue static_cast<struct std::_Rb_tree_iterator<struct std::pair<const class std::__cxx11::basic_string<char>, struct Library::AllocFunc> > &&> <NoOp>\n"
" `-DeclRefExpr 0x3e453b0 <col:12> 'std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, Library::AllocFunc> >' lvalue ParmVar 0x3e45250 '' 'std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, Library::AllocFunc> > &&'";
ASSERT_EQUALS("int a@1 = static_cast<structstd::_Rb_tree_iterator<structstd::pair<constclassstd::__cxx11::basic_string<char>,structLibrary::AllocFunc>>&&> ( <NoName> ) ;", parse(clang));
}
void cxxStaticCastExpr3() {
const char clang[] = "`-ClassTemplateSpecializationDecl 0xd842d8 <a.cpp:4:3, line:7:3> line:4:21 struct char_traits definition\n"
" |-TemplateArgument type 'char'\n"
" | `-BuiltinType 0xd444c0 'char'\n"
" |-CXXRecordDecl 0xd84500 <col:14, col:21> col:21 implicit struct char_traits\n"
" |-TypedefDecl 0xd845a0 <line:5:7, col:20> col:20 referenced char_type 'char'\n"
" | `-BuiltinType 0xd444c0 'char'\n"
" `-CXXMethodDecl 0xd847b0 <line:6:7, col:80> col:18 assign 'char_traits<char>::char_type *(char_traits<char>::char_type *)'\n"
" |-ParmVarDecl 0xd84670 <col:25, col:36> col:36 used __s 'char_traits<char>::char_type *'\n"
" `-CompoundStmt 0xd848f8 <col:41, col:80>\n"
" `-ReturnStmt 0xd848e8 <col:43, col:77>\n"
" `-CXXStaticCastExpr 0xd848b8 <col:50, col:77> 'char_traits<char>::char_type *' static_cast<char_traits<char>::char_type *> <NoOp>\n"
" `-ImplicitCastExpr 0xd848a0 <col:74> 'char_traits<char>::char_type *' <LValueToRValue> part_of_explicit_cast\n"
" `-DeclRefExpr 0xd84870 <col:74> 'char_traits<char>::char_type *' lvalue ParmVar 0xd84670 '__s' 'char_traits<char>::char_type *'\n";
ASSERT_EQUALS("struct char_traits<char> { typedef char char_type ; char_traits<char>::char_type * assign ( char_traits<char>::char_type * __s@1 ) { return static_cast<char_traits<char>::char_type*> ( __s@1 ) ; } } ;", parse(clang));
}
void cxxStdInitializerListExpr() {
const char clang[] = "`-VarDecl 0x2f92060 <1.cpp:3:1, col:25> col:18 x 'std::vector<int>':'std::vector<int, std::allocator<int> >' listinit\n"
" `-ExprWithCleanups 0x2fb0b40 <col:18, col:25> 'std::vector<int>':'std::vector<int, std::allocator<int> >'\n"
" `-CXXConstructExpr 0x2fb0b00 <col:18, col:25> 'std::vector<int>':'std::vector<int, std::allocator<int> >' 'void (initializer_list<std::vector<int, std::allocator<int> >::value_type>, const std::vector<int, std::allocator<int> >::allocator_type &)' list std::initializer_list\n"
" |-CXXStdInitializerListExpr 0x2fb0928 <col:19, col:25> 'initializer_list<std::vector<int, std::allocator<int> >::value_type>':'std::initializer_list<int>'\n"
" | `-MaterializeTemporaryExpr 0x2fb0910 <col:19, col:25> 'const int [3]' xvalue\n"
" | `-InitListExpr 0x2fb08b8 <col:19, col:25> 'const int [3]'\n"
" | |-IntegerLiteral 0x2f920c0 <col:20> 'int' 1\n"
" | |-IntegerLiteral 0x2f920e0 <col:22> 'int' 2\n"
" | `-IntegerLiteral 0x2f92100 <col:24> 'int' 3\n"
" `-CXXDefaultArgExpr 0x2fb0ae0 <<invalid sloc>> 'const std::vector<int, std::allocator<int> >::allocator_type':'const std::allocator<int>' lvalue";
ASSERT_EQUALS("std :: vector<int> x@1 { 1 , 2 , 3 } ;", parse(clang));
}
void cxxThrowExpr() {
const char clang[] = "`-FunctionDecl 0x3701690 <1.cpp:2:1, col:23> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x37017b0 <col:12, col:23>\n"
" `-CXXThrowExpr 0x3701790 <col:14, col:20> 'void'\n"
" `-IntegerLiteral 0x3701770 <col:20> 'int' 1";
ASSERT_EQUALS("void foo ( ) { throw 1 ; }", parse(clang));
}
void defaultStmt() {
const char clang[] = "`-FunctionDecl 0x18476b8 <1.c:3:1, line:9:1> line:3:5 foo 'int (int)'\n"
" |-ParmVarDecl 0x18475e0 <col:9, col:13> col:13 used rc 'int'\n"
" `-CompoundStmt 0x1847868 <line:4:1, line:9:1>\n"
" `-SwitchStmt 0x18477e0 <line:5:3, line:8:3>\n"
" |-ImplicitCastExpr 0x18477c8 <line:5:10> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x18477a8 <col:10> 'int' lvalue ParmVar 0x18475e0 'rc' 'int'\n"
" `-CompoundStmt 0x1847850 <col:14, line:8:3>\n"
" `-DefaultStmt 0x1847830 <line:6:3, line:7:12>\n"
" `-ReturnStmt 0x1847820 <col:5, col:12>\n"
" `-IntegerLiteral 0x1847800 <col:12> 'int' 1";
ASSERT_EQUALS("int foo ( int rc@1 ) { switch ( rc@1 ) { default : return 1 ; } }", parse(clang));
}
void doStmt() {
const char clang[] = "`-FunctionDecl 0x27fbbc8 <a.cpp:2:1, col:34> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x27fbd08 <col:12, col:34>\n"
" `-DoStmt 0x27fbce8 <col:14, col:31>\n"
" |-CompoundStmt 0x27fbcb0 <col:17, col:22>\n"
" | `-UnaryOperator 0x27fbc90 <col:18, col:19> 'int' postfix '++'\n"
" | `-DeclRefExpr 0x27fbc68 <col:18> 'int' lvalue Var 0x27fbae0 'x' 'int'\n"
" `-IntegerLiteral 0x27fbcc8 <col:30> 'int' 1";
ASSERT_EQUALS("void foo ( ) { do { ++ x ; } while ( 1 ) ; }", parse(clang));
}
void enumDecl1() {
const char clang[] = "`-EnumDecl 0x2660660 <a.cpp:3:1, col:16> col:6 referenced abc\n"
" |-EnumConstantDecl 0x2660720 <col:11> col:11 referenced a 'abc'\n"
" |-EnumConstantDecl 0x2660768 <col:13> col:13 b 'abc'\n"
" `-EnumConstantDecl 0x26607b0 <col:15> col:15 c 'abc'";
ASSERT_EQUALS("enum abc { a , b , c }", parse(clang));
}
void enumDecl2() {
const char clang[] = "`-EnumDecl 0xb55d50 <2.cpp:4:3, col:44> col:8 syntax_option_type 'unsigned int'";
ASSERT_EQUALS("enum syntax_option_type : unsigned int { }", parse(clang));
}
void enumDecl3() {
const char clang[] = "|-EnumDecl 0x1586e48 <2.cpp:1:3, line:5:3> line:1:8 __syntax_option\n"
"| |-EnumConstantDecl 0x1586f18 <line:3:5> col:5 referenced _S_polynomial '__syntax_option'\n"
"| `-EnumConstantDecl 0x1586f68 <line:4:5> col:5 _S_syntax_last '__syntax_option'";
ASSERT_EQUALS("enum __syntax_option { _S_polynomial , _S_syntax_last }", parse(clang));
}
void enumDecl4() {
const char clang[] = "|-EnumDecl 0xace1f8 <e1.cpp:3:1, col:51> col:1\n"
"| |-EnumConstantDecl 0xace2c8 <col:7> col:7 A '(anonymous enum at e1.cpp:3:1)'\n"
"| |-EnumConstantDecl 0xace318 <col:16> col:16 B '(anonymous enum at e1.cpp:3:1)'\n"
"| `-EnumConstantDecl 0xace3b8 <col:46> col:46 referenced C '(anonymous enum at e1.cpp:3:1)'\n"
"`-VarDecl 0xace470 <col:1, col:66> col:53 x 'enum (anonymous enum at e1.cpp:3:1)':'(anonymous enum at e1.cpp:3:1)' cinit\n"
" `-DeclRefExpr 0xace520 <col:66> '(anonymous enum at e1.cpp:3:1)' EnumConstant 0xace3b8 'C' '(anonymous enum at e1.cpp:3:1)'";
ASSERT_EQUALS("enum { A , B , C } x@1 = C ;", parse(clang));
}
void forStmt() {
const char clang[] = "`-FunctionDecl 0x2f93ae0 <1.c:1:1, col:56> col:5 main 'int ()'\n"
" `-CompoundStmt 0x2f93dc0 <col:12, col:56>\n"
" |-ForStmt 0x2f93d50 <col:14, col:44>\n"
" | |-DeclStmt 0x2f93c58 <col:19, col:28>\n"
" | | `-VarDecl 0x2f93bd8 <col:19, col:27> col:23 used i 'int' cinit\n"
" | | `-IntegerLiteral 0x2f93c38 <col:27> 'int' 0\n"
" | |-<<<NULL>>>\n"
" | |-BinaryOperator 0x2f93cd0 <col:30, col:34> 'int' '<'\n"
" | | |-ImplicitCastExpr 0x2f93cb8 <col:30> 'int' <LValueToRValue>\n"
" | | | `-DeclRefExpr 0x2f93c70 <col:30> 'int' lvalue Var 0x2f93bd8 'i' 'int'\n"
" | | `-IntegerLiteral 0x2f93c98 <col:34> 'int' 10\n"
" | |-UnaryOperator 0x2f93d20 <col:38, col:39> 'int' postfix '++'\n"
" | | `-DeclRefExpr 0x2f93cf8 <col:38> 'int' lvalue Var 0x2f93bd8 'i' 'int'\n"
" | `-CompoundStmt 0x2f93d40 <col:43, col:44>\n"
" `-ReturnStmt 0x2f93da8 <col:46, col:53>\n"
" `-IntegerLiteral 0x2f93d88 <col:53> 'int' 0";
ASSERT_EQUALS("int main ( ) { for ( int i@1 = 0 ; i@1 < 10 ; ++ i@1 ) { } return 0 ; }", parse(clang));
}
void funcdecl1() {
const char clang[] = "`-FunctionDecl 0x3122c30 <1.c:1:1, col:22> col:6 foo 'void (int, int)'\n"
" |-ParmVarDecl 0x3122ae0 <col:10, col:14> col:14 x 'int'\n"
" `-ParmVarDecl 0x3122b58 <col:17, col:21> col:21 y 'int'";
ASSERT_EQUALS("void foo ( int x@1 , int y@2 ) ;", parse(clang));
}
void funcdecl2() {
const char clang[] = "`-FunctionDecl 0x24b2c38 <1.c:1:1, line:4:1> line:1:5 foo 'int (int, int)'\n"
" |-ParmVarDecl 0x24b2ae0 <col:9, col:13> col:13 used x 'int'\n"
" |-ParmVarDecl 0x24b2b58 <col:16, col:20> col:20 used y 'int'\n"
" `-CompoundStmt 0x24b2de8 <line:2:1, line:4:1>\n"
" `-ReturnStmt 0x24b2dd0 <line:3:5, col:16>\n"
" `-BinaryOperator 0x24b2da8 <col:12, col:16> 'int' '/'\n"
" |-ImplicitCastExpr 0x24b2d78 <col:12> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x24b2d28 <col:12> 'int' lvalue ParmVar 0x24b2ae0 'x' 'int'\n"
" `-ImplicitCastExpr 0x24b2d90 <col:16> 'int' <LValueToRValue>\n"
" `-DeclRefExpr 0x24b2d50 <col:16> 'int' lvalue ParmVar 0x24b2b58 'y' 'int'";
ASSERT_EQUALS("int foo ( int x@1 , int y@2 ) { return x@1 / y@2 ; }", parse(clang));
}
void funcdecl3() {
const char clang[] = "|-FunctionDecl 0x27cb6b8 <a.cpp:865:1, col:35> col:12 __overflow 'int (FILE *, int)' extern\n"
"| |-ParmVarDecl 0x27cb528 <col:24, col:29> col:30 'FILE *'\n"
"| `-ParmVarDecl 0x27cb5a0 <col:32> col:35 'int'";
ASSERT_EQUALS("int __overflow ( FILE * , int ) ;", parse(clang));
}
void funcdecl4() {
const char clang[] = "|-FunctionDecl 0x272bb60 <a.cpp:658:15> col:15 implicit fwrite 'unsigned long (const void *, unsigned long, unsigned long, FILE *)' extern\n"
"| |-ParmVarDecl 0x272cc40 <<invalid sloc>> <invalid sloc> 'const void *'\n"
"| |-ParmVarDecl 0x272cca0 <<invalid sloc>> <invalid sloc> 'unsigned long'\n"
"| |-ParmVarDecl 0x272cd00 <<invalid sloc>> <invalid sloc> 'unsigned long'\n"
"| `-ParmVarDecl 0x272cd60 <<invalid sloc>> <invalid sloc> 'FILE *'";
ASSERT_EQUALS("unsigned long fwrite ( const void * , unsigned long , unsigned long , FILE * ) ;", parse(clang));
}
void funcdecl5() {
const char clang[] = "`-FunctionDecl 0x59d670 <1.c:1:1, col:28> col:20 foo 'void (void)' static inline";
ASSERT_EQUALS("static inline void foo ( ) ;", parse(clang));
}
void funcdecl6() {
const char clang[] = "`-FunctionDecl 0x196eea8 <1.cpp:3:5, col:27> col:12 foo 'void **(int)'\n"
" `-ParmVarDecl 0x196eda0 <col:17, col:21> col:21 count 'int'";
ASSERT_EQUALS("void * * foo ( int count@1 ) ;", parse(clang));
}
void functionTemplateDecl1() {
const char clang[] = "`-FunctionTemplateDecl 0x3242860 <a.cpp:1:1, col:46> col:21 foo";
ASSERT_EQUALS("", parse(clang));
}
void functionTemplateDecl2() {
const char clang[] = "|-FunctionTemplateDecl 0x333a860 <a.cpp:1:1, col:46> col:21 foo\n"
"| |-TemplateTypeParmDecl 0x333a5f8 <col:10, col:16> col:16 referenced class depth 0 index 0 T\n"
"| |-FunctionDecl 0x333a7c0 <col:19, col:46> col:21 foo 'T (T)'\n"
"| | |-ParmVarDecl 0x333a6c0 <col:25, col:27> col:27 referenced t 'T'\n"
"| | `-CompoundStmt 0x333a980 <col:30, col:46>\n"
"| | `-ReturnStmt 0x333a968 <col:32, col:43>\n"
"| | `-BinaryOperator 0x333a940 <col:39, col:43> '<dependent type>' '+'\n"
"| | |-DeclRefExpr 0x333a8f8 <col:39> 'T' lvalue ParmVar 0x333a6c0 't' 'T'\n"
"| | `-IntegerLiteral 0x333a920 <col:43> 'int' 1\n"
"| `-FunctionDecl 0x333ae00 <col:19, col:46> col:21 used foo 'int (int)'\n"
"| |-TemplateArgument type 'int'\n"
"| |-ParmVarDecl 0x333ad00 <col:25, col:27> col:27 used t 'int':'int'\n"
"| `-CompoundStmt 0x333b0a8 <col:30, col:46>\n"
"| `-ReturnStmt 0x333b090 <col:32, col:43>\n"
"| `-BinaryOperator 0x333b068 <col:39, col:43> 'int' '+'\n"
"| |-ImplicitCastExpr 0x333b050 <col:39> 'int':'int' <LValueToRValue>\n"
"| | `-DeclRefExpr 0x333b028 <col:39> 'int':'int' lvalue ParmVar 0x333ad00 't' 'int':'int'\n"
"| `-IntegerLiteral 0x333a920 <col:43> 'int' 1\n"
"`-FunctionDecl 0x333a9f8 <line:2:1, col:22> col:1 invalid bar 'int ()'\n"
" `-CompoundStmt 0x333b010 <col:7, col:22>\n"
" `-CallExpr 0x333afe0 <col:9, col:19> 'int':'int'\n"
" |-ImplicitCastExpr 0x333afc8 <col:9, col:16> 'int (*)(int)' <FunctionToPointerDecay>\n"
" | `-DeclRefExpr 0x333af00 <col:9, col:16> 'int (int)' lvalue Function 0x333ae00 'foo' 'int (int)' (FunctionTemplate 0x333a860 'foo')\n"
" `-IntegerLiteral 0x333ab48 <col:18> 'int' 1";
ASSERT_EQUALS("int foo<int> ( int t@1 ) { return t@1 + 1 ; } int bar ( ) { foo ( 1 ) ; }", parse(clang));
}
void ifelse() {
const char clang[] = "`-FunctionDecl 0x2637ba8 <1.c:1:1, line:4:1> line:1:5 foo 'int (int)'\n"
" |-ParmVarDecl 0x2637ae0 <col:9, col:13> col:13 used x 'int'\n"
" `-CompoundStmt 0x2637d70 <col:16, line:4:1>\n"
" `-IfStmt 0x2637d38 <line:2:5, line:3:11>\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" |-BinaryOperator 0x2637cf0 <line:2:9, col:13> 'int' '>'\n"
" | |-ImplicitCastExpr 0x2637cd8 <col:9> 'int' <LValueToRValue>\n"
" | | `-DeclRefExpr 0x2637c90 <col:9> 'int' lvalue ParmVar 0x2637ae0 'x' 'int'\n"
" | `-IntegerLiteral 0x2637cb8 <col:13> 'int' 10\n"
" |-CompoundStmt 0x2637d18 <col:17, col:18>\n"
" `-CompoundStmt 0x2637d28 <line:3:10, col:11>";
ASSERT_EQUALS("int foo ( int x@1 ) { if ( x@1 > 10 ) { } else { } }", parse(clang));
}
void ifStmt() {
// Clang 8 in cygwin
const char clang[] = "`-FunctionDecl 0x41d0690 <2.cpp:1:1, col:24> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x41d07f0 <col:12, col:24>\n"
" `-IfStmt 0x41d07b8 <col:14, col:22>\n"
" |-ImplicitCastExpr 0x41d0790 <col:18> 'bool' <IntegralToBoolean>\n"
" | `-IntegerLiteral 0x41d0770 <col:18> 'int' 1\n"
" |-CompoundStmt 0x41d07a8 <col:21, col:22>\n";
ASSERT_EQUALS("void foo ( ) { if ( 1 ) { } }", parse(clang));
}
void initListExpr() {
const char clang[] = "|-VarDecl 0x397c680 <1.cpp:2:1, col:26> col:11 used ints 'const int [3]' cinit\n"
"| `-InitListExpr 0x397c7d8 <col:20, col:26> 'const int [3]'\n"
"| |-IntegerLiteral 0x397c720 <col:21> 'int' 1\n"
"| |-IntegerLiteral 0x397c740 <col:23> 'int' 2\n"
"| `-IntegerLiteral 0x397c760 <col:25> 'int' 3";
ASSERT_EQUALS("const int [3] ints@1 = { 1 , 2 , 3 } ;", parse(clang));
}
void labelStmt() {
const char clang[] = "`-FunctionDecl 0x2ed1ba0 <1.c:1:1, col:36> col:6 foo 'void (int)'\n"
" `-CompoundStmt 0x2ed1d00 <col:17, col:36>\n"
" `-LabelStmt 0x2ed1ce8 <col:19, col:30> 'loop'\n"
" `-GotoStmt 0x2ed1cd0 <col:25, col:30> 'loop' 0x2ed1c88";
ASSERT_EQUALS("void foo ( ) { loop : goto loop ; }", parse(clang));
}
void memberExpr() {
// C code:
// struct S { int x };
// int foo(struct S s) { return s.x; }
const char clang[] = "|-RecordDecl 0x2441a88 <1.c:1:1, col:18> col:8 struct S definition\n"
"| `-FieldDecl 0x2441b48 <col:12, col:16> col:16 referenced x 'int'\n"
"`-FunctionDecl 0x2441cf8 <line:2:1, col:35> col:5 foo 'int (struct S)'\n"
" |-ParmVarDecl 0x2441be8 <col:9, col:18> col:18 used s 'struct S':'struct S'\n"
" `-CompoundStmt 0x2441e70 <col:21, col:35>\n"
" `-ReturnStmt 0x2441e58 <col:23, col:32>\n"
" `-ImplicitCastExpr 0x2441e40 <col:30, col:32> 'int' <LValueToRValue>\n"
" `-MemberExpr 0x2441e08 <col:30, col:32> 'int' lvalue .x 0x2441b48\n"
" `-DeclRefExpr 0x2441de0 <col:30> 'struct S':'struct S' lvalue ParmVar 0x2441be8 's' 'struct S':'struct S'";
ASSERT_EQUALS("struct S { int x@1 ; } ; int foo ( struct S s@2 ) { return s@2 . x@1 ; }",
parse(clang));
}
void namespaceDecl1() {
const char clang[] = "`-NamespaceDecl 0x2e5f658 <hello.cpp:1:1, col:24> col:11 x\n"
" `-VarDecl 0x2e5f6d8 <col:15, col:19> col:19 var 'int'";
ASSERT_EQUALS("namespace x { int var@1 ; }",
parse(clang));
}
void namespaceDecl2() {
const char clang[] = "`-NamespaceDecl 0x1753e60 <1.cpp:1:1, line:4:1> line:1:11 std\n"
" |-VisibilityAttr 0x1753ed0 <col:31, col:56> Default\n"
" `-VarDecl 0x1753f40 <line:3:5, col:9> col:9 x 'int'";
ASSERT_EQUALS("namespace std { int x@1 ; }",
parse(clang));
}
void recordDecl1() {
const char clang[] = "`-RecordDecl 0x354eac8 <1.c:1:1, line:4:1> line:1:8 struct S definition\n"
" |-FieldDecl 0x354eb88 <line:2:3, col:7> col:7 x 'int'\n"
" `-FieldDecl 0x354ebe8 <line:3:3, col:7> col:7 y 'int'";
ASSERT_EQUALS("struct S { int x@1 ; int y@2 ; } ;",
parse(clang));
}
void recordDecl2() {
const char clang[] = "`-RecordDecl 0x3befac8 <2.c:2:1, col:22> col:1 struct definition\n"
" `-FieldDecl 0x3befbf0 <col:10, col:19> col:14 val 'int'";
ASSERT_EQUALS("struct { int val@1 ; } ;",
parse(clang));
}
void switchStmt() {
const char clang[] = "`-FunctionDecl 0x2796ba0 <1.c:1:1, col:35> col:6 foo 'void (int)'\n"
" |-ParmVarDecl 0x2796ae0 <col:10, col:14> col:14 used x 'int'\n"
" `-CompoundStmt 0x2796d18 <col:17, col:35>\n"
" |-SwitchStmt 0x2796cc8 <col:19, col:32>\n"
" | |-<<<NULL>>>\n"
" | |-<<<NULL>>>\n"
" | |-ImplicitCastExpr 0x2796cb0 <col:27> 'int' <LValueToRValue>\n"
" | | `-DeclRefExpr 0x2796c88 <col:27> 'int' lvalue ParmVar 0x2796ae0 'x' 'int'\n"
" | `-CompoundStmt 0x2796cf8 <col:30, col:32>\n"
" `-NullStmt 0x2796d08 <col:33>";
ASSERT_EQUALS("void foo ( int x@1 ) { switch ( x@1 ) { } ; }",
parse(clang));
}
void typedefDeclPrologue()
{
// these TypedefDecl are included in *any* AST dump and we should ignore them as they should not be of interest to us
// see https://github.com/llvm/llvm-project/issues/120228#issuecomment-2549212109 for an explanation
const char clang[] =
"TranslationUnitDecl 0x60efd80ef9f8 <<invalid sloc>> <invalid sloc>\n"
"|-TypedefDecl 0x60efd80f0228 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'\n"
"| `-BuiltinType 0x60efd80effc0 '__int128'\n"
"|-TypedefDecl 0x60efd80f0298 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'\n"
"| `-BuiltinType 0x60efd80effe0 'unsigned __int128'\n"
"|-TypedefDecl 0x60efd80f05a0 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'\n"
"| `-RecordType 0x60efd80f0370 'struct __NSConstantString_tag'\n"
"| `-Record 0x60efd80f02f0 '__NSConstantString_tag'\n"
"|-TypedefDecl 0x60efd80f0648 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'\n"
"| `-PointerType 0x60efd80f0600 'char *'\n"
"| `-BuiltinType 0x60efd80efaa0 'char'\n"
"|-TypedefDecl 0x60efd80f0940 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag[1]'\n"
"| `-ConstantArrayType 0x60efd80f08e0 'struct __va_list_tag[1]' 1\n"
"| `-RecordType 0x60efd80f0720 'struct __va_list_tag'\n"
"| `-Record 0x60efd80f06a0 '__va_list_tag'\n"
"`-FunctionDecl 0x60efd8151470 <a.cpp:1:1, line:3:1> line:1:6 f 'void ()'\n"
"`-CompoundStmt 0x60efd8151560 <line:2:1, line:3:1>\n";
ASSERT_EQUALS("void f ( ) ;", parse(clang));
}
void unaryExprOrTypeTraitExpr1() {
const char clang[] = "`-VarDecl 0x24cc610 <a.cpp:1:1, col:19> col:5 x 'int' cinit\n"
" `-ImplicitCastExpr 0x24cc6e8 <col:9, col:19> 'int' <IntegralCast>\n"
" `-UnaryExprOrTypeTraitExpr 0x24cc6c8 <col:9, col:19> 'unsigned long' sizeof 'int'\n";
ASSERT_EQUALS("int x@1 = sizeof ( int ) ;", parse(clang));
}
void unaryExprOrTypeTraitExpr2() {
const char clang[] = "`-VarDecl 0x27c6c00 <a.cpp:3:5, col:23> col:9 x 'int' cinit\n"
" `-ImplicitCastExpr 0x27c6cc8 <col:13, col:23> 'int' <IntegralCast>\n"
" `-UnaryExprOrTypeTraitExpr 0x27c6ca8 <col:13, col:23> 'unsigned long' sizeof\n"
" `-ParenExpr 0x27c6c88 <col:19, col:23> 'char [10]' lvalue\n"
" `-DeclRefExpr 0x27c6c60 <col:20> 'char [10]' lvalue Var 0x27c6b48 'buf' 'char [10]'";
ASSERT_EQUALS("int x@1 = sizeof ( buf ) ;", parse(clang));
}
void unaryOperator() {
const char clang[] = "`-FunctionDecl 0x2dd9748 <1.cpp:2:1, col:44> col:5 foo 'int (int *)'\n"
" |-ParmVarDecl 0x2dd9680 <col:14, col:19> col:19 used p 'int *'\n"
" `-CompoundStmt 0x2dd9908 <col:22, col:44>\n"
" `-ReturnStmt 0x2dd98f0 <col:24, col:41>\n"
" `-BinaryOperator 0x2dd98c8 <col:31, col:41> 'int' '/'\n"
" |-IntegerLiteral 0x2dd9830 <col:31> 'int' 100000\n"
" `-ImplicitCastExpr 0x2dd98b0 <col:40, col:41> 'int' <LValueToRValue>\n"
" `-UnaryOperator 0x2dd9890 <col:40, col:41> 'int' lvalue prefix '*' cannot overflow\n"
" `-ImplicitCastExpr 0x2dd9878 <col:41> 'int *' <LValueToRValue>\n"
" `-DeclRefExpr 0x2dd9850 <col:41> 'int *' lvalue ParmVar 0x2dd9680 'p' 'int *'";
ASSERT_EQUALS("int foo ( int * p@1 ) { return 100000 / * p@1 ; }", parse(clang));
}
void vardecl1() {
const char clang[] = "|-VarDecl 0x32b8aa0 <1.c:1:1, col:9> col:5 used a 'int' cinit\n"
"| `-IntegerLiteral 0x32b8b40 <col:9> 'int' 1\n"
"`-VarDecl 0x32b8b78 <line:2:1, col:9> col:5 b 'int' cinit\n"
" `-ImplicitCastExpr 0x32b8c00 <col:9> 'int' <LValueToRValue>\n"
" `-DeclRefExpr 0x32b8bd8 <col:9> 'int' lvalue Var 0x32b8aa0 'a' 'int'";
ASSERT_EQUALS("int a@1 = 1 ; int b@2 = a@1 ;",
parse(clang));
}
void vardecl2() {
const char clang[] = "|-VarDecl 0x3873b50 <1.c:1:1, col:9> col:5 used a 'int [10]'\n"
"`-FunctionDecl 0x3873c38 <line:3:1, line:6:1> line:3:6 foo 'void ()'\n"
" `-CompoundStmt 0x3873dd0 <line:4:1, line:6:1>\n"
" `-BinaryOperator 0x3873da8 <line:5:3, col:10> 'int' '='\n"
" |-ArraySubscriptExpr 0x3873d60 <col:3, col:6> 'int' lvalue\n"
" | |-ImplicitCastExpr 0x3873d48 <col:3> 'int *' <ArrayToPointerDecay>\n"
" | | `-DeclRefExpr 0x3873cd8 <col:3> 'int [10]' lvalue Var 0x3873b50 'a' 'int [10]'\n"
" | `-IntegerLiteral 0x3873d00 <col:5> 'int' 0\n"
" `-IntegerLiteral 0x3873d88 <col:10> 'int' 0\n";
ASSERT_EQUALS("int [10] a@1 ; void foo ( ) { a@1 [ 0 ] = 0 ; }",
parse(clang));
}
void vardecl3() {
const char clang[] = "`-VarDecl 0x25a8aa0 <1.c:1:1, col:12> col:12 p 'const int *'";
ASSERT_EQUALS("const int * p@1 ;", parse(clang));
}
void vardecl4() {
const char clang[] = "|-VarDecl 0x23d6c78 <a.cpp:137:1, col:14> col:14 stdin 'FILE *' extern";
ASSERT_EQUALS("FILE * stdin@1 ;", parse(clang));
}
void vardecl5() {
const char clang[] = "|-VarDecl 0x2e31fc0 <a.cpp:27:1, col:38> col:26 sys_errlist 'const char *const []' extern";
ASSERT_EQUALS("const char * const [] sys_errlist@1 ;", parse(clang));
}
void vardecl6() {
const char clang[] = "`-VarDecl 0x278e170 <1.c:1:1, col:16> col:12 x 'int' static cinit\n"
" `-IntegerLiteral 0x278e220 <col:16> 'int' 3";
ASSERT_EQUALS("static int x@1 = 3 ;", parse(clang));
}
void vardecl7() {
const char clang[] = "`-VarDecl 0x2071f20 <1.cpp:2:1, col:23> col:9 start 'void *(*)(void *)'";
ASSERT_EQUALS("void * * start@1 ;", parse(clang));
}
void whileStmt1() {
const char clang[] = "`-FunctionDecl 0x3d45b18 <1.c:1:1, line:3:1> line:1:6 foo 'void ()'\n"
" `-CompoundStmt 0x3d45c48 <col:12, line:3:1>\n"
" `-WhileStmt 0x3d45c28 <line:2:5, col:14>\n"
" |-<<<NULL>>>\n"
" |-IntegerLiteral 0x3d45bf8 <col:12> 'int' 0\n"
" `-NullStmt 0x3d45c18 <col:14>";
ASSERT_EQUALS("void foo ( ) { while ( 0 ) { ; } }",
parse(clang));
}
void whileStmt2() {
// clang 9
const char clang[] = "`-FunctionDecl 0x1c99ac8 <1.cpp:1:1, col:27> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x1c99c10 <col:12, col:27>\n"
" `-WhileStmt 0x1c99bf8 <col:14, col:25>\n"
" |-ImplicitCastExpr 0x1c99bd0 <col:21> 'bool' <IntegralToBoolean>\n"
" | `-IntegerLiteral 0x1c99bb0 <col:21> 'int' 1\n"
" `-CompoundStmt 0x1c99be8 <col:24, col:25>";
ASSERT_EQUALS("void foo ( ) { while ( 1 ) { } }", parse(clang));
}
#define GET_SYMBOL_DB(AST) \
const Settings settings = settingsBuilder().clang().platform(Platform::Type::Unix64).build(); \
Tokenizer tokenizer(settings, *this); \
{ \
std::istringstream istr(AST); \
clangimport::parseClangAstDump(tokenizer, istr); \
} \
const SymbolDatabase *db = tokenizer.getSymbolDatabase(); \
ASSERT(db)
void tokenIndex() {
const char clang[] = "`-FunctionDecl 0x1e07dd0 <67.cpp:1:1, col:13> col:6 foo 'void ()'\n"
" `-CompoundStmt 0x1e07eb8 <col:12, col:13>";
ASSERT_EQUALS("void foo ( ) { }", parse(clang));
GET_SYMBOL_DB(clang);
const Token *tok = tokenizer.tokens();
ASSERT_EQUALS(tok->index() + 1, tok->next()->index());
}
void symbolDatabaseEnum1() {
const char clang[] = "|-NamespaceDecl 0x29ad5f8 <1.cpp:1:1, line:3:1> line:1:11 ns\n"
"| `-EnumDecl 0x29ad660 <line:2:1, col:16> col:6 referenced abc\n"
"| |-EnumConstantDecl 0x29ad720 <col:11> col:11 a 'ns::abc'\n"
"| |-EnumConstantDecl 0x29ad768 <col:13> col:13 b 'ns::abc'\n"
"| `-EnumConstantDecl 0x29ad7b0 <col:15> col:15 referenced c 'ns::abc'\n"
"`-VarDecl 0x29ad898 <line:5:1, col:22> col:9 x 'ns::abc':'ns::abc' cinit\n"
" `-DeclRefExpr 0x29ad998 <col:13, col:22> 'ns::abc' EnumConstant 0x29ad7b0 'c' 'ns::abc'\n";
ASSERT_EQUALS("namespace ns { enum abc { a , b , c } } ns :: abc x@1 = c ;", parse(clang));
GET_SYMBOL_DB(clang);
// Enum scope and type
ASSERT_EQUALS(3, db->scopeList.size());
const Scope &enumScope = db->scopeList.back();
ASSERT_EQUALS(Scope::ScopeType::eEnum, enumScope.type);
ASSERT_EQUALS("abc", enumScope.className);
const Type *enumType = enumScope.definedType;
ASSERT_EQUALS("abc", enumType->name());
// Variable
const Token *vartok = Token::findsimplematch(tokenizer.tokens(), "x");
ASSERT(vartok);
ASSERT(vartok->variable());
ASSERT(vartok->variable()->valueType());
ASSERT_EQUALS(uintptr_t(&enumScope), uintptr_t(vartok->variable()->valueType()->typeScope));
}
void symbolDatabaseFunction1() {
const char clang[] = "|-FunctionDecl 0x3aea7a0 <1.cpp:2:1, col:22> col:6 used foo 'void (int, int)'\n"
" |-ParmVarDecl 0x3aea650 <col:10, col:14> col:14 x 'int'\n"
" |-ParmVarDecl 0x3aea6c8 <col:17, col:21> col:21 y 'int'\n"
" `-CompoundStmt 0x3d45c48 <col:12>\n";
GET_SYMBOL_DB(clang);
// There is a function foo that has 2 arguments
ASSERT_EQUALS(1, db->functionScopes.size());
const Scope *scope = db->functionScopes[0];
const Function *func = scope->function;
ASSERT_EQUALS(2, func->argCount());
ASSERT_EQUALS("x", func->getArgumentVar(0)->name());
ASSERT_EQUALS("y", func->getArgumentVar(1)->name());
ASSERT_EQUALS(ValueType::Type::INT, func->getArgumentVar(0)->valueType()->type);
ASSERT_EQUALS(ValueType::Type::INT, func->getArgumentVar(1)->valueType()->type);
}
void symbolDatabaseFunction2() {
const char clang[] = "|-FunctionDecl 0x3aea7a0 <1.cpp:2:1, col:22> col:6 used foo 'void (int, int)'\n"
"| |-ParmVarDecl 0x3aea650 <col:10, col:14> col:14 'int'\n"
"| |-ParmVarDecl 0x3aea6c8 <col:17, col:21> col:21 'int'\n"
" `-CompoundStmt 0x3d45c48 <col:12>\n";
GET_SYMBOL_DB(clang);
// There is a function foo that has 2 arguments
ASSERT_EQUALS(1, db->functionScopes.size());
const Scope *scope = db->functionScopes[0];
const Function *func = scope->function;
ASSERT_EQUALS(2, func->argCount());
ASSERT_EQUALS(0, (long long)func->getArgumentVar(0)->nameToken());
ASSERT_EQUALS(0, (long long)func->getArgumentVar(1)->nameToken());
}
void symbolDatabaseFunction3() { // #9640
const char clang[] = "`-FunctionDecl 0x238fcd8 <9640.cpp:1:1, col:26> col:6 used bar 'bool (const char, int &)'\n"
" |-ParmVarDecl 0x238fb10 <col:10, col:16> col:20 'const char'\n"
" |-ParmVarDecl 0x238fbc0 <col:22, col:25> col:26 'int &'\n"
" `-CompoundStmt 0x3d45c48 <col:12>\n";
GET_SYMBOL_DB(clang);
// There is a function foo that has 2 arguments
ASSERT_EQUALS(1, db->functionScopes.size());
const Scope *scope = db->functionScopes[0];
const Function *func = scope->function;
ASSERT_EQUALS(2, func->argCount());
ASSERT_EQUALS(false, func->getArgumentVar(0)->isReference());
ASSERT_EQUALS(true, func->getArgumentVar(1)->isReference());
}
void symbolDatabaseFunctionConst() {
const char clang[] = "`-CXXRecordDecl 0x7e2d98 <1.cpp:2:1, line:5:1> line:2:7 class foo definition\n"
" `-CXXMethodDecl 0x7e3000 <line:4:3, col:12> col:8 f 'void () const'";
GET_SYMBOL_DB(clang);
// There is a function f that is const
ASSERT_EQUALS(2, db->scopeList.size());
ASSERT_EQUALS(1, db->scopeList.back().functionList.size());
const Function &func = db->scopeList.back().functionList.back();
ASSERT(func.isConst());
}
void symbolDatabaseVariableRef() {
const char clang[] = "`-FunctionDecl 0x1593df0 <3.cpp:1:1, line:4:1> line:1:6 foo 'void ()'\n"
" `-CompoundStmt 0x15940b0 <col:12, line:4:1>\n"
" |-DeclStmt 0x1593f58 <line:2:3, col:8>\n"
" | `-VarDecl 0x1593ef0 <col:3, col:7> col:7 used x 'int'\n"
" `-DeclStmt 0x1594098 <line:3:3, col:15>\n"
" `-VarDecl 0x1593fb8 <col:3, col:14> col:8 ref 'int &' cinit\n"
" `-DeclRefExpr 0x1594020 <col:14> 'int' lvalue Var 0x1593ef0 'x' 'int'";
GET_SYMBOL_DB(clang);
const Variable *refVar = db->variableList().back();
ASSERT(refVar->isReference());
}
void symbolDatabaseVariableRRef() {
const char clang[] = "`-FunctionDecl 0x1a40df0 <3.cpp:1:1, line:4:1> line:1:6 foo 'void ()'\n"
" `-CompoundStmt 0x1a41180 <col:12, line:4:1>\n"
" |-DeclStmt 0x1a40f58 <line:2:3, col:8>\n"
" | `-VarDecl 0x1a40ef0 <col:3, col:7> col:7 used x 'int'\n"
" `-DeclStmt 0x1a41168 <line:3:3, col:18>\n"
" `-VarDecl 0x1a40fb8 <col:3, col:17> col:9 ref 'int &&' cinit\n"
" `-ExprWithCleanups 0x1a410f8 <col:15, col:17> 'int' xvalue\n"
" `-MaterializeTemporaryExpr 0x1a41098 <col:15, col:17> 'int' xvalue extended by Var 0x1a40fb8 'ref' 'int &&'\n"
" `-BinaryOperator 0x1a41078 <col:15, col:17> 'int' '+'\n"
" |-ImplicitCastExpr 0x1a41060 <col:15> 'int' <LValueToRValue>\n"
" | `-DeclRefExpr 0x1a41020 <col:15> 'int' lvalue Var 0x1a40ef0 'x' 'int'\n"
" `-IntegerLiteral 0x1a41040 <col:17> 'int' 1\n";
ASSERT_EQUALS("void foo ( ) { int x@1 ; int && ref@2 = x@1 + 1 ; }", parse(clang));
GET_SYMBOL_DB(clang);
const Variable *refVar = db->variableList().back();
ASSERT(refVar->isReference());
ASSERT(refVar->isRValueReference());
}
void symbolDatabaseVariablePointerRef() {
const char clang[] = "`-FunctionDecl 0x9b4f10 <3.cpp:1:1, col:17> col:6 used foo 'void (int *&)'\n"
" `-ParmVarDecl 0x9b4e40 <col:10, col:16> col:16 p 'int *&'\n";
ASSERT_EQUALS("void foo ( int * & p@1 ) ;", parse(clang));
GET_SYMBOL_DB(clang);
const Variable *p = db->variableList().back();
ASSERT(p->isPointer());
ASSERT(p->isReference());
}
void symbolDatabaseNodeType1() {
const char clang[] = "`-FunctionDecl 0x32438c0 <a.cpp:5:1, line:7:1> line:5:6 foo 'a::b (a::b)'\n"
" |-ParmVarDecl 0x32437b0 <col:10, col:15> col:15 used i 'a::b':'long'\n"
" `-CompoundStmt 0x3243a60 <col:18, line:7:1>\n"
" `-ReturnStmt 0x3243a48 <line:6:3, col:12>\n"
" `-BinaryOperator 0x3243a20 <col:10, col:12> 'long' '+'\n"
" |-ImplicitCastExpr 0x32439f0 <col:10> 'a::b':'long' <LValueToRValue>\n"
" | `-DeclRefExpr 0x32439a8 <col:10> 'a::b':'long' lvalue ParmVar 0x32437b0 'i' 'a::b':'long'\n"
" `-ImplicitCastExpr 0x3243a08 <col:12> 'long' <IntegralCast>\n"
" `-IntegerLiteral 0x32439d0 <col:12> 'int' 1\n";
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "i + 1");
ASSERT(!!tok);
ASSERT(!!tok->valueType());
ASSERT_EQUALS("signed long", tok->valueType()->str());
}
void symbolDatabaseForVariable() {
const char clang[] = "`-FunctionDecl 0x38f8bb0 <10100.c:2:1, line:4:1> line:2:6 f 'void (void)'\n"
" `-CompoundStmt 0x38f8d88 <col:14, line:4:1>\n"
" `-ForStmt 0x38f8d50 <line:3:5, col:26>\n"
" |-DeclStmt 0x38f8d28 <col:10, col:19>\n"
" | `-VarDecl 0x38f8ca8 <col:10, col:18> col:14 i 'int' cinit\n"
" | `-IntegerLiteral 0x38f8d08 <col:18> 'int' 0\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" `-CompoundStmt 0x38f8d40 <col:25, col:26>";
ASSERT_EQUALS("void f ( ) { for ( int i@1 = 0 ; ; ) { } }", parse(clang));
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "i");
ASSERT(!!tok);
ASSERT(!!tok->variable());
ASSERT_EQUALS(Scope::ScopeType::eFor, tok->variable()->scope()->type);
}
void valueFlow1() {
// struct S { int x; int buf[10]; } ; int sz = sizeof(struct S);
const char clang[] = "|-RecordDecl 0x2fc5a88 <1.c:1:1, line:4:1> line:1:8 struct S definition\n"
"| |-FieldDecl 0x2fc5b48 <line:2:3, col:7> col:7 x 'int'\n"
"| `-FieldDecl 0x2fc5c10 <line:3:3, col:13> col:7 buf 'int [10]'\n"
"`-VarDecl 0x2fc5c70 <line:6:1, col:25> col:5 sz 'int' cinit\n"
" `-ImplicitCastExpr 0x2fc5d88 <col:10, col:25> 'int' <IntegralCast>\n"
" `-UnaryExprOrTypeTraitExpr 0x2fc5d68 <col:10, col:25> 'unsigned long' sizeof 'struct S':'struct S'";
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof (");
ASSERT(!!tok);
tok = tok->next();
ASSERT(tok->hasKnownIntValue());
ASSERT_EQUALS(44, tok->getKnownIntValue());
}
void valueFlow2() {
// int buf[42];
// int x = sizeof(buf);
const char clang[] = "|-VarDecl 0x10f6de8 <66.cpp:3:1, col:11> col:5 referenced buf 'int [42]'\n"
"`-VarDecl 0x10f6eb0 <line:4:1, col:19> col:5 x 'int' cinit\n"
" `-ImplicitCastExpr 0x10f6f78 <col:9, col:19> 'int' <IntegralCast>\n"
" `-UnaryExprOrTypeTraitExpr 0x10f6f58 <col:9, col:19> 'unsigned long' sizeof\n"
" `-ParenExpr 0x10f6f38 <col:15, col:19> 'int [42]' lvalue\n"
" `-DeclRefExpr 0x10f6f18 <col:16> 'int [42]' lvalue Var 0x10f6de8 'buf' 'int [42]' non_odr_use_unevaluated";
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof (");
ASSERT(!!tok);
tok = tok->next();
TODO_ASSERT_EQUALS(true, false, tok->hasKnownIntValue() && tok->getKnownIntValue() == 10);
}
void valueType1() {
const char clang[] = "`-FunctionDecl 0x32438c0 <a.cpp:5:1, line:7:1> line:5:6 foo 'a::b (a::b)'\n"
" |-ParmVarDecl 0x32437b0 <col:10, col:15> col:15 used i 'a::b':'long'\n"
" `-CompoundStmt 0x3243a60 <col:18, line:7:1>\n"
" `-ReturnStmt 0x3243a48 <line:6:3, col:12>\n"
" `-ImplicitCastExpr 0x2176ca8 <col:9> 'int' <IntegralCast>\n"
" `-ImplicitCastExpr 0x2176c90 <col:9> 'bool' <LValueToRValue>\n"
" `-DeclRefExpr 0x2176c60 <col:9> 'bool' lvalue Var 0x2176bd0 'e' 'bool'\n";
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "e");
ASSERT(!!tok);
ASSERT(!!tok->valueType());
ASSERT_EQUALS("bool", tok->valueType()->str());
}
void valueType2() {
const char clang[] = "`-VarDecl 0xc9eda0 <1.cpp:2:1, col:17> col:13 s 'const char *' cinit\n"
" `-ImplicitCastExpr 0xc9eef0 <col:17> 'const char *' <ArrayToPointerDecay>\n"
" `-StringLiteral 0xc9eed0 <col:17> 'const char [6]' lvalue \"hello\"\n";
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "\"hello\"");
ASSERT(!!tok);
ASSERT(!!tok->valueType());
ASSERT_EQUALS("const signed char *", tok->valueType()->str());
}
void stdinLoc() {
// we should never encounter this
/*
int i;
*/
const char clang[] = "`-VarDecl 0x5776bb240470 <<stdin>:1:1, col:5> col:5 i 'int'\n";
ASSERT_THROW_INTERNAL_EQUALS(parse(clang), AST, "invalid AST location: <<stdin>");
}
void crash() {
const char* clang = "TranslationUnitDecl 0x56037914f998 <<invalid sloc>> <invalid sloc>\n"
"|-ClassTemplateDecl 0x560379196b58 <test1.cpp:1:1, col:50> col:37 A\n"
"| |-TemplateTypeParmDecl 0x560379196950 <col:11> col:19 typename depth 0 index 0\n"
"| |-TemplateTypeParmDecl 0x5603791969f8 <col:21> col:29 typename depth 0 index 1\n"
"| `-CXXRecordDecl 0x560379196ac8 <col:31, col:50> col:37 class A definition\n"
"| |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n"
"| | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n"
"| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveConstructor exists simple trivial needs_implicit\n"
"| | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveAssignment exists simple trivial needs_implicit\n"
"| | `-Destructor simple irrelevant trivial needs_implicit\n"
"| |-CXXRecordDecl 0x560379196de0 <col:31, col:37> col:37 implicit referenced class A\n"
"| `-CXXRecordDecl 0x560379196e70 <col:41, col:47> col:47 class b\n"
"|-CXXRecordDecl 0x560379197110 parent 0x560379196ac8 prev 0x560379196e70 <line:2:1, col:63> col:50 class b definition\n"
"| |-DefinitionData empty standard_layout trivially_copyable has_user_declared_ctor can_const_default_init\n"
"| | |-DefaultConstructor defaulted_is_constexpr\n"
"| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveConstructor exists simple trivial needs_implicit\n"
"| | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param\n"
"| | |-MoveAssignment exists simple trivial needs_implicit\n"
"| | `-Destructor simple irrelevant trivial needs_implicit\n"
"| |-CXXRecordDecl 0x560379197250 <col:35, col:50> col:50 implicit referenced class b\n"
"| `-CXXConstructorDecl 0x5603791974b8 <col:54, col:60> col:54 b 'void (A<type-parameter-0-0, type-parameter-0-1> &)'\n"
"| `-ParmVarDecl 0x560379197380 <col:56, col:59> col:59 a 'A<type-parameter-0-0, type-parameter-0-1> &'\n"
"`-CXXConstructorDecl 0x5603791b5600 parent 0x560379197110 prev 0x5603791974b8 <line:3:1, col:55> col:47 b 'void (A<type-parameter-0-0, type-parameter-0-1> &)'\n"
" |-ParmVarDecl 0x5603791b5570 <col:49, col:51> col:52 'A<type-parameter-0-0, type-parameter-0-1> &'\n"
" `-CompoundStmt 0x5603791b5700 <col:54, col:55>\n";
(void)parse(clang); // don't crash
}
};
REGISTER_TEST(TestClangImport)
|