Add unit tests for expr ids (#5722)
This commit is contained in:
parent
ae27b613ae
commit
6192d0d3fa
|
@ -16,13 +16,14 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "library.h"
|
|
||||||
#include "platform.h"
|
|
||||||
#include "settings.h"
|
|
||||||
#include "symboldatabase.h"
|
|
||||||
#include "errortypes.h"
|
#include "errortypes.h"
|
||||||
#include "fixture.h"
|
#include "fixture.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "library.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "sourcelocation.h"
|
||||||
|
#include "symboldatabase.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "tokenlist.h"
|
#include "tokenlist.h"
|
||||||
|
@ -82,6 +83,60 @@ private:
|
||||||
return tokenizer.tokenize(istr, filename) ? tokenizer.getSymbolDatabase() : nullptr;
|
return tokenizer.tokenize(istr, filename) ? tokenizer.getSymbolDatabase() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const Token* findToken(Tokenizer& tokenizer, const std::string& expr, unsigned int exprline)
|
||||||
|
{
|
||||||
|
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
|
if (Token::simpleMatch(tok, expr.c_str(), expr.size()) && tok->linenr() == exprline) {
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string asExprIdString(const Token* tok)
|
||||||
|
{
|
||||||
|
return tok->expressionString() + "@" + std::to_string(tok->exprId());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string testExprIdEqual(const char code[],
|
||||||
|
const std::string& expr1,
|
||||||
|
unsigned int exprline1,
|
||||||
|
const std::string& expr2,
|
||||||
|
unsigned int exprline2,
|
||||||
|
SourceLocation loc = SourceLocation::current())
|
||||||
|
{
|
||||||
|
Tokenizer tokenizer(&settings1, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), loc.file_name(), loc.line());
|
||||||
|
|
||||||
|
const Token* tok1 = findToken(tokenizer, expr1, exprline1);
|
||||||
|
const Token* tok2 = findToken(tokenizer, expr2, exprline2);
|
||||||
|
|
||||||
|
if (!tok1)
|
||||||
|
return "'" + expr1 + "'" + " not found";
|
||||||
|
if (!tok2)
|
||||||
|
return "'" + expr2 + "'" + " not found";
|
||||||
|
if (tok1->exprId() == 0)
|
||||||
|
return asExprIdString(tok1) + " has not exprId";
|
||||||
|
if (tok2->exprId() == 0)
|
||||||
|
return asExprIdString(tok2) + " has not exprId";
|
||||||
|
|
||||||
|
if (tok1->exprId() != tok2->exprId())
|
||||||
|
return asExprIdString(tok1) + " != " + asExprIdString(tok2);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
bool testExprIdNotEqual(const char code[],
|
||||||
|
const std::string& expr1,
|
||||||
|
unsigned int exprline1,
|
||||||
|
const std::string& expr2,
|
||||||
|
unsigned int exprline2,
|
||||||
|
SourceLocation loc = SourceLocation::current())
|
||||||
|
{
|
||||||
|
std::string result = testExprIdEqual(code, expr1, exprline1, expr2, exprline2, loc);
|
||||||
|
return !result.empty();
|
||||||
|
}
|
||||||
|
|
||||||
static const Scope *findFunctionScopeByToken(const SymbolDatabase * db, const Token *tok) {
|
static const Scope *findFunctionScopeByToken(const SymbolDatabase * db, const Token *tok) {
|
||||||
std::list<Scope>::const_iterator scope;
|
std::list<Scope>::const_iterator scope;
|
||||||
|
|
||||||
|
@ -530,6 +585,7 @@ private:
|
||||||
TEST_CASE(unionWithConstructor);
|
TEST_CASE(unionWithConstructor);
|
||||||
|
|
||||||
TEST_CASE(incomplete_type); // #9255 (infinite recursion)
|
TEST_CASE(incomplete_type); // #9255 (infinite recursion)
|
||||||
|
TEST_CASE(exprIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void array() {
|
void array() {
|
||||||
|
@ -10000,6 +10056,214 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exprIds()
|
||||||
|
{
|
||||||
|
const char* code;
|
||||||
|
|
||||||
|
code = "int f(int a) {\n"
|
||||||
|
" return a +\n"
|
||||||
|
" a;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "a", 2U, "a", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a, int b) {\n"
|
||||||
|
" return a +\n"
|
||||||
|
" b;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "a", 2U, "b", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a) {\n"
|
||||||
|
" int x = a++;\n"
|
||||||
|
" int y = a++;\n"
|
||||||
|
" return x + a;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "++", 2U, "++", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a) {\n"
|
||||||
|
" int x = a;\n"
|
||||||
|
" return x + a;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "x", 3U, "a", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a) {\n"
|
||||||
|
" int& x = a;\n"
|
||||||
|
" return x + a;\n"
|
||||||
|
"}\n";
|
||||||
|
TODO_ASSERT_EQUALS("", "x@2 != a@1", testExprIdEqual(code, "x", 3U, "a", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a) {\n"
|
||||||
|
" int& x = a;\n"
|
||||||
|
" return (x + 1) +\n"
|
||||||
|
" (a + 1);\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+", 3U, "+", 4U));
|
||||||
|
|
||||||
|
code = "int& g(int& x) { return x; }\n"
|
||||||
|
"int f(int a) {\n"
|
||||||
|
" return (g(a) + 1) +\n"
|
||||||
|
" (a + 1);\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+", 3U, "+", 4U));
|
||||||
|
|
||||||
|
code = "int f(int a, int b) {\n"
|
||||||
|
" int x = (b-a)-a;\n"
|
||||||
|
" int y = (b-a)-a;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a ;", 2U, "- a ;", 3U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a )", 2U, "- a )", 3U));
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "- a )", 2U, "- a ;", 3U));
|
||||||
|
|
||||||
|
code = "int f(int a, int b) {\n"
|
||||||
|
" int x = a-(b-a);\n"
|
||||||
|
" int y = a-(b-a);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- ( b", 2U, "- ( b", 3U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a )", 2U, "- a )", 3U));
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "- a )", 2U, "- ( b", 3U));
|
||||||
|
|
||||||
|
code = "void f(int a, int b) {\n"
|
||||||
|
" int x = (b+a)+a;\n"
|
||||||
|
" int y = a+(b+a);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+ a ;", 2U, "+ ( b", 3U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+ a ) +", 2U, "+ a ) ;", 3U));
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "+ a ;", 2U, "+ a )", 3U));
|
||||||
|
|
||||||
|
code = "void f(int a, int b) {\n"
|
||||||
|
" int x = (b+a)+a;\n"
|
||||||
|
" int y = a+(a+b);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+ a ;", 2U, "+ ( a", 3U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "+ a ) +", 2U, "+ b ) ;", 3U));
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "+ a ;", 2U, "+ b", 3U));
|
||||||
|
|
||||||
|
code = "struct A { int x; };\n"
|
||||||
|
"void f(A a, int b) {\n"
|
||||||
|
" int x = (b-a.x)-a.x;\n"
|
||||||
|
" int y = (b-a.x)-a.x;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a . x ;", 3U, "- a . x ;", 4U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a . x )", 3U, "- a . x )", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int x; };\n"
|
||||||
|
"void f(A a, int b) {\n"
|
||||||
|
" int x = a.x-(b-a.x);\n"
|
||||||
|
" int y = a.x-(b-a.x);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- ( b", 3U, "- ( b", 4U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "- a . x )", 3U, "- a . x )", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int x; };\n"
|
||||||
|
"void f(A a) {\n"
|
||||||
|
" int x = a.x;\n"
|
||||||
|
" int y = a.x;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". x", 3U, ". x", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int x; };\n"
|
||||||
|
"void f(A a, A b) {\n"
|
||||||
|
" int x = a.x;\n"
|
||||||
|
" int y = b.x;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, ". x", 3U, ". x", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int y; };\n"
|
||||||
|
"struct B { A x; }\n"
|
||||||
|
"void f(B a) {\n"
|
||||||
|
" int x = a.x.y;\n"
|
||||||
|
" int y = a.x.y;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". x . y", 4U, ". x . y", 5U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". y", 4U, ". y", 5U));
|
||||||
|
|
||||||
|
code = "struct A { int y; };\n"
|
||||||
|
"struct B { A x; }\n"
|
||||||
|
"void f(B a, B b) {\n"
|
||||||
|
" int x = a.x.y;\n"
|
||||||
|
" int y = b.x.y;\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, ". x . y", 4U, ". x . y", 5U));
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, ". y", 4U, ". y", 5U));
|
||||||
|
|
||||||
|
code = "struct A { int g(); };\n"
|
||||||
|
"struct B { A x; }\n"
|
||||||
|
"void f(B a) {\n"
|
||||||
|
" int x = a.x.g();\n"
|
||||||
|
" int y = a.x.g();\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". x . g ( )", 4U, ". x . g ( )", 5U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". g ( )", 4U, ". g ( )", 5U));
|
||||||
|
|
||||||
|
code = "struct A { int g(int, int); };\n"
|
||||||
|
"struct B { A x; }\n"
|
||||||
|
"void f(B a, int b, int c) {\n"
|
||||||
|
" int x = a.x.g(b, c);\n"
|
||||||
|
" int y = a.x.g(b, c);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". x . g ( b , c )", 4U, ". x . g ( b , c )", 5U));
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, ". g ( b , c )", 4U, ". g ( b , c )", 5U));
|
||||||
|
|
||||||
|
code = "int g();\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int x = g();\n"
|
||||||
|
" int y = g();\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "(", 3U, "(", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int g(); };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int x = A::g();\n"
|
||||||
|
" int y = A::g();\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "(", 3U, "(", 4U));
|
||||||
|
|
||||||
|
code = "int g();\n"
|
||||||
|
"void f(int a, int b) {\n"
|
||||||
|
" int x = g(a, b);\n"
|
||||||
|
" int y = g(a, b);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "(", 3U, "(", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int g(); };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int x = A::g(a, b);\n"
|
||||||
|
" int y = A::g(a, b);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS("", testExprIdEqual(code, "(", 3U, "(", 4U));
|
||||||
|
|
||||||
|
code = "int g();\n"
|
||||||
|
"void f(int a, int b) {\n"
|
||||||
|
" int x = g(a, b);\n"
|
||||||
|
" int y = g(b, a);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "(", 3U, "(", 4U));
|
||||||
|
|
||||||
|
code = "struct A { int g(); };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int x = A::g(a, b);\n"
|
||||||
|
" int y = A::g(b, a);\n"
|
||||||
|
" return x + y;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testExprIdNotEqual(code, "(", 3U, "(", 4U));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestSymbolDatabase)
|
REGISTER_TEST(TestSymbolDatabase)
|
||||||
|
|
Loading…
Reference in New Issue