// Cppcheck - A tool for static C/C++ code analysis
// Copyright (C) 2007-2021 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(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(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(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(valueFlow1);
TEST_CASE(valueFlow2);
TEST_CASE(valueType1);
TEST_CASE(valueType2);
}
std::string parse(const char clang[]) {
Settings settings;
settings.clang = true;
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 \n"
" `-WhileStmt 0x2c31c20 \n"
" |-<<>>\n"
" |-IntegerLiteral 0x2c31bf8 'int' 0\n"
" `-BreakStmt 0x3687c18 ";
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:14 used x 'int'\n"
" `-CompoundStmt 0x2444e00 \n"
" `-CallExpr 0x7f5a6c04b158 'bool'\n"
" |-ImplicitCastExpr 0x7f5a6c04b140 'bool (*)(const Token *, const char *, int)' \n"
" | `-DeclRefExpr 0x7f5a6c04b0a8 'bool (const Token *, const char *, int)' lvalue CXXMethod 0x43e5600 'Match' 'bool (const Token *, const char *, int)'\n"
" |-ImplicitCastExpr 0x7f5a6c04b1c8 'const Token *' \n"
" | `-ImplicitCastExpr 0x7f5a6c04b1b0 'Token *' \n"
" | `-DeclRefExpr 0x7f5a6c04b0e0 'Token *' lvalue Var 0x7f5a6c045968 'tokAfterCondition' 'Token *'\n"
" |-ImplicitCastExpr 0x7f5a6c04b1e0 'const char *' \n"
" | `-StringLiteral 0x7f5a6c04b108 'const char [11]' lvalue \"%name% : {\"\n"
" `-CXXDefaultArgExpr 0x7f5a6c04b1f8 <> '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: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 ) { switch ( x@1 ) { case 16 : case 32 : x@1 = 123 ; 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 ; } C ( ) { } C ( const C & ) = default ; C ( C && ) = default ; } ;", 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 cxxConstructorDecl1() {
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("C ( ) { this . x@1 = 0 ; } int x@1", parse(clang));
}
void cxxConstructorDecl2() {
const char clang[] = "`-CXXConstructorDecl 0x1c208c0 col:11 implicit constexpr basic_string 'void (std::basic_string &&)' inline default trivial noexcept-unevaluated 0x1c208c0\n"
" `-ParmVarDecl 0x1c209f0 col:11 'std::basic_string &&'";
ASSERT_EQUALS("basic_string ( std::basic_string && ) = default ;", 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 cxxDeleteExpr() {
const char clang[] = "|-FunctionDecl 0x2e0e740 <1.cpp:1:1, col:28> col:6 f 'void (int *)'\n"
"| |-ParmVarDecl 0x2e0e680 col:13 used p 'int *'\n"
"| `-CompoundStmt 0x2e0ee70 \n"
"| `-CXXDeleteExpr 0x2e0ee48 'void' Function 0x2e0ebb8 'operator delete' 'void (void *) noexcept'\n"
"| `-ImplicitCastExpr 0x2e0e850 'int *' \n"
"| `-DeclRefExpr 0x2e0e828 '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 col:3 ~S 'void () noexcept'\n"
" `-CompoundStmt 0x8ed1a8 ";
ASSERT_EQUALS("struct S { ~S ( ) { } } ;", parse(clang));
}
void cxxForRangeStmt1() {
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 ( ) { for ( char c1@1 : hello ) { } }",
parse(clang));
}
void cxxForRangeStmt2() {
// clang 9
const char clang[] = "`-FunctionDecl 0xc15d98 col:6 foo 'void ()'\n"
" `-CompoundStmt 0xc16668 \n"
" `-CXXForRangeStmt 0xc165f8 \n"
" |-<<>>\n"
" |-DeclStmt 0xc161c0 \n"
" | `-VarDecl 0xc15f48 col:25 implicit referenced __range1 'int const (&)[4]' cinit\n"
" | `-DeclRefExpr 0xc15e38 'const int [4]' lvalue Var 0xc15ac0 'values' 'const int [4]'\n"
" |-DeclStmt 0xc16498 \n"
" | `-VarDecl 0xc16228 col:24 implicit used __begin1 'const int *':'const int *' cinit\n"
" | `-ImplicitCastExpr 0xc163b0 'const int *' \n"
" | `-DeclRefExpr 0xc161d8 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n"
" |-DeclStmt 0xc164b0 \n"
" | `-VarDecl 0xc162a0 col:24 implicit used __end1 'const int *':'const int *' cinit\n"
" | `-BinaryOperator 0xc16400 'const int *' '+'\n"
" | |-ImplicitCastExpr 0xc163e8 'const int *' \n"
" | | `-DeclRefExpr 0xc161f8 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n"
" | `-IntegerLiteral 0xc163c8 'long' 4\n"
" |-BinaryOperator 0xc16538 'bool' '!='\n"
" | |-ImplicitCastExpr 0xc16508 'const int *':'const int *' \n"
" | | `-DeclRefExpr 0xc164c8 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" | `-ImplicitCastExpr 0xc16520 'const int *':'const int *' \n"
" | `-DeclRefExpr 0xc164e8 'const int *':'const int *' lvalue Var 0xc162a0 '__end1' 'const int *':'const int *'\n"
" |-UnaryOperator 0xc16578 'const int *':'const int *' lvalue prefix '++'\n"
" | `-DeclRefExpr 0xc16558 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" |-DeclStmt 0xc15ed8 \n"
" | `-VarDecl 0xc15e70 col:23 v 'int' cinit\n"
" | `-ImplicitCastExpr 0xc165e0 'int' \n"
" | `-UnaryOperator 0xc165c8 'const int' lvalue prefix '*' cannot overflow\n"
" | `-ImplicitCastExpr 0xc165b0 'const int *':'const int *' \n"
" | `-DeclRefExpr 0xc16590 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n"
" `-CompoundStmt 0xc16658 ";
ASSERT_EQUALS("void foo ( ) { for ( int v@1 : values ) { } }",
parse(clang));
}
void cxxFunctionalCastExpr() {
const char clang[] = "`-FunctionDecl 0x156fe98 line:1:5 main 'int (int, char **)'\n"
" |-ParmVarDecl 0x156fd00 col:14 argc 'int'\n"
" |-ParmVarDecl 0x156fdb8 col:27 argv 'char **'\n"
" `-CompoundStmt 0x1596410 \n"
" |-DeclStmt 0x15946a8 \n"
" | `-VarDecl 0x1570118 col:11 used setCode 'MyVar':'MyVar' cinit\n"
" | `-ExprWithCleanups 0x1594690 'MyVar':'MyVar'\n"
" | `-CXXConstructExpr 0x1594660 'MyVar':'MyVar' 'void (MyVar &&) noexcept' elidable\n"
" | `-MaterializeTemporaryExpr 0x1592b68 'MyVar':'MyVar' xvalue\n"
" | `-CXXFunctionalCastExpr 0x1592b40 'MyVar':'MyVar' functional cast to MyVar \n"
" | `-CXXConstructExpr 0x15929f0