MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / validateAst

Method validateAst

lib/tokenlist.cpp:1935–2047  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1933}
1934
1935void TokenList::validateAst(bool print) const
1936{
1937 OnException oe{[&] {
1938 if (print)
1939 mTokensFrontBack->front->printOut(std::cout);
1940 }};
1941 // Check for some known issues in AST to avoid crash/hang later on
1942 std::set<const Token*> safeAstTokens; // list of "safe" AST tokens without endless recursion
1943 for (const Token *tok = mTokensFrontBack->front; tok; tok = tok->next()) {
1944 // Syntax error if binary operator only has 1 operand
1945 if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2())
1946 throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::AST);
1947
1948 // Syntax error if we encounter "?" with operand2 that is not ":"
1949 if (tok->str() == "?") {
1950 if (!tok->astOperand1() || !tok->astOperand2())
1951 throw InternalError(tok, "AST broken, ternary operator missing operand(s)", InternalError::AST);
1952 if (tok->astOperand2()->str() != ":")
1953 throw InternalError(tok, "Syntax Error: AST broken, ternary operator lacks ':'.", InternalError::AST);
1954 }
1955
1956 // Check for endless recursion
1957 const Token* parent = tok->astParent();
1958 if (parent) {
1959 std::set<const Token*> astTokens; // list of ancestors
1960 astTokens.insert(tok);
1961 do {
1962 if (safeAstTokens.find(parent) != safeAstTokens.end())
1963 break;
1964 if (astTokens.find(parent) != astTokens.end())
1965 throw InternalError(tok, "AST broken: endless recursion from '" + tok->str() + "'", InternalError::AST);
1966 astTokens.insert(parent);
1967 } while ((parent = parent->astParent()) != nullptr);
1968 safeAstTokens.insert(astTokens.cbegin(), astTokens.cend());
1969 } else if (tok->str() == ";") {
1970 safeAstTokens.clear();
1971 } else {
1972 safeAstTokens.insert(tok);
1973 }
1974
1975 // Don't check templates
1976 if (tok->str() == "<" && tok->link()) {
1977 tok = tok->link();
1978 continue;
1979 }
1980 if (tok->isCast()) {
1981 if (!tok->astOperand2() && precedes(tok->astOperand1(), tok))
1982 throw InternalError(tok, "AST broken: '" + tok->str() + "' has improper operand.", InternalError::AST);
1983 if (tok->astOperand1() && tok->link()) { // skip casts (not part of the AST)
1984 tok = tok->link();
1985 continue;
1986 }
1987 }
1988
1989 if (findLambdaEndToken(tok)) { // skip lambda captures
1990 tok = tok->link();
1991 continue;
1992 }

Callers 2

simplifyTokens1Method · 0.80
testAstMethod · 0.80

Calls 15

precedesFunction · 0.85
findLambdaEndTokenFunction · 0.85
nextMethod · 0.80
isAssignmentOpMethod · 0.80
astOperand1Method · 0.80
astOperand2Method · 0.80
astParentMethod · 0.80
isCastMethod · 0.80
simpleMatchFunction · 0.70
printOutMethod · 0.45
strMethod · 0.45
findMethod · 0.45

Tested by 1

testAstMethod · 0.64