diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index c6e2c1b88..a8c5998f5 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8486,6 +8486,8 @@ void Tokenizer::findGarbageCode() const if (Token::Match(tok, "> %cop%")) continue; } + if (Token::Match(tok, "%assign% typename|class %assign%")) + syntaxError(tok); if (Token::Match(tok, "%cop%|=|,|[ %or%|%oror%|/|%")) syntaxError(tok); if (Token::Match(tok, ";|(|[ %comp%")) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 884c96181..e244f278d 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -1217,14 +1217,23 @@ void TokenList::validateAst() const // Skip pure virtual functions if (Token::simpleMatch(tok->previous(), ") = 0")) continue; + // Skip operator definitions + if (Token::simpleMatch(tok->previous(), "operator")) + continue; // Skip incomplete code if (!tok->astOperand1() && !tok->astOperand2() && !tok->astParent()) continue; - // FIXME - if (Token::Match(tok->previous(), "%name%") && Token::Match(tok->next(), "%name%")) - continue; // Skip lambda assignment and/or initializer - if (Token::Match(tok, "= {|^")) + if (Token::Match(tok, "= {|^|[")) + continue; + // FIXME: Workaround broken AST assignment in type aliases + if (Token::Match(tok->previous(), "%name% = %name%")) + continue; + // FIXME: Workaround when assigning from a new expression: #8749 + if (Token::simpleMatch(tok, "= new")) + continue; + // FIXME: Workaround assigning when using c style cast: #8786 + if (Token::Match(tok, "= ( %name%")) continue; if (!tok->astOperand1() || !tok->astOperand2()) throw InternalError(tok, "Syntax Error: AST broken, binary operator '" + tok->str() + "' doesn't have two operands.", InternalError::AST); diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 3b8da0507..3088df0c1 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -578,7 +578,7 @@ private: void garbageCode35() { // ticket #2604 segmentation fault - checkCode("sizeof <= A"); + ASSERT_THROW(checkCode("sizeof <= A"), InternalError); } void garbageCode36() { // #6334 @@ -1028,8 +1028,8 @@ private: // Ticket #5605, #5759, #5762, #5774, #5823, #6059 ASSERT_THROW(checkCode("foo() template struct tuple Args> tuple { } main() { foo(); }"), InternalError); ASSERT_THROW(checkCode("( ) template < T1 = typename = unused> struct Args { } main ( ) { foo < int > ( ) ; }"), InternalError); - checkCode("() template < T = typename = x > struct a {} { f () }"); - checkCode("template < T = typename = > struct a { f }"); + ASSERT_THROW(checkCode("() template < T = typename = x > struct a {} { f () }"), InternalError); + ASSERT_THROW(checkCode("template < T = typename = > struct a { f }"), InternalError); checkCode("struct S { int i, j; }; " "template struct X {}; " "X<&S::i, int> x = X<&S::i, int>(); " @@ -1438,11 +1438,10 @@ private: } void garbageCode184() { // #7699 - ASSERT_THROW(checkCode("unsigned int AquaSalSystem::GetDisplayScreenCount() {\n" + checkCode("unsigned int AquaSalSystem::GetDisplayScreenCount() {\n" " NSArray* pScreens = [NSScreen screens];\n" " return pScreens ? [pScreens count] : 1;\n" - "}"), - InternalError); + "}"); } void garbageCode185() { // #6011 crash in libreoffice failure to create proper AST @@ -1617,6 +1616,32 @@ private: "template< class Predicate > int\n" "List::DeleteIf( const Predicate &pred )\n" "{}\n"); + + // #8749 + checkCode( + "typedef char A[1];\n" + "void f(void) {\n" + " char (*p)[1] = new A[1];\n" + "}\n"); + + // #8786 + checkCode( + "void f() {\n" + " char * pBuf = (char*)(new int[32]);\n" + "}\n"); + + // #8749 + checkCode( + "struct A {\n" + " void operator+=(A&) && = delete;\n" + "};\n"); + + // #8788 + checkCode( + "struct foo;\n" + "void f() {\n" + " auto fn = []() -> foo* { return new foo(); };\n" + "}\n"); } };