Skip to content

Commit bbdfd8b

Browse files
committed
Make it possible to create AST, by using the --ast flag
1 parent 46b4a19 commit bbdfd8b

8 files changed

Lines changed: 59 additions & 11 deletions

File tree

cli/cmdlineparser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
125125
else if (std::strcmp(argv[i], "--debug-fp") == 0)
126126
_settings->debugFalsePositive = true;
127127

128+
// Experimental AST handling
129+
else if (std::strcmp(argv[i], "--ast") == 0)
130+
_settings->ast = true;
131+
128132
// Inconclusive checking (still in testing phase)
129133
else if (std::strcmp(argv[i], "--inconclusive") == 0)
130134
_settings->inconclusive = true;

lib/settings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
Settings::Settings()
2727
: _terminate(false),
2828
debug(false), debugwarnings(false), debugFalsePositive(false),
29-
inconclusive(false), experimental(false),
29+
ast(false), inconclusive(false), experimental(false),
3030
_errorsOnly(false),
3131
_inlineSuppressions(false),
3232
_verbose(false),

lib/settings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class CPPCHECKLIB Settings {
6262
/** @brief Is --debug-fp given? */
6363
bool debugFalsePositive;
6464

65+
/** @brief Experimental AST handling */
66+
bool ast;
67+
6568
/** @brief Inconclusive checks */
6669
bool inconclusive;
6770

lib/token.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,13 +1166,30 @@ void Token::astHandleParentheses()
11661166
innerTop = innerTop->_astParent;
11671167

11681168
if (_astParent) {
1169-
if (_str == "(" && _astParent->_astOperand2 != NULL)
1169+
if (_astParent->_astOperand2 == this)
11701170
_astParent->_astOperand2 = innerTop;
1171-
else
1171+
else if (_astParent->_astOperand1 == this)
11721172
_astParent->_astOperand1 = innerTop;
11731173
innerTop->_astParent = _astParent;
1174-
} else {
1175-
_astParent = innerTop;
1174+
_astParent = NULL;
11761175
}
11771176
}
11781177

1178+
1179+
void Token::printAst() const
1180+
{
1181+
bool title = false;
1182+
1183+
bool print = true;
1184+
for (const Token *tok = this; tok; tok = tok->next()) {
1185+
if (print && tok->_astOperand1) {
1186+
if (!title)
1187+
std::cout << "\n\n##AST" << std::endl;
1188+
title = true;
1189+
std::cout << tok->astTop()->astString(" ") << std::endl;
1190+
print = false;
1191+
}
1192+
if (Token::Match(tok, "[;{}]"))
1193+
print = true;
1194+
}
1195+
}

lib/token.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,14 +671,16 @@ class CPPCHECKLIB Token {
671671
return ret;
672672
}
673673

674-
std::string astString() const {
674+
std::string astString(const char *sep = "") const {
675675
std::string ret;
676676
if (_astOperand1)
677-
ret = _astOperand1->astString();
677+
ret = _astOperand1->astString(sep);
678678
if (_astOperand2)
679-
ret += _astOperand2->astString();
680-
return ret+_str;
679+
ret += _astOperand2->astString(sep);
680+
return ret + sep + _str;
681681
}
682+
683+
void printAst() const;
682684
};
683685

684686
/// @}

lib/tokenize.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,12 @@ bool Tokenizer::simplifyTokenList()
36453645
tok->deleteNext();
36463646
}
36473647

3648+
// Experimental AST handling. Only for C code now since
3649+
// uninstantiated C++ templates are not handled well. Fix
3650+
// TestTokenize::asttemplate
3651+
if (_settings->ast && isC())
3652+
list.createAst();
3653+
36483654
if (_settings->terminated())
36493655
return false;
36503656

@@ -3653,6 +3659,9 @@ bool Tokenizer::simplifyTokenList()
36533659

36543660
if (_settings->_verbose)
36553661
_symbolDatabase->printOut("Symbol database");
3662+
3663+
if (_settings->ast)
3664+
list.front()->printAst();
36563665
}
36573666

36583667
if (_settings->debugwarnings) {

lib/tokenlist.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ void TokenList::createAst() const
392392
while (tok->next())
393393
tok = tok->next();
394394
for (; tok; tok = tok->previous()) {
395-
if ((!tok->previous() || tok->previous()->isOp()) &&
395+
if (tok->isOp() && (!tok->previous() || tok->previous()->isOp() || tok->previous()->type() == Token::eOther) &&
396396
op.find(" "+tok->str()+" ")!=std::string::npos) {
397397
tok->astOperand1(tok->next());
398398
}
@@ -401,6 +401,13 @@ void TokenList::createAst() const
401401
const std::string op(operators[i]);
402402
for (Token *tok = _front; tok; tok = tok->next()) {
403403
if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) {
404+
// Don't create AST for "..."
405+
if (tok->str() == "." && (tok->previous()->str() == "." || tok->next()->str() == "."))
406+
continue;
407+
408+
if (Token::Match(tok, "* [)]]"))
409+
continue;
410+
404411
if (tok->type() != Token::eIncDecOp) {
405412
tok->astOperand1(tok->previous());
406413
tok->astOperand2(tok->next());

test/testtokenize.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9929,7 +9929,13 @@ class TestTokenizer : public TestFixture {
99299929
// Create AST..
99309930
tokenList.createAst();
99319931

9932-
return tokenList.front()->astTop()->astString();
9932+
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
9933+
if (tok->astOperand1())
9934+
return tok->astTop()->astString();
9935+
}
9936+
9937+
// No AST found
9938+
return "";
99339939
}
99349940

99359941
void astexpr() const { // simple expressions with arithmetical ops

0 commit comments

Comments
 (0)