Remove Tokenizer::simplifyNull()
This commit is contained in:
parent
9cea2d6dfa
commit
efa3aba32a
|
@ -83,6 +83,15 @@ std::string astCanonicalType(const Token *expr)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool match(const Token *tok, const std::string &rhs)
|
||||||
|
{
|
||||||
|
if (tok->str() == rhs)
|
||||||
|
return true;
|
||||||
|
if (tok->isName() && !tok->varId() && tok->values.size() == 1U && tok->values.front().isKnown() && MathLib::toString(tok->values.front().intvalue) == rhs)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
|
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
@ -90,7 +99,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
|
||||||
|
|
||||||
const Token *ret = nullptr;
|
const Token *ret = nullptr;
|
||||||
if (tok->isComparisonOp()) {
|
if (tok->isComparisonOp()) {
|
||||||
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
if (tok->astOperand1() && match(tok->astOperand1(), rhs)) {
|
||||||
// Invert comparator
|
// Invert comparator
|
||||||
std::string s = tok->str();
|
std::string s = tok->str();
|
||||||
if (s[0] == '>')
|
if (s[0] == '>')
|
||||||
|
@ -100,7 +109,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
|
||||||
if (s == comp) {
|
if (s == comp) {
|
||||||
ret = tok->astOperand2();
|
ret = tok->astOperand2();
|
||||||
}
|
}
|
||||||
} else if (tok->str() == comp && tok->astOperand2() && tok->astOperand2()->str() == rhs) {
|
} else if (tok->str() == comp && tok->astOperand2() && match(tok->astOperand2(), rhs)) {
|
||||||
ret = tok->astOperand1();
|
ret = tok->astOperand1();
|
||||||
}
|
}
|
||||||
} else if (comp == "!=" && rhs == std::string("0")) {
|
} else if (comp == "!=" && rhs == std::string("0")) {
|
||||||
|
|
|
@ -983,6 +983,13 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
variables.write(varid1, tok);
|
variables.write(varid1, tok);
|
||||||
} else if (varid1 && Token::Match(tok, "%varid% .", varid1)) {
|
} else if (varid1 && Token::Match(tok, "%varid% .", varid1)) {
|
||||||
variables.use(varid1, tok);
|
variables.use(varid1, tok);
|
||||||
|
} else if (var &&
|
||||||
|
var->_type == Variables::pointer &&
|
||||||
|
Token::Match(tok, "%name% ;") &&
|
||||||
|
tok->varId() == 0 &&
|
||||||
|
tok->hasKnownIntValue() &&
|
||||||
|
tok->values.front().intvalue == 0) {
|
||||||
|
variables.use(varid1, tok);
|
||||||
} else {
|
} else {
|
||||||
variables.write(varid1, tok);
|
variables.write(varid1, tok);
|
||||||
}
|
}
|
||||||
|
|
|
@ -748,6 +748,10 @@ public:
|
||||||
/** Values of token */
|
/** Values of token */
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
|
|
||||||
|
bool hasKnownIntValue() const {
|
||||||
|
return values.size() == 1U && values.front().isKnown() && values.front().tokvalue == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const ValueFlow::Value * getValue(const MathLib::bigint val) const {
|
const ValueFlow::Value * getValue(const MathLib::bigint val) const {
|
||||||
std::list<ValueFlow::Value>::const_iterator it;
|
std::list<ValueFlow::Value>::const_iterator it;
|
||||||
for (it = values.begin(); it != values.end(); ++it) {
|
for (it = values.begin(); it != values.end(); ++it) {
|
||||||
|
|
|
@ -1889,26 +1889,6 @@ void Tokenizer::combineStringAndCharLiterals()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::simplifyNull()
|
|
||||||
{
|
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
|
||||||
if (tok->str() == "NULL" && (!Token::Match(tok->previous(), "[(,] NULL [,)]") || tok->strAt(-2) == "="))
|
|
||||||
tok->str("0");
|
|
||||||
else if (tok->str() == "__null") {
|
|
||||||
tok->originalName(tok->str());
|
|
||||||
tok->str("0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nullptr..
|
|
||||||
if (isCPP() && _settings->standards.cpp == Standards::CPP11) {
|
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
|
||||||
if (tok->str() == "nullptr")
|
|
||||||
tok->str("0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tokenizer::concatenateNegativeNumberAndAnyPositive()
|
void Tokenizer::concatenateNegativeNumberAndAnyPositive()
|
||||||
{
|
{
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
@ -3362,9 +3342,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
// Simplify the C alternative tokens (and, or, etc.)
|
// Simplify the C alternative tokens (and, or, etc.)
|
||||||
simplifyCAlternativeTokens();
|
simplifyCAlternativeTokens();
|
||||||
|
|
||||||
// replace 'NULL' and similar '0'-defined macros with '0'
|
|
||||||
simplifyNull();
|
|
||||||
|
|
||||||
// replace 'sin(0)' to '0' and other similar math expressions
|
// replace 'sin(0)' to '0' and other similar math expressions
|
||||||
simplifyMathExpressions();
|
simplifyMathExpressions();
|
||||||
|
|
||||||
|
|
|
@ -468,8 +468,6 @@ public:
|
||||||
|
|
||||||
void combineStringAndCharLiterals();
|
void combineStringAndCharLiterals();
|
||||||
|
|
||||||
void simplifyNull();
|
|
||||||
|
|
||||||
void concatenateNegativeNumberAndAnyPositive();
|
void concatenateNegativeNumberAndAnyPositive();
|
||||||
|
|
||||||
void simplifyExternC();
|
void simplifyExternC();
|
||||||
|
|
|
@ -604,7 +604,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
|
||||||
|
|
||||||
|
|
||||||
// Handle various constants..
|
// Handle various constants..
|
||||||
static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings)
|
static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings, bool cpp)
|
||||||
{
|
{
|
||||||
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
|
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
|
||||||
ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
|
ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
|
||||||
|
@ -614,6 +614,10 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
|
||||||
ValueFlow::Value value(tok->enumerator()->value);
|
ValueFlow::Value value(tok->enumerator()->value);
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
setTokenValue(const_cast<Token *>(tok), value);
|
setTokenValue(const_cast<Token *>(tok), value);
|
||||||
|
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
|
||||||
|
ValueFlow::Value value(0);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok), value);
|
||||||
} else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) {
|
} else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) {
|
||||||
const Token *tok2 = tok->tokAt(2);
|
const Token *tok2 = tok->tokAt(2);
|
||||||
if (tok2->enumerator() && tok2->enumerator()->scope) {
|
if (tok2->enumerator() && tok2->enumerator()->scope) {
|
||||||
|
@ -655,7 +659,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
|
||||||
static void valueFlowNumber(TokenList *tokenlist)
|
static void valueFlowNumber(TokenList *tokenlist)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok;) {
|
for (Token *tok = tokenlist->front(); tok;) {
|
||||||
tok = valueFlowSetConstantValue(tok, tokenlist->getSettings());
|
tok = valueFlowSetConstantValue(tok, tokenlist->getSettings(), tokenlist->isCPP());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenlist->isCPP()) {
|
if (tokenlist->isCPP()) {
|
||||||
|
@ -983,12 +987,12 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symbo
|
||||||
MathLib::bigint num = 0;
|
MathLib::bigint num = 0;
|
||||||
const Token *vartok = nullptr;
|
const Token *vartok = nullptr;
|
||||||
if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
|
if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
|
||||||
if (tok->astOperand1()->isName() && tok->astOperand2()->isNumber()) {
|
if (tok->astOperand1()->isName() && tok->astOperand2()->hasKnownIntValue()) {
|
||||||
vartok = tok->astOperand1();
|
vartok = tok->astOperand1();
|
||||||
num = MathLib::toLongNumber(tok->astOperand2()->str());
|
num = tok->astOperand2()->values.front().intvalue;
|
||||||
} else if (tok->astOperand1()->isNumber() && tok->astOperand2()->isName()) {
|
} else if (tok->astOperand1()->hasKnownIntValue() && tok->astOperand2()->isName()) {
|
||||||
vartok = tok->astOperand2();
|
vartok = tok->astOperand2();
|
||||||
num = MathLib::toLongNumber(tok->astOperand1()->str());
|
num = tok->astOperand1()->values.front().intvalue;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1708,7 +1712,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
if (Token::Match(tok, "==|!=|>=|<=")) {
|
if (Token::Match(tok, "==|!=|>=|<=")) {
|
||||||
if (!tok->astOperand1() || !tok->astOperand2())
|
if (!tok->astOperand1() || !tok->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
if (tok->astOperand1()->isNumber()) {
|
if (tok->astOperand1()->hasKnownIntValue()) {
|
||||||
numtok = tok->astOperand1();
|
numtok = tok->astOperand1();
|
||||||
vartok = tok->astOperand2();
|
vartok = tok->astOperand2();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1717,7 +1721,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
}
|
}
|
||||||
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
|
||||||
vartok = vartok->astOperand1();
|
vartok = vartok->astOperand1();
|
||||||
if (!vartok->isName() || !numtok->isNumber() || !MathLib::isInt(numtok->str()))
|
if (!vartok->isName() || !numtok->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
} else if (tok->str() == "!") {
|
} else if (tok->str() == "!") {
|
||||||
vartok = tok->astOperand1();
|
vartok = tok->astOperand1();
|
||||||
|
@ -1742,7 +1746,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
|
||||||
if (!var || !(var->isLocal() || var->isArgument()))
|
if (!var || !(var->isLocal() || var->isArgument()))
|
||||||
continue;
|
continue;
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL));
|
values.push_back(ValueFlow::Value(tok, numtok ? numtok->values.front().intvalue : 0LL));
|
||||||
|
|
||||||
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
if (Token::Match(tok->astParent(), "%oror%|&&")) {
|
||||||
Token *parent = const_cast<Token*>(tok->astParent());
|
Token *parent = const_cast<Token*>(tok->astParent());
|
||||||
|
@ -2549,7 +2553,7 @@ const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(const Token *expr, c
|
||||||
if (expr && expr->values.empty()) {
|
if (expr && expr->values.empty()) {
|
||||||
valueFlowConstantFoldAST(expr->astOperand1(), settings);
|
valueFlowConstantFoldAST(expr->astOperand1(), settings);
|
||||||
valueFlowConstantFoldAST(expr->astOperand2(), settings);
|
valueFlowConstantFoldAST(expr->astOperand2(), settings);
|
||||||
valueFlowSetConstantValue(expr, settings);
|
valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
|
||||||
}
|
}
|
||||||
return expr && expr->values.size() == 1U && expr->values.front().isKnown() ? &expr->values.front() : nullptr;
|
return expr && expr->values.size() == 1U && expr->values.front().isKnown() ? &expr->values.front() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1669,7 +1669,7 @@ private:
|
||||||
" return;\n"
|
" return;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==NULL' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||||
|
|
||||||
// check, and use
|
// check, and use
|
||||||
check("void f(struct X *p, int x) {\n"
|
check("void f(struct X *p, int x) {\n"
|
||||||
|
@ -1689,7 +1689,7 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(code, true); // inconclusive
|
check(code, true); // inconclusive
|
||||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==0' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
check("void f(char *s) {\n" // #3358
|
check("void f(char *s) {\n" // #3358
|
||||||
|
|
|
@ -1592,7 +1592,7 @@ private:
|
||||||
"{ "
|
"{ "
|
||||||
"FILE * f ; "
|
"FILE * f ; "
|
||||||
"f = fopen ( \"foo\" , \"r\" ) ; "
|
"f = fopen ( \"foo\" , \"r\" ) ; "
|
||||||
"if ( f == 0 ) "
|
"if ( f == NULL ) "
|
||||||
"{ "
|
"{ "
|
||||||
"return -1 ; "
|
"return -1 ; "
|
||||||
"} "
|
"} "
|
||||||
|
@ -1669,7 +1669,7 @@ private:
|
||||||
ASSERT_EQUALS("char * s ; do { s = new char [ 10 ] ; } while ( ! s ) ;",
|
ASSERT_EQUALS("char * s ; do { s = new char [ 10 ] ; } while ( ! s ) ;",
|
||||||
tok("char *s; do { } while (0 == (s=new char[10]));"));
|
tok("char *s; do { } while (0 == (s=new char[10]));"));
|
||||||
// #4911
|
// #4911
|
||||||
ASSERT_EQUALS("; do { current = f ( ) ; } while ( ( current ) != 0 ) ;", simplifyIfAndWhileAssign(";do { } while((current=f()) != NULL);"));
|
ASSERT_EQUALS("; do { current = f ( ) ; } while ( ( current ) != NULL ) ;", simplifyIfAndWhileAssign(";do { } while((current=f()) != NULL);"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void not1() {
|
void not1() {
|
||||||
|
|
|
@ -1707,7 +1707,7 @@ private:
|
||||||
{
|
{
|
||||||
const char code[] = "typedef int RexxFunctionHandler();\n"
|
const char code[] = "typedef int RexxFunctionHandler();\n"
|
||||||
"RexxFunctionHandler *(efuncs[]) = { NULL, NULL };";
|
"RexxFunctionHandler *(efuncs[]) = { NULL, NULL };";
|
||||||
const char expected[] = "int ( * ( efuncs [ ] ) ) ( ) = { 0 , 0 } ;";
|
const char expected[] = "int ( * ( efuncs [ ] ) ) ( ) = { NULL , NULL } ;";
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,6 @@ private:
|
||||||
TEST_CASE(simplify_constants4);
|
TEST_CASE(simplify_constants4);
|
||||||
TEST_CASE(simplify_constants5);
|
TEST_CASE(simplify_constants5);
|
||||||
TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter
|
TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter
|
||||||
TEST_CASE(simplifyNull);
|
|
||||||
TEST_CASE(simplifyMulAndParens); // Ticket #2784 + #3184
|
TEST_CASE(simplifyMulAndParens); // Ticket #2784 + #3184
|
||||||
|
|
||||||
TEST_CASE(simplifyStructDecl);
|
TEST_CASE(simplifyStructDecl);
|
||||||
|
@ -2675,7 +2674,7 @@ private:
|
||||||
" nr = (last = list->prev)->nr;\n" // <- don't replace "last" with 0
|
" nr = (last = list->prev)->nr;\n" // <- don't replace "last" with 0
|
||||||
"}\n";
|
"}\n";
|
||||||
const char expected[] = "void f ( struct ABC * list ) {\n"
|
const char expected[] = "void f ( struct ABC * list ) {\n"
|
||||||
"struct ABC * last ; last = 0 ;\n"
|
"struct ABC * last ; last = NULL ;\n"
|
||||||
"nr = ( last = list . prev ) . nr ;\n"
|
"nr = ( last = list . prev ) . nr ;\n"
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
|
||||||
|
@ -3394,24 +3393,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyNull() {
|
|
||||||
{
|
|
||||||
const char code[] =
|
|
||||||
"int * p = NULL;\n"
|
|
||||||
"int * q = __null;\n";
|
|
||||||
const char expected[] =
|
|
||||||
"int * p ; p = 0 ;\nint * q ; q = 0 ;";
|
|
||||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code,true));
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_EQUALS("( a == nullptr )", tokenizeAndStringify("(a==nullptr)", false, false, Settings::Native, "test.c"));
|
|
||||||
ASSERT_EQUALS("( a == 0 )", tokenizeAndStringify("(a==nullptr)", false, false, Settings::Native, "test.cpp"));
|
|
||||||
|
|
||||||
ASSERT_EQUALS("if ( p == 0 )", tokenizeAndStringify("if (p==NULL)"));
|
|
||||||
ASSERT_EQUALS("f ( NULL ) ;", tokenizeAndStringify("f(NULL);"));
|
|
||||||
ASSERT_EQUALS("char * i ; i = 0 ;", tokenizeAndStringify("char* i = (NULL);"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void simplifyMulAndParens() {
|
void simplifyMulAndParens() {
|
||||||
// (error) Resource leak
|
// (error) Resource leak
|
||||||
const char code[] = "void f() {"
|
const char code[] = "void f() {"
|
||||||
|
@ -3482,19 +3463,19 @@ private:
|
||||||
// ticket #346
|
// ticket #346
|
||||||
|
|
||||||
const char code1[] = "void *p = NULL;";
|
const char code1[] = "void *p = NULL;";
|
||||||
const char res1[] = "void * p ; p = 0 ;";
|
const char res1[] = "void * p ; p = NULL ;";
|
||||||
ASSERT_EQUALS(res1, tokenizeAndStringify(code1));
|
ASSERT_EQUALS(res1, tokenizeAndStringify(code1));
|
||||||
|
|
||||||
const char code2[] = "const void *p = NULL;";
|
const char code2[] = "const void *p = NULL;";
|
||||||
const char res2[] = "const void * p ; p = 0 ;";
|
const char res2[] = "const void * p ; p = NULL ;";
|
||||||
ASSERT_EQUALS(res2, tokenizeAndStringify(code2));
|
ASSERT_EQUALS(res2, tokenizeAndStringify(code2));
|
||||||
|
|
||||||
const char code3[] = "void * const p = NULL;";
|
const char code3[] = "void * const p = NULL;";
|
||||||
const char res3[] = "void * const p ; p = 0 ;";
|
const char res3[] = "void * const p ; p = NULL ;";
|
||||||
ASSERT_EQUALS(res3, tokenizeAndStringify(code3));
|
ASSERT_EQUALS(res3, tokenizeAndStringify(code3));
|
||||||
|
|
||||||
const char code4[] = "const void * const p = NULL;";
|
const char code4[] = "const void * const p = NULL;";
|
||||||
const char res4[] = "const void * const p ; p = 0 ;";
|
const char res4[] = "const void * const p ; p = NULL ;";
|
||||||
ASSERT_EQUALS(res4, tokenizeAndStringify(code4));
|
ASSERT_EQUALS(res4, tokenizeAndStringify(code4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3562,7 +3543,7 @@ private:
|
||||||
|
|
||||||
// ticket #3927
|
// ticket #3927
|
||||||
const char code3[] = "union xy *p = NULL;";
|
const char code3[] = "union xy *p = NULL;";
|
||||||
ASSERT_EQUALS("union xy * p ; p = 0 ;", tokenizeAndStringify(code3));
|
ASSERT_EQUALS("union xy * p ; p = NULL ;", tokenizeAndStringify(code3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vardecl_par() {
|
void vardecl_par() {
|
||||||
|
|
Loading…
Reference in New Issue