// Cppcheck - A tool for static C/C++ code analysis // Copyright (C) 2007-2019 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 . #include "clangimport.h" #include "settings.h" #include "symboldatabase.h" #include "tokenize.h" #include "testsuite.h" class TestClangImport: public TestFixture { public: TestClangImport() :TestFixture("TestClangImport") { } private: void run() OVERRIDE { TEST_CASE(breakStmt); 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(cxxConstructorDecl); TEST_CASE(cxxConstructExpr1); TEST_CASE(cxxConstructExpr2); TEST_CASE(cxxConstructExpr3); TEST_CASE(cxxForRangeStmt); TEST_CASE(cxxMemberCall); TEST_CASE(cxxMethodDecl); TEST_CASE(cxxNullPtrLiteralExpr); TEST_CASE(cxxOperatorCallExpr); TEST_CASE(cxxRecordDecl1); TEST_CASE(cxxStaticCastExpr1); TEST_CASE(cxxStaticCastExpr2); TEST_CASE(doStmt); TEST_CASE(forStmt); TEST_CASE(funcdecl1); TEST_CASE(funcdecl2); TEST_CASE(funcdecl3); TEST_CASE(funcdecl4); TEST_CASE(functionTemplateDecl1); TEST_CASE(functionTemplateDecl2); TEST_CASE(initListExpr); TEST_CASE(ifelse); TEST_CASE(labelStmt); TEST_CASE(memberExpr); TEST_CASE(namespaceDecl); TEST_CASE(recordDecl); TEST_CASE(switchStmt); TEST_CASE(typedefDecl1); TEST_CASE(typedefDecl2); TEST_CASE(typedefDecl3); 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(whileStmt); TEST_CASE(symbolDatabaseFunction1); TEST_CASE(symbolDatabaseFunction2); TEST_CASE(symbolDatabaseNodeType1); TEST_CASE(valueFlow1); TEST_CASE(valueFlow2); } std::string parse(const char clang[]) { Settings settings; Tokenizer tokenizer(&settings, this); std::istringstream istr(clang); clangimport::parseClangAstDump(&tokenizer, istr); return tokenizer.tokens()->stringifyList(true, false, false, true, false); } void breakStmt() { const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n" " `-CompoundStmt 0x2c31c40 \n" " `-WhileStmt 0x2c31c20 \n" " |-<<>>\n" " |-IntegerLiteral 0x2c31bf8 'int' 0\n" " `-BreakStmt 0x3687c18 "; ASSERT_EQUALS("void foo ( ) { while ( 0 ) { break ; } }", 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:14 used x 'int'\n" " `-CompoundStmt 0x2444e00 \n" " `-SwitchStmt 0x2444c88 \n" " |-<<>>\n" " |-<<>>\n" " |-ImplicitCastExpr 0x2444c70 'int' \n" " | `-DeclRefExpr 0x2444c48 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n" " `-CompoundStmt 0x2444de0 \n" " |-CaseStmt 0x2444cd8 \n" " | |-IntegerLiteral 0x2444cb8 'int' 16\n" " | |-<<>>\n" " | `-CaseStmt 0x2444d30 \n" " | |-IntegerLiteral 0x2444d10 'int' 32\n" " | |-<<>>\n" " | `-BinaryOperator 0x2444db0 'int' '='\n" " | |-DeclRefExpr 0x2444d68 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n" " | `-IntegerLiteral 0x2444d90 'int' 123\n" " `-BreakStmt 0x2444dd8 "; ASSERT_EQUALS("void foo ( int x@1 ) {\n" "switch ( x@1 ) {\n" "case 16 :\n" "case 32 :\n" "x@1 = 123 ;\n" "\n" "\n" "break ; } }", parse(clang)); } void characterLiteral() { const char clang[] = "`-VarDecl 0x3df8608 col:6 c 'char' cinit\n" " `-CharacterLiteral 0x3df86a8 'char' 120"; ASSERT_EQUALS("char c@1 = 'x' ;", parse(clang)); } void class1() { const char clang[] = "`-CXXRecordDecl 0x274c638 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:7 implicit class C\n" " `-CXXMethodDecl 0x274c870 col:16 foo 'void ()'\n" " `-CompoundStmt 0x274c930 "; ASSERT_EQUALS("class C { void foo ( ) { } }", parse(clang)); } void classTemplateDecl1() { const char clang[] = "`-ClassTemplateDecl 0x29d1748 col:25 C\n" " |-TemplateTypeParmDecl 0x29d15f8 col:16 referenced class depth 0 index 0 T\n" " `-CXXRecordDecl 0x29d16b0 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:25 implicit class C\n" " |-AccessSpecDecl 0x29d1a48 col:29 public\n" " `-CXXMethodDecl 0x29d1b20 col:39 foo 'T ()'\n" " `-CompoundStmt 0x29d1c18 \n" " `-ReturnStmt 0x29d1c00 \n" " `-IntegerLiteral 0x29d1be0 'int' 0"; ASSERT_EQUALS("", parse(clang)); } void classTemplateDecl2() { const char clang[] = "|-ClassTemplateDecl 0x244e748 col:25 C\n" "| |-TemplateTypeParmDecl 0x244e5f8 col:16 referenced class depth 0 index 0 T\n" "| |-CXXRecordDecl 0x244e6b0 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:25 implicit class C\n" "| | |-AccessSpecDecl 0x244ea48 col:29 public\n" "| | `-CXXMethodDecl 0x244eb20 col:39 foo 'T ()'\n" "| | `-CompoundStmt 0x244ec18 \n" "| | `-ReturnStmt 0x244ec00 \n" "| | `-IntegerLiteral 0x244ebe0 'int' 0\n" "| `-ClassTemplateSpecializationDecl 0x244ed78 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:25 implicit class C\n" "| |-AccessSpecDecl 0x244f088 col:29 public\n" "| |-CXXMethodDecl 0x244f160 col:39 used foo 'int ()'\n" "| | `-CompoundStmt 0x247cb40 \n" "| | `-ReturnStmt 0x247cb28 \n" "| | `-IntegerLiteral 0x244ebe0 'int' 0\n" "| |-CXXConstructorDecl 0x247c540 col:25 implicit used constexpr C 'void () noexcept' inline default trivial\n" "| | `-CompoundStmt 0x247ca00 \n" "| |-CXXConstructorDecl 0x247c658 col:25 implicit constexpr C 'void (const C &)' inline default trivial noexcept-unevaluated 0x247c658\n" "| | `-ParmVarDecl 0x247c790 col:25 'const C &'\n" "| `-CXXConstructorDecl 0x247c828 col:25 implicit constexpr C 'void (C &&)' inline default trivial noexcept-unevaluated 0x247c828\n" "| `-ParmVarDecl 0x247c960 col:25 'C &&'\n"; ASSERT_EQUALS("class C { int foo ( ) { return 0 ; } }", parse(clang)); } void conditionalExpr() { const char clang[] = "`-VarDecl 0x257cc88 col:5 x 'int' cinit\n" " `-ConditionalOperator 0x257cda8 'int'\n" " |-ImplicitCastExpr 0x257cd60 'int' \n" " | `-DeclRefExpr 0x257cce8 'int' lvalue Var 0x257cae0 'a' 'int'\n" " |-ImplicitCastExpr 0x257cd78 'int' \n" " | `-DeclRefExpr 0x257cd10 'int' lvalue Var 0x257cb98 'b' 'int'\n" " `-ImplicitCastExpr 0x257cd90 'int' \n" " `-DeclRefExpr 0x257cd38 '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 \n" " `-CompoundAssignOperator 0x3570848 'int' lvalue '+=' ComputeLHSTy='int' ComputeResultTy='int'\n" " |-DeclRefExpr 0x3570800 'int' lvalue Var 0x3570788 'x' 'int'\n" " `-IntegerLiteral 0x3570828 '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 \n" " `-WhileStmt 0x2c31c20 \n" " |-<<>>\n" " |-IntegerLiteral 0x2c31bf8 'int' 0\n" " `-ContinueStmt 0x2c31c18 "; 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 'int' \n" " `-CharacterLiteral 0x2336b40 'int' 97"; ASSERT_EQUALS("int x@1 = ( int ) 'a' ;", parse(clang)); } void cxxBoolLiteralExpr() { const char clang[] = "`-VarDecl 0x3940608 col:6 x 'bool' cinit\n" " `-CXXBoolLiteralExpr 0x39406a8 'bool' true"; ASSERT_EQUALS("bool x@1 = true ;", parse(clang)); } void cxxConstructorDecl() { const char clang[] = "|-CXXConstructorDecl 0x428e890 col:11 C 'void ()'\n" "| `-CompoundStmt 0x428ea58 \n" "| `-BinaryOperator 0x428ea30 'int' lvalue '='\n" "| |-MemberExpr 0x428e9d8 'int' lvalue ->x 0x428e958\n" "| | `-CXXThisExpr 0x428e9c0 'C *' this\n" "| `-IntegerLiteral 0x428ea10 'int' 0\n" "`-FieldDecl 0x428e958 col:30 referenced x 'int'"; ASSERT_EQUALS("void C ( ) { this . x@1 = 0 ; } int x@1", parse(clang)); } void cxxConstructExpr1() { const char clang[] = "`-FunctionDecl 0x2dd7940 col:5 f 'Foo (Foo)'\n" " |-ParmVarDecl 0x2dd7880 col:11 used foo 'Foo'\n" " `-CompoundStmt 0x2dd80c0 \n" " `-ReturnStmt 0x2dd80a8 \n" " `-CXXConstructExpr 0x2dd8070 'Foo' 'void (Foo &&) noexcept'\n" " `-ImplicitCastExpr 0x2dd7f28 'Foo' xvalue \n" " `-DeclRefExpr 0x2dd7a28 '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 \n" " `-ReturnStmt 0x3e4cb68 \n" " `-CXXConstructExpr 0x3e4cb38 'std::string':'std::__cxx11::basic_string' '....' 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 \n" " |-DeclStmt 0x2c586d0 \n" " | `-VarDecl 0x2c58670 col:18 used p 'char *'\n" " `-DeclStmt 0x2c589b8 \n" " `-VarDecl 0x2c58798 col:33 s 'std::string':'std::__cxx11::basic_string' callinit\n" " `-ExprWithCleanups 0x2c589a0 'std::string':'std::__cxx11::basic_string'\n" " `-CXXConstructExpr 0x2c58960 'std::string':'std::__cxx11::basic_string' 'void (const char *, const std::allocator &)'\n" " |-ImplicitCastExpr 0x2c58870 'const char *' \n" " | `-ImplicitCastExpr 0x2c58858 'char *' \n" " | `-DeclRefExpr 0x2c58750 'char *' lvalue Var 0x2c58670 'p' 'char *'\n" " `-CXXDefaultArgExpr 0x2c58940 <> 'const std::allocator':'const std::allocator' lvalue\n"; ASSERT_EQUALS("void f ( ) { char * p@1 ; std::string s@2 ( p@1 ) ; }", parse(clang)); } void cxxForRangeStmt() { const char clang[] = "`-FunctionDecl 0x4280820 line:4:6 foo 'void ()'\n" " `-CompoundStmt 0x42810f0 \n" " `-CXXForRangeStmt 0x4281090 \n" " |-DeclStmt 0x4280c30 \n" " | `-VarDecl 0x42809c8 col:17 implicit referenced __range1 'char const (&)[6]' cinit\n" " | `-DeclRefExpr 0x42808c0 'const char [6]' lvalue Var 0x4280678 'hello' 'const char [6]'\n" " |-DeclStmt 0x4280ef8 \n" " | `-VarDecl 0x4280ca8 col:15 implicit used __begin1 'const char *':'const char *' cinit\n" " | `-ImplicitCastExpr 0x4280e10 'const char *' \n" " | `-DeclRefExpr 0x4280c48 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n" " |-DeclStmt 0x4280f10 \n" " | `-VarDecl 0x4280d18 col:15 implicit used __end1 'const char *':'const char *' cinit\n" " | `-BinaryOperator 0x4280e60 'const char *' '+'\n" " | |-ImplicitCastExpr 0x4280e48 'const char *' \n" " | | `-DeclRefExpr 0x4280c70 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n" " | `-IntegerLiteral 0x4280e28 'long' 6\n" " |-BinaryOperator 0x4280fa8 'bool' '!='\n" " | |-ImplicitCastExpr 0x4280f78 'const char *':'const char *' \n" " | | `-DeclRefExpr 0x4280f28 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" " | `-ImplicitCastExpr 0x4280f90 'const char *':'const char *' \n" " | `-DeclRefExpr 0x4280f50 'const char *':'const char *' lvalue Var 0x4280d18 '__end1' 'const char *':'const char *'\n" " |-UnaryOperator 0x4280ff8 'const char *':'const char *' lvalue prefix '++'\n" " | `-DeclRefExpr 0x4280fd0 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" " |-DeclStmt 0x4280958 \n" " | `-VarDecl 0x42808f8 col:13 c1 'char' cinit\n" " | `-ImplicitCastExpr 0x4281078 'char' \n" " | `-UnaryOperator 0x4281058 'const char' lvalue prefix '*' cannot overflow\n" " | `-ImplicitCastExpr 0x4281040 'const char *':'const char *' \n" " | `-DeclRefExpr 0x4281018 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" " `-CompoundStmt 0x42810e0 "; ASSERT_EQUALS("void foo ( ) {\n" "for ( char c1@1 : hello ) { } }", parse(clang)); } void cxxMemberCall() { const char clang[] = "`-FunctionDecl 0x320dc80 col:6 bar 'void ()'\n" " `-CompoundStmt 0x323bb08 \n" " |-DeclStmt 0x323ba40 \n" " | `-VarDecl 0x320df28 col:21 used c 'C':'C' callinit\n" " | `-CXXConstructExpr 0x323ba10 'C':'C' 'void () noexcept'\n" " `-CXXMemberCallExpr 0x323bab8 'int':'int'\n" " `-MemberExpr 0x323ba80 '' .foo 0x320e160\n" " `-DeclRefExpr 0x323ba58 'C':'C' lvalue Var 0x320df28 'c' 'C':'C'"; ASSERT_EQUALS("void bar ( ) { C c@1 ( C ( ) ) ; c@1 . foo ( ) ; }", parse(clang)); } void cxxMethodDecl() { const char clang[] = "|-CXXMethodDecl 0x55c786f5ad60 col:10 analyzeFile '_Bool (const std::string &, const std::string &, const std::string &, unsigned long long, std::list *)'\n" "| |-ParmVarDecl 0x55c786f5a4c8 col:41 buildDir 'const std::string &'\n" "| |-ParmVarDecl 0x55c786f5a580 col:70 sourcefile 'const std::string &'\n" "| |-ParmVarDecl 0x55c786f5a638 col:101 cfg 'const std::string &'\n" "| |-ParmVarDecl 0x55c786f5a6a8 col:125 checksum 'unsigned long long'\n" "| |-ParmVarDecl 0x55c786f5ac00 col:173 errors 'std::list *'\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 * errors@5 ) { }", parse(clang)); } void cxxNullPtrLiteralExpr() { const char clang[] = "`-VarDecl 0x2a7d650 <1.cpp:1:1, col:17> col:13 p 'const char *' cinit\n" " `-ImplicitCastExpr 0x2a7d708 'const char *' \n" " `-CXXNullPtrLiteralExpr 0x2a7d6f0 'nullptr_t'"; ASSERT_EQUALS("const char * p@1 = nullptr ;", parse(clang)); } void cxxOperatorCallExpr() { const char clang[] = "`-FunctionDecl 0x3c099f0 col:6 foo 'void ()'\n" " `-CompoundStmt 0x3c37308 \n" " |-DeclStmt 0x3c0a060 \n" " | `-VarDecl 0x3c09ae0 col:16 used c 'C' callinit\n" " | `-CXXConstructExpr 0x3c0a030 'C' 'void () noexcept'\n" " `-CXXOperatorCallExpr 0x3c372c0 'void'\n" " |-ImplicitCastExpr 0x3c372a8 'void (*)(int)' \n" " | `-DeclRefExpr 0x3c37250 'void (int)' lvalue CXXMethod 0x3c098c0 'operator=' 'void (int)'\n" " |-DeclRefExpr 0x3c0a078 'C' lvalue Var 0x3c09ae0 'c' 'C'\n" " `-IntegerLiteral 0x3c0a0a0 '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("", parse(clang)); } void cxxStaticCastExpr1() { const char clang[] = "`-VarDecl 0x2e0e650 col:5 a 'int' cinit\n" " `-CXXStaticCastExpr 0x2e0e728 'int' static_cast \n" " `-IntegerLiteral 0x2e0e6f0 'int' 0"; ASSERT_EQUALS("int a@1 = static_cast ( 0 ) ;", parse(clang)); } void cxxStaticCastExpr2() { const char clang[] = "`-VarDecl 0x2e0e650 col:5 a 'int' cinit\n" " `-CXXStaticCastExpr 0x3e453e8 'std::_Rb_tree_iterator, Library::AllocFunc> >' xvalue static_cast, struct Library::AllocFunc> > &&> \n" " `-DeclRefExpr 0x3e453b0 'std::_Rb_tree_iterator, Library::AllocFunc> >' lvalue ParmVar 0x3e45250 '' 'std::_Rb_tree_iterator, Library::AllocFunc> > &&'"; ASSERT_EQUALS("int a@1 = static_cast,structLibrary::AllocFunc>>&&> ( ) ;", parse(clang)); } void doStmt() { const char clang[] = "`-FunctionDecl 0x27fbbc8 col:6 foo 'void ()'\n" " `-CompoundStmt 0x27fbd08 \n" " `-DoStmt 0x27fbce8 \n" " |-CompoundStmt 0x27fbcb0 \n" " | `-UnaryOperator 0x27fbc90 'int' postfix '++'\n" " | `-DeclRefExpr 0x27fbc68 'int' lvalue Var 0x27fbae0 'x' 'int'\n" " `-IntegerLiteral 0x27fbcc8 'int' 1"; ASSERT_EQUALS("void foo ( ) { do { ++ x ; } while ( 1 ) ; }", parse(clang)); } void forStmt() { const char clang[] = "`-FunctionDecl 0x2f93ae0 <1.c:1:1, col:56> col:5 main 'int ()'\n" " `-CompoundStmt 0x2f93dc0 \n" " |-ForStmt 0x2f93d50 \n" " | |-DeclStmt 0x2f93c58 \n" " | | `-VarDecl 0x2f93bd8 col:23 used i 'int' cinit\n" " | | `-IntegerLiteral 0x2f93c38 'int' 0\n" " | |-<<>>\n" " | |-BinaryOperator 0x2f93cd0 'int' '<'\n" " | | |-ImplicitCastExpr 0x2f93cb8 'int' \n" " | | | `-DeclRefExpr 0x2f93c70 'int' lvalue Var 0x2f93bd8 'i' 'int'\n" " | | `-IntegerLiteral 0x2f93c98 'int' 10\n" " | |-UnaryOperator 0x2f93d20 'int' postfix '++'\n" " | | `-DeclRefExpr 0x2f93cf8 'int' lvalue Var 0x2f93bd8 'i' 'int'\n" " | `-CompoundStmt 0x2f93d40 \n" " `-ReturnStmt 0x2f93da8 \n" " `-IntegerLiteral 0x2f93d88 '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:14 x 'int'\n" " `-ParmVarDecl 0x3122b58 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:13 used x 'int'\n" " |-ParmVarDecl 0x24b2b58 col:20 used y 'int'\n" " `-CompoundStmt 0x24b2de8 \n" " `-ReturnStmt 0x24b2dd0 \n" " `-BinaryOperator 0x24b2da8 'int' '/'\n" " |-ImplicitCastExpr 0x24b2d78 'int' \n" " | `-DeclRefExpr 0x24b2d28 'int' lvalue ParmVar 0x24b2ae0 'x' 'int'\n" " `-ImplicitCastExpr 0x24b2d90 'int' \n" " `-DeclRefExpr 0x24b2d50 'int' lvalue ParmVar 0x24b2b58 'y' 'int'"; ASSERT_EQUALS("int foo ( int x@1 , int y@2 ) {\n\n" "return x@1 / y@2 ; }", parse(clang)); } void funcdecl3() { const char clang[] = "|-FunctionDecl 0x27cb6b8 col:12 __overflow 'int (FILE *, int)' extern\n" "| |-ParmVarDecl 0x27cb528 col:30 'FILE *'\n" "| `-ParmVarDecl 0x27cb5a0 col:35 'int'"; ASSERT_EQUALS("int __overflow ( FILE * , int ) ;", parse(clang)); } void funcdecl4() { const char clang[] = "|-FunctionDecl 0x272bb60 col:15 implicit fwrite 'unsigned long (const void *, unsigned long, unsigned long, FILE *)' extern\n" "| |-ParmVarDecl 0x272cc40 <> 'const void *'\n" "| |-ParmVarDecl 0x272cca0 <> 'unsigned long'\n" "| |-ParmVarDecl 0x272cd00 <> 'unsigned long'\n" "| `-ParmVarDecl 0x272cd60 <> 'FILE *'"; ASSERT_EQUALS("unsigned long fwrite ( const void * , unsigned long , unsigned long , FILE * ) ;", parse(clang)); } void functionTemplateDecl1() { const char clang[] = "`-FunctionTemplateDecl 0x3242860 col:21 foo"; ASSERT_EQUALS("", parse(clang)); } void functionTemplateDecl2() { const char clang[] = "|-FunctionTemplateDecl 0x333a860 col:21 foo\n" "| |-TemplateTypeParmDecl 0x333a5f8 col:16 referenced class depth 0 index 0 T\n" "| |-FunctionDecl 0x333a7c0 col:21 foo 'T (T)'\n" "| | |-ParmVarDecl 0x333a6c0 col:27 referenced t 'T'\n" "| | `-CompoundStmt 0x333a980 \n" "| | `-ReturnStmt 0x333a968 \n" "| | `-BinaryOperator 0x333a940 '' '+'\n" "| | |-DeclRefExpr 0x333a8f8 'T' lvalue ParmVar 0x333a6c0 't' 'T'\n" "| | `-IntegerLiteral 0x333a920 'int' 1\n" "| `-FunctionDecl 0x333ae00 col:21 used foo 'int (int)'\n" "| |-TemplateArgument type 'int'\n" "| |-ParmVarDecl 0x333ad00 col:27 used t 'int':'int'\n" "| `-CompoundStmt 0x333b0a8 \n" "| `-ReturnStmt 0x333b090 \n" "| `-BinaryOperator 0x333b068 'int' '+'\n" "| |-ImplicitCastExpr 0x333b050 'int':'int' \n" "| | `-DeclRefExpr 0x333b028 'int':'int' lvalue ParmVar 0x333ad00 't' 'int':'int'\n" "| `-IntegerLiteral 0x333a920 'int' 1\n" "`-FunctionDecl 0x333a9f8 col:1 invalid bar 'int ()'\n" " `-CompoundStmt 0x333b010 \n" " `-CallExpr 0x333afe0 'int':'int'\n" " |-ImplicitCastExpr 0x333afc8 'int (*)(int)' \n" " | `-DeclRefExpr 0x333af00 'int (int)' lvalue Function 0x333ae00 'foo' 'int (int)' (FunctionTemplate 0x333a860 'foo')\n" " `-IntegerLiteral 0x333ab48 'int' 1"; ASSERT_EQUALS("int foo ( int t@1 ) { return t@1 + 1 ; }\n" "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:13 used x 'int'\n" " `-CompoundStmt 0x2637d70 \n" " `-IfStmt 0x2637d38 \n" " |-<<>>\n" " |-<<>>\n" " |-BinaryOperator 0x2637cf0 'int' '>'\n" " | |-ImplicitCastExpr 0x2637cd8 'int' \n" " | | `-DeclRefExpr 0x2637c90 'int' lvalue ParmVar 0x2637ae0 'x' 'int'\n" " | `-IntegerLiteral 0x2637cb8 'int' 10\n" " |-CompoundStmt 0x2637d18 \n" " `-CompoundStmt 0x2637d28 "; ASSERT_EQUALS("int foo ( int x@1 ) {\n" "if ( x@1 > 10 ) { }\n" "else { } }", 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 'const int [3]'\n" "| |-IntegerLiteral 0x397c720 'int' 1\n" "| |-IntegerLiteral 0x397c740 'int' 2\n" "| `-IntegerLiteral 0x397c760 '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 \n" " `-LabelStmt 0x2ed1ce8 'loop'\n" " `-GotoStmt 0x2ed1cd0 '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:16 referenced x 'int'\n" "`-FunctionDecl 0x2441cf8 col:5 foo 'int (struct S)'\n" " |-ParmVarDecl 0x2441be8 col:18 used s 'struct S':'struct S'\n" " `-CompoundStmt 0x2441e70 \n" " `-ReturnStmt 0x2441e58 \n" " `-ImplicitCastExpr 0x2441e40 'int' \n" " `-MemberExpr 0x2441e08 'int' lvalue .x 0x2441b48\n" " `-DeclRefExpr 0x2441de0 'struct S':'struct S' lvalue ParmVar 0x2441be8 's' 'struct S':'struct S'"; ASSERT_EQUALS("struct S { int x@1 ; } ;\n" "int foo ( struct S s@2 ) { return s@2 . x@1 ; }", parse(clang)); } void namespaceDecl() { const char clang[] = "`-NamespaceDecl 0x2e5f658 col:11 x\n" " `-VarDecl 0x2e5f6d8 col:19 var 'int'"; ASSERT_EQUALS("namespace x { int var@1 ; }", parse(clang)); } void recordDecl() { const char clang[] = "`-RecordDecl 0x354eac8 <1.c:1:1, line:4:1> line:1:8 struct S definition\n" " |-FieldDecl 0x354eb88 col:7 x 'int'\n" " `-FieldDecl 0x354ebe8 col:7 y 'int'"; ASSERT_EQUALS("struct S\n" "{ int x@1 ;\n" "int y@2 ; } ;", parse(clang)); } void switchStmt() { const char clang[] = "`-FunctionDecl 0x2796ba0 <1.c:1:1, col:35> col:6 foo 'void (int)'\n" " |-ParmVarDecl 0x2796ae0 col:14 used x 'int'\n" " `-CompoundStmt 0x2796d18 \n" " |-SwitchStmt 0x2796cc8 \n" " | |-<<>>\n" " | |-<<>>\n" " | |-ImplicitCastExpr 0x2796cb0 'int' \n" " | | `-DeclRefExpr 0x2796c88 'int' lvalue ParmVar 0x2796ae0 'x' 'int'\n" " | `-CompoundStmt 0x2796cf8 \n" " `-NullStmt 0x2796d08 "; ASSERT_EQUALS("void foo ( int x@1 ) { switch ( x@1 ) { } ; }", parse(clang)); } void typedefDecl1() { const char clang[] = "|-TypedefDecl 0x2d60180 <> implicit __int128_t '__int128'\n" "| `-BuiltinType 0x2d5fe80 '__int128'"; ASSERT_EQUALS("typedef __int128 __int128_t ;", parse(clang)); } void typedefDecl2() { const char clang[] = "|-TypedefDecl 0x2d604a8 <> implicit __NSConstantString 'struct __NSConstantString_tag'\n" "| `-RecordType 0x2d602c0 'struct __NSConstantString_tag'\n" "| `-Record 0x2d60238 '__NSConstantString_tag'"; ASSERT_EQUALS("typedef struct __NSConstantString_tag __NSConstantString ;", parse(clang)); } void typedefDecl3() { const char clang[] = "|-TypedefDecl 0x2d60540 <> implicit __builtin_ms_va_list 'char *'\n" "| `-PointerType 0x2d60500 'char *'\n" "| `-BuiltinType 0x2d5f980 'char'"; ASSERT_EQUALS("typedef char * __builtin_ms_va_list ;", parse(clang)); } void unaryExprOrTypeTraitExpr1() { const char clang[] = "`-VarDecl 0x24cc610 col:5 x 'int' cinit\n" " `-ImplicitCastExpr 0x24cc6e8 'int' \n" " `-UnaryExprOrTypeTraitExpr 0x24cc6c8 'unsigned long' sizeof 'int'\n"; ASSERT_EQUALS("int x@1 = sizeof ( int ) ;", parse(clang)); } void unaryExprOrTypeTraitExpr2() { const char clang[] = "`-VarDecl 0x27c6c00 col:9 x 'int' cinit\n" " `-ImplicitCastExpr 0x27c6cc8 'int' \n" " `-UnaryExprOrTypeTraitExpr 0x27c6ca8 'unsigned long' sizeof\n" " `-ParenExpr 0x27c6c88 'char [10]' lvalue\n" " `-DeclRefExpr 0x27c6c60 'char [10]' lvalue Var 0x27c6b48 'buf' 'char [10]'"; ASSERT_EQUALS("int x@1 = sizeof ( char [10] ) ;", parse(clang)); } void unaryOperator() { const char clang[] = "`-FunctionDecl 0x2dd9748 <1.cpp:2:1, col:44> col:5 foo 'int (int *)'\n" " |-ParmVarDecl 0x2dd9680 col:19 used p 'int *'\n" " `-CompoundStmt 0x2dd9908 \n" " `-ReturnStmt 0x2dd98f0 \n" " `-BinaryOperator 0x2dd98c8 'int' '/'\n" " |-IntegerLiteral 0x2dd9830 'int' 100000\n" " `-ImplicitCastExpr 0x2dd98b0 'int' \n" " `-UnaryOperator 0x2dd9890 'int' lvalue prefix '*' cannot overflow\n" " `-ImplicitCastExpr 0x2dd9878 'int *' \n" " `-DeclRefExpr 0x2dd9850 '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 'int' 1\n" "`-VarDecl 0x32b8b78 col:5 b 'int' cinit\n" " `-ImplicitCastExpr 0x32b8c00 'int' \n" " `-DeclRefExpr 0x32b8bd8 'int' lvalue Var 0x32b8aa0 'a' 'int'"; ASSERT_EQUALS("int a@1 = 1 ;\n" "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:6 foo 'void ()'\n" " `-CompoundStmt 0x3873dd0 \n" " `-BinaryOperator 0x3873da8 'int' '='\n" " |-ArraySubscriptExpr 0x3873d60 'int' lvalue\n" " | |-ImplicitCastExpr 0x3873d48 'int *' \n" " | | `-DeclRefExpr 0x3873cd8 'int [10]' lvalue Var 0x3873b50 'a' 'int [10]'\n" " | `-IntegerLiteral 0x3873d00 'int' 0\n" " `-IntegerLiteral 0x3873d88 'int' 0\n"; ASSERT_EQUALS("int [10] a@1 ;\n" // <- TODO "\n" "void foo ( ) {\n" "\n" "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 col:14 stdin 'FILE *' extern"; ASSERT_EQUALS("FILE * stdin@1 ;", parse(clang)); } void vardecl5() { const char clang[] = "|-VarDecl 0x2e31fc0 col:26 sys_errlist 'const char *const []' extern"; ASSERT_EQUALS("const char *const [] sys_errlist@1 ;", parse(clang)); } void whileStmt() { const char clang[] = "`-FunctionDecl 0x3d45b18 <1.c:1:1, line:3:1> line:1:6 foo 'void ()'\n" " `-CompoundStmt 0x3d45c48 \n" " `-WhileStmt 0x3d45c28 \n" " |-<<>>\n" " |-IntegerLiteral 0x3d45bf8 'int' 0\n" " `-NullStmt 0x3d45c18 "; ASSERT_EQUALS("void foo ( ) {\n" "while ( 0 ) { ; } }", parse(clang)); } #define GET_SYMBOL_DB(clang) \ Settings settings; \ settings.platform(cppcheck::Platform::PlatformType::Unix64); \ Tokenizer tokenizer(&settings, this); \ std::istringstream istr(clang); \ clangimport::parseClangAstDump(&tokenizer, istr); \ const SymbolDatabase *db = tokenizer.getSymbolDatabase(); \ ASSERT(db); void symbolDatabaseFunction1() { const char clang[] = "|-FunctionDecl 0x3aea7a0 <1.cpp:2:1, col:22> col:6 used foo 'void (int, int)'\n" "| |-ParmVarDecl 0x3aea650 col:14 x 'int'\n" "| `-ParmVarDecl 0x3aea6c8 col:21 y 'int'\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:14 'int'\n" "| `-ParmVarDecl 0x3aea6c8 col:21 'int'\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 symbolDatabaseNodeType1() { const char clang[] = "`-FunctionDecl 0x32438c0 line:5:6 foo 'a::b (a::b)'\n" " |-ParmVarDecl 0x32437b0 col:15 used i 'a::b':'long'\n" " `-CompoundStmt 0x3243a60 \n" " `-ReturnStmt 0x3243a48 \n" " `-BinaryOperator 0x3243a20 'long' '+'\n" " |-ImplicitCastExpr 0x32439f0 'a::b':'long' \n" " | `-DeclRefExpr 0x32439a8 'a::b':'long' lvalue ParmVar 0x32437b0 'i' 'a::b':'long'\n" " `-ImplicitCastExpr 0x3243a08 'long' \n" " `-IntegerLiteral 0x32439d0 '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 valueFlow1() { const char clang[] = "|-RecordDecl 0x2fc5a88 <1.c:1:1, line:4:1> line:1:8 struct S definition\n" "| |-FieldDecl 0x2fc5b48 col:7 x 'int'\n" "| `-FieldDecl 0x2fc5c10 col:7 buf 'int [10]'\n" "`-VarDecl 0x2fc5c70 col:5 sz 'int' cinit\n" " `-ImplicitCastExpr 0x2fc5d88 'int' \n" " `-UnaryExprOrTypeTraitExpr 0x2fc5d68 '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() { const char clang[] = "`-VarDecl 0x4145bc0 col:5 sz 'int' cinit\n" " `-ImplicitCastExpr 0x4145c88 'int' \n" " `-UnaryExprOrTypeTraitExpr 0x4145c68 'unsigned long' sizeof\n" " `-ParenExpr 0x4145c48 'char [10]' lvalue\n" " `-DeclRefExpr 0x4145c20 'char [10]' lvalue Var 0x4145b08 'buf' 'char [10]'"; GET_SYMBOL_DB(clang); const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof ("); ASSERT(!!tok); tok = tok->next(); ASSERT(tok->hasKnownIntValue()); ASSERT_EQUALS(10, tok->getKnownIntValue()); } }; REGISTER_TEST(TestClangImport)