From ac67049661bb37bab8431a168ce8ef992f3a4f10 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Mon, 7 Sep 2020 03:54:32 -0500 Subject: [PATCH] Fix issue 9858: Token::astOperand1() cyclic dependency on valid C++ code (#2784) --- lib/tokenlist.cpp | 45 ++++++++++++++++++++++++++++--------------- test/testtokenize.cpp | 13 +++++++++++++ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index efd17ed50..64330324e 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -1302,23 +1302,36 @@ static Token * createAstAtToken(Token *tok, bool cpp); static void createAstAtTokenInner(Token * const tok1, const Token *endToken, bool cpp) { for (Token *tok = tok1; tok && tok != endToken; tok = tok ? tok->next() : nullptr) { - if (tok->str() == "{" && !iscpp11init(tok) && !tok->astOperand1()) { + if (tok->str() == "{" && !iscpp11init(tok)) { + if (Token::simpleMatch(tok->astOperand1(), ",")) + continue; + if (Token::simpleMatch(tok->previous(), "( {")) + ; + // struct assignment + else if (Token::simpleMatch(tok->previous(), ") {") && Token::simpleMatch(tok->linkAt(-1), "( struct")) + continue; + // Lambda function + else if (Token::simpleMatch(tok->astParent(), "(") && + Token::simpleMatch(tok->astParent()->astParent(), "[") && + tok->astParent()->astParent()->astOperand1() && + tok == tok->astParent()->astParent()->astOperand1()->astOperand1()) + ; + else { + // function argument is initializer list? + const Token *parent = tok->astParent(); + while (Token::simpleMatch(parent, ",")) + parent = parent->astParent(); + if (!parent || !Token::Match(parent->previous(), "%name% (")) + // not function argument.. + continue; + } + + if (Token::simpleMatch(tok->previous(), "( { .")) + break; + const Token * const endToken2 = tok->link(); - bool hasAst = false; - for (const Token *inner = tok->next(); inner != endToken2; inner = inner->next()) { - if (inner->astOperand1()) { - hasAst = true; - break; - } - if (tok->isConstOp()) - break; - if (inner->str() == "{") - inner = inner->link(); - } - if (!hasAst) { - for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr) - tok = createAstAtToken(tok, cpp); - } + for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr) + tok = createAstAtToken(tok, cpp); } else if (cpp && tok->str() == "[") { if (isLambdaCaptureList(tok)) { tok = tok->astOperand1(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a723b2dde..185dd3479 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -8292,6 +8292,19 @@ private: " }\n" "};\n")); + // #9858 + ASSERT_NO_THROW(tokenizeAndStringify( + "struct a {\n" + " struct b {};\n" + "};\n" + "void c(a::b, a::b);\n" + "void g(a::b f) { c(f, {a::b{}}); }\n" + "template void h() {\n" + " int e;\n" + " for (int d = 0; d < e; d++)\n" + " ;\n" + "}\n")); + ASSERT_NO_THROW(tokenizeAndStringify("a()==3;")); }