Clang import testing: Compare AST
This commit is contained in:
parent
b052843655
commit
c3517924d0
|
@ -1545,11 +1545,25 @@ static Token * createAstAtToken(Token *tok, bool cpp)
|
|||
return tok->linkAt(1);
|
||||
|
||||
if (Token::Match(tok, "%type% %name%|*|&|::") && tok->str() != "return") {
|
||||
int typecount = 0;
|
||||
Token *typetok = tok;
|
||||
while (Token::Match(typetok, "%type%|::|*|&"))
|
||||
while (Token::Match(typetok, "%type%|::|*|&")) {
|
||||
if (typetok->isName() && !Token::simpleMatch(typetok->previous(), "::"))
|
||||
typecount++;
|
||||
typetok = typetok->next();
|
||||
}
|
||||
if (Token::Match(typetok, "%var% =") && typetok->varId())
|
||||
tok = typetok;
|
||||
|
||||
// Do not create AST for function declaration
|
||||
if (typetok &&
|
||||
typecount >= 2 &&
|
||||
!Token::Match(tok, "return|throw") &&
|
||||
Token::Match(typetok->previous(), "%name% (") &&
|
||||
typetok->previous()->varId() == 0 &&
|
||||
!typetok->previous()->isKeyword() &&
|
||||
Token::Match(typetok->link(), ") const|;|{"))
|
||||
return typetok;
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "return|case") ||
|
||||
|
|
|
@ -42,6 +42,39 @@ def check_symbol_database(code):
|
|||
assert get_debug_section('### Symbol database', stdout1) == get_debug_section('### Symbol database', stdout2)
|
||||
|
||||
|
||||
def check_ast(code):
|
||||
# Only compare syntax trees if clang is found in PATH
|
||||
try:
|
||||
subprocess.call(['clang', '--version'])
|
||||
except OSError:
|
||||
return
|
||||
|
||||
testfile = 'test.cpp'
|
||||
with open(testfile, 'w+t') as f:
|
||||
f.write(code)
|
||||
ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile])
|
||||
ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile])
|
||||
os.remove(testfile)
|
||||
assert get_debug_section('##AST', stdout1) == get_debug_section('##AST', stdout2)
|
||||
|
||||
|
||||
def todo_check_ast(code):
|
||||
# Only compare syntax trees if clang is found in PATH
|
||||
try:
|
||||
subprocess.call(['clang', '--version'])
|
||||
except OSError:
|
||||
return
|
||||
|
||||
testfile = 'test.cpp'
|
||||
with open(testfile, 'w+t') as f:
|
||||
f.write(code)
|
||||
ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile])
|
||||
ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile])
|
||||
os.remove(testfile)
|
||||
assert get_debug_section('##AST', stdout1) != get_debug_section('##AST', stdout2)
|
||||
|
||||
|
||||
|
||||
def test1():
|
||||
check_symbol_database('int main(){return 0;}')
|
||||
|
||||
|
@ -49,5 +82,14 @@ def test2():
|
|||
code = 'struct Foo { void f(); }; void Foo::f() {}'
|
||||
check_symbol_database(code)
|
||||
|
||||
def test_ast_calculations():
|
||||
check_ast('int x = 5; int y = (x + 4) * 2;')
|
||||
todo_check_ast('int dostuff(int x) { return x ? 3 : 5; }')
|
||||
|
||||
def test_ast_control_flow():
|
||||
check_ast('void foo(int x) { if (x > 5){} }')
|
||||
check_ast('int dostuff() { for (int x = 0; x < 10; x++); }')
|
||||
todo_check_ast('void foo(int x) { switch (x) {case 1: break; } }')
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5838,7 +5838,7 @@ private:
|
|||
|
||||
check("void f() {\n"
|
||||
" int val = 0;\n"
|
||||
" int *p = &val;n"
|
||||
" int *p = &val;\n"
|
||||
" if (*p < 0) continue;\n"
|
||||
" if ((*p > 0)) {}\n"
|
||||
"}\n");
|
||||
|
|
|
@ -1153,8 +1153,7 @@ private:
|
|||
|
||||
ASSERT_EQUALS(expected, tok(code, false));
|
||||
ASSERT_EQUALS_WITHOUT_LINENUMBERS(
|
||||
"[test.cpp:31]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n"
|
||||
"[test.cpp:28]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n",
|
||||
"[test.cpp:31]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
|
@ -2158,7 +2157,7 @@ private:
|
|||
" return fred;\n"
|
||||
"}";
|
||||
tok(code);
|
||||
ASSERT_EQUALS_WITHOUT_LINENUMBERS("[test.cpp:2]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n", errout.str());
|
||||
ASSERT_EQUALS_WITHOUT_LINENUMBERS("", errout.str());
|
||||
}
|
||||
|
||||
void simplifyTypedef101() { // ticket #3003 (segmentation fault)
|
||||
|
|
|
@ -6665,7 +6665,7 @@ private:
|
|||
|
||||
void executableScopeWithUnknownFunction() {
|
||||
GET_SYMBOL_DB("class Fred {\n"
|
||||
" void foo(const std::string & a = "");\n"
|
||||
" void foo(const std::string & a = \"\");\n"
|
||||
"};\n"
|
||||
"Fred::foo(const std::string & b) { }\n");
|
||||
|
||||
|
|
|
@ -7579,7 +7579,7 @@ private:
|
|||
|
||||
ASSERT_EQUALS("a0>bc/d:?", testAst("(a>0) ? (b/(c)) : d;"));
|
||||
ASSERT_EQUALS("abc/+d+", testAst("a + (b/(c)) + d;"));
|
||||
ASSERT_EQUALS("f( x1024x/0:?", testAst("void f() { x ? 1024 / x : 0; }"));
|
||||
ASSERT_EQUALS("x1024x/0:?", testAst("void f() { x ? 1024 / x : 0; }"));
|
||||
|
||||
ASSERT_EQUALS("absizeofd(ef.+(=", testAst("a = b(sizeof(c d) + e.f)"));
|
||||
|
||||
|
@ -7623,11 +7623,11 @@ private:
|
|||
|
||||
ASSERT_EQUALS("catch...(", testAst("try {} catch (...) {}"));
|
||||
|
||||
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&);"));
|
||||
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&&);"));
|
||||
ASSERT_EQUALS("", testAst("void Foo(Bar&);"));
|
||||
ASSERT_EQUALS("", testAst("void Foo(Bar&&);"));
|
||||
|
||||
ASSERT_EQUALS("FooBarb&(", testAst("void Foo(Bar& b);"));
|
||||
ASSERT_EQUALS("FooBarb&&(", testAst("void Foo(Bar&& b);"));
|
||||
ASSERT_EQUALS("Barb&", testAst("void Foo(Bar& b);"));
|
||||
ASSERT_EQUALS("Barb&&", testAst("void Foo(Bar&& b);"));
|
||||
|
||||
ASSERT_EQUALS("DerivedDerived::(", testAst("Derived::~Derived() {}"));
|
||||
|
||||
|
@ -7720,7 +7720,7 @@ private:
|
|||
ASSERT_EQUALS("a::new=", testAst("a = new (b) ::X;"));
|
||||
ASSERT_EQUALS("aA1(new(bB2(new(,", testAst("a(new A(1)), b(new B(2))"));
|
||||
ASSERT_EQUALS("Fred10[new", testAst(";new Fred[10];"));
|
||||
ASSERT_EQUALS("f( adelete", testAst("void f() { delete a; }"));
|
||||
ASSERT_EQUALS("adelete", testAst("void f() { delete a; }"));
|
||||
|
||||
// invalid code (libreoffice), don't hang
|
||||
// #define SlideSorterViewShell
|
||||
|
@ -7788,7 +7788,7 @@ private:
|
|||
// Type{data}()
|
||||
ASSERT_EQUALS("ab{(=", testAst("a=b{}();"));
|
||||
ASSERT_EQUALS("abc{((=", testAst("a=b(c{}());"));
|
||||
ASSERT_EQUALS("f( xNULL!=0(x(:?", testAst("void f() { {} ((x != NULL) ? (void)0 : x()); }"));
|
||||
ASSERT_EQUALS("xNULL!=0(x(:?", testAst("void f() { {} ((x != NULL) ? (void)0 : x()); }"));
|
||||
|
||||
// ({..})
|
||||
ASSERT_EQUALS("a{+d+ bc+", testAst("a+({b+c;})+d"));
|
||||
|
@ -7824,7 +7824,7 @@ private:
|
|||
ASSERT_EQUALS("a0{,( \'\'abc12:?,", testAst("a(0, {{\'\', (abc) ? 1 : 2}});"));
|
||||
|
||||
// struct initialization hang
|
||||
ASSERT_EQUALS("sbar.1{,{(={= fcmd( forfieldfield++;;(",
|
||||
ASSERT_EQUALS("sbar.1{,{(={= forfieldfield++;;(",
|
||||
testAst("struct S s = {.bar = (struct foo) { 1, { } } };\n"
|
||||
"void f(struct cmd *) { for (; field; field++) {} }"));
|
||||
|
||||
|
@ -7864,8 +7864,8 @@ private:
|
|||
// #9127
|
||||
const char code1[] = "using uno::Ref;\n"
|
||||
"Ref<X> r;\n"
|
||||
"int x(0);";
|
||||
ASSERT_EQUALS("unoRef:: x0(", testAst(code1));
|
||||
"int var(0);";
|
||||
ASSERT_EQUALS("unoRef:: var0(", testAst(code1));
|
||||
|
||||
ASSERT_EQUALS("vary=", testAst("std::string var = y;"));
|
||||
}
|
||||
|
@ -7897,10 +7897,10 @@ private:
|
|||
ASSERT_EQUALS("1f2(+3+", testAst("1+f(2)+3"));
|
||||
ASSERT_EQUALS("1f23,(+4+", testAst("1+f(2,3)+4"));
|
||||
ASSERT_EQUALS("1f2a&,(+", testAst("1+f(2,&a)"));
|
||||
ASSERT_EQUALS("fargv[(", testAst("int f(char argv[]);"));
|
||||
ASSERT_EQUALS("fchar(", testAst("extern unsigned f(const char *);"));
|
||||
ASSERT_EQUALS("fcharformat*...,(", testAst("extern void f(const char *format, ...);"));
|
||||
ASSERT_EQUALS("for_each_commit_graftint((void,(", testAst("extern int for_each_commit_graft(int (*)(int*), void *);"));
|
||||
ASSERT_EQUALS("argv[", testAst("int f(char argv[]);"));
|
||||
ASSERT_EQUALS("", testAst("extern unsigned f(const char *);"));
|
||||
ASSERT_EQUALS("charformat*...,", testAst("extern void f(const char *format, ...);"));
|
||||
ASSERT_EQUALS("int((void,", testAst("extern int for_each_commit_graft(int (*)(int*), void *);"));
|
||||
ASSERT_EQUALS("for;;(", testAst("for (;;) {}"));
|
||||
ASSERT_EQUALS("xsizeofvoid(=", testAst("x=sizeof(void*)"));
|
||||
ASSERT_EQUALS("abc{d{,{(=", testAst("a = b({ c{}, d{} });"));
|
||||
|
@ -7918,7 +7918,7 @@ private:
|
|||
|
||||
// This two unit tests were added to avoid a crash. The actual correct AST result for non-executable code has not been determined so far.
|
||||
ASSERT_EQUALS("Cpublica::b:::", testAst("class C : public ::a::b<bool> { };"));
|
||||
ASSERT_EQUALS("AB: f( abc+=", testAst("struct A : public B<C*> { void f() { a=b+c; } };"));
|
||||
ASSERT_EQUALS("AB: abc+=", testAst("struct A : public B<C*> { void f() { a=b+c; } };"));
|
||||
|
||||
ASSERT_EQUALS("xfts(=", testAst("; auto x = f(ts...);"));
|
||||
}
|
||||
|
@ -8011,7 +8011,7 @@ private:
|
|||
|
||||
// #9662
|
||||
ASSERT_EQUALS("b{[{ stdunique_ptr::0nullptrnullptr:?{", testAst("auto b{[] { std::unique_ptr<void *>{0 ? nullptr : nullptr}; }};"));
|
||||
ASSERT_EQUALS("a( b{[=", testAst("void a() { [b = [] { ; }] {}; }"));
|
||||
ASSERT_EQUALS("b{[=", testAst("void a() { [b = [] { ; }] {}; }"));
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue