From 2d80acbe763e1cd1f872e4d49ba653d09bca8c6e Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@trolltech.com> Date: Tue, 10 Feb 2009 14:43:19 +0100 Subject: [PATCH] Improved the implementation of new-expressions. --- src/shared/cplusplus/AST.cpp | 114 +++++++++++++-------- src/shared/cplusplus/AST.h | 46 +++++++-- src/shared/cplusplus/ASTVisitor.h | 6 +- src/shared/cplusplus/ASTfwd.h | 3 +- src/shared/cplusplus/CheckExpression.cpp | 5 +- src/shared/cplusplus/Parser.cpp | 123 ++++++++++++++++------- src/shared/cplusplus/Parser.h | 3 +- src/shared/cplusplus/PrettyPrinter.cpp | 59 +++++------ src/shared/cplusplus/PrettyPrinter.h | 3 +- tests/auto/cplusplus/ast/tst_ast.cpp | 55 ++++++++++ 10 files changed, 293 insertions(+), 124 deletions(-) diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index b75994f366d..8a9c201dc5d 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -2225,56 +2225,79 @@ unsigned NestedNameSpecifierAST::lastToken() const return class_or_namespace_name->lastToken(); } -NewDeclaratorAST *NewDeclaratorAST::clone(MemoryPool *pool) const +NewPlacementAST *NewPlacementAST::clone(MemoryPool *pool) const { - NewDeclaratorAST *ast = new (pool) NewDeclaratorAST; - if (ptr_operators) - ast->ptr_operators = ptr_operators->clone(pool); - if (declarator) - ast->declarator = declarator->clone(pool); + NewPlacementAST *ast = new (pool) NewPlacementAST; + ast->lparen_token = lparen_token; + if (expression_list) + ast->expression_list = expression_list->clone(pool); + ast->rparen_token = rparen_token; return ast; } -void NewDeclaratorAST::accept0(ASTVisitor *visitor) +void NewPlacementAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { - for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; - ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next)) { - accept(ptr_op, visitor); + for (ExpressionListAST *it = expression_list; it; it = it->next) { + accept(it->expression, visitor); } - - accept(declarator, visitor); } visitor->endVisit(this); } -unsigned NewDeclaratorAST::firstToken() const +unsigned NewPlacementAST::firstToken() const { - return ptr_operators->firstToken(); + return lparen_token; } -unsigned NewDeclaratorAST::lastToken() const +unsigned NewPlacementAST::lastToken() const { - if (declarator) - return declarator->lastToken(); + return rparen_token + 1; +} - for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { - if (! it->next) - return it->lastToken(); +NewArrayDeclaratorAST *NewArrayDeclaratorAST::clone(MemoryPool *pool) const +{ + NewArrayDeclaratorAST *ast = new (pool) NewArrayDeclaratorAST; + ast->lbracket_token = lbracket_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rbracket_token = rbracket_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void NewArrayDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(next, visitor); } + visitor->endVisit(this); +} - return 0; +unsigned NewArrayDeclaratorAST::firstToken() const +{ + return lbracket_token; +} + +unsigned NewArrayDeclaratorAST::lastToken() const +{ + return rbracket_token + 1; } NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const { NewExpressionAST *ast = new (pool) NewExpressionAST; + ast->scope_token = scope_token; ast->new_token = new_token; - if (expression) - ast->expression = expression->clone(pool); + if (new_placement) + ast->new_placement = new_placement->clone(pool); + ast->lparen_token = lparen_token; if (type_id) ast->type_id = type_id->clone(pool); + ast->rparen_token = rparen_token; if (new_type_id) ast->new_type_id = new_type_id->clone(pool); if (new_initializer) @@ -2285,7 +2308,7 @@ NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const void NewExpressionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { - accept(expression, visitor); + accept(new_placement, visitor); accept(type_id, visitor); accept(new_type_id, visitor); accept(new_initializer, visitor); @@ -2302,15 +2325,8 @@ unsigned NewExpressionAST::firstToken() const unsigned NewExpressionAST::lastToken() const { - if (new_initializer) - return new_initializer->lastToken(); - else if (new_type_id) - return new_type_id->lastToken(); - else if (type_id) - return type_id->lastToken(); - else if (expression) - return expression->lastToken(); - else if (new_token) + // ### FIXME + if (new_token) return new_token + 1; else if (scope_token) return scope_token + 1; @@ -2363,12 +2379,13 @@ TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const { NewTypeIdAST *ast = new (pool) NewTypeIdAST; + if (type_specifier) ast->type_specifier = type_specifier->clone(pool); - if (new_initializer) - ast->new_initializer = new_initializer->clone(pool); - if (new_declarator) - ast->new_declarator = new_declarator->clone(pool); + if (ptr_operators) + ast->ptr_operators = ptr_operators->clone(pool); + if (new_array_declarators) + ast->new_array_declarators = new_array_declarators->clone(pool); return ast; } @@ -2377,8 +2394,13 @@ void NewTypeIdAST::accept0(ASTVisitor *visitor) if (visitor->visit(this)) { for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) accept(spec, visitor); - accept(new_initializer, visitor); - accept(new_declarator, visitor); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) + accept(it, visitor); + + for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next) + accept(it, visitor); + } visitor->endVisit(this); } @@ -2390,15 +2412,19 @@ unsigned NewTypeIdAST::firstToken() const unsigned NewTypeIdAST::lastToken() const { - if (new_declarator) - return new_declarator->lastToken(); - else if (new_initializer) - return new_initializer->lastToken(); - for (SpecifierAST *it = type_specifier; it; it = it->next) { + for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next) { if (! it->next) return it->lastToken(); } + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (it->next) + return it->lastToken(); + } + + if (type_specifier) + return type_specifier->lastToken(); + // ### assert? return 0; } diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 26f0a6692b5..78e45ce328f 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -152,7 +152,8 @@ public: virtual NestedDeclaratorAST *asNestedDeclarator() { return 0; } virtual NestedExpressionAST *asNestedExpression() { return 0; } virtual NestedNameSpecifierAST *asNestedNameSpecifier() { return 0; } - virtual NewDeclaratorAST *asNewDeclarator() { return 0; } + virtual NewPlacementAST *asNewPlacement() { return 0; } + virtual NewArrayDeclaratorAST *asNewArrayDeclarator() { return 0; } virtual NewExpressionAST *asNewExpression() { return 0; } virtual NewInitializerAST *asNewInitializer() { return 0; } virtual NewTypeIdAST *asNewTypeId() { return 0; } @@ -1440,20 +1441,42 @@ protected: virtual void accept0(ASTVisitor *visitor); }; -class CPLUSPLUS_EXPORT NewDeclaratorAST: public AST +class CPLUSPLUS_EXPORT NewPlacementAST: public AST { public: - PtrOperatorAST *ptr_operators; - NewDeclaratorAST *declarator; + unsigned lparen_token; + ExpressionListAST *expression_list; + unsigned rparen_token; public: - virtual NewDeclaratorAST *asNewDeclarator() + virtual NewPlacementAST *asNewPlacement() { return this; } virtual unsigned firstToken() const; virtual unsigned lastToken() const; - virtual NewDeclaratorAST *clone(MemoryPool *pool) const; + virtual NewPlacementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewArrayDeclaratorAST: public AST +{ +public: + unsigned lbracket_token; + ExpressionAST *expression; + unsigned rbracket_token; + NewArrayDeclaratorAST *next; + +public: + virtual NewArrayDeclaratorAST *asNewArrayDeclarator() + { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewArrayDeclaratorAST *clone(MemoryPool *pool) const; protected: virtual void accept0(ASTVisitor *visitor); @@ -1464,9 +1487,14 @@ class CPLUSPLUS_EXPORT NewExpressionAST: public ExpressionAST public: unsigned scope_token; unsigned new_token; - ExpressionAST *expression; + NewPlacementAST *new_placement; + + unsigned lparen_token; ExpressionAST *type_id; + unsigned rparen_token; + NewTypeIdAST *new_type_id; + NewInitializerAST *new_initializer; public: @@ -1506,8 +1534,8 @@ class CPLUSPLUS_EXPORT NewTypeIdAST: public AST { public: SpecifierAST *type_specifier; - NewInitializerAST *new_initializer; - NewDeclaratorAST *new_declarator; + PtrOperatorAST *ptr_operators; + NewArrayDeclaratorAST *new_array_declarators; public: virtual NewTypeIdAST *asNewTypeId() diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 92fa70e55bd..3ab1fc66e9a 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -144,7 +144,8 @@ public: virtual bool visit(NestedDeclaratorAST *) { return true; } virtual bool visit(NestedExpressionAST *) { return true; } virtual bool visit(NestedNameSpecifierAST *) { return true; } - virtual bool visit(NewDeclaratorAST *) { return true; } + virtual bool visit(NewPlacementAST *) { return true; } + virtual bool visit(NewArrayDeclaratorAST *) { return true; } virtual bool visit(NewExpressionAST *) { return true; } virtual bool visit(NewInitializerAST *) { return true; } virtual bool visit(NewTypeIdAST *) { return true; } @@ -248,7 +249,8 @@ public: virtual void endVisit(NestedDeclaratorAST *) { } virtual void endVisit(NestedExpressionAST *) { } virtual void endVisit(NestedNameSpecifierAST *) { } - virtual void endVisit(NewDeclaratorAST *) { } + virtual void endVisit(NewPlacementAST *) { } + virtual void endVisit(NewArrayDeclaratorAST *) { } virtual void endVisit(NewExpressionAST *) { } virtual void endVisit(NewInitializerAST *) { } virtual void endVisit(NewTypeIdAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index b4f5283a748..140b0820c0f 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -121,8 +121,9 @@ class NamespaceAliasDefinitionAST; class NestedDeclaratorAST; class NestedExpressionAST; class NestedNameSpecifierAST; -class NewDeclaratorAST; +class NewArrayDeclaratorAST; class NewExpressionAST; +class NewPlacementAST; class NewInitializerAST; class NewTypeIdAST; class NumericLiteralAST; diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index e26a19ba805..aaf24c48e15 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -214,8 +214,9 @@ bool CheckExpression::visit(TemplateIdAST *ast) bool CheckExpression::visit(NewExpressionAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); - FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); + // ### FIXME + //FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + //FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); // ### process new-typeid // ### process new-initializer return false; diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index bfd2d6696a4..c5dacb08114 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -3104,37 +3104,91 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node) return parsePostfixExpression(node); } +// new-placement ::= T_LPAREN expression-list T_RPAREN +bool Parser::parseNewPlacement(NewPlacementAST *&node) +{ + if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + ExpressionListAST *expression_list = 0; + if (parseExpressionList(expression_list) && expression_list && LA() == T_RPAREN) { + unsigned rparen_token = consumeToken(); + NewPlacementAST *ast = new (_pool) NewPlacementAST; + ast->lparen_token = lparen_token; + ast->expression_list = expression_list; + ast->rparen_token = rparen_token; + node = ast; + return true; + } + } + + return false; +} + +// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt +// new-type-id new-initializer.opt +// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt +// T_LPAREN type-id T_RPAREN new-initializer.opt bool Parser::parseNewExpression(ExpressionAST *&node) { - if (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW)) { - NewExpressionAST *ast = new (_pool) NewExpressionAST; + if (! (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW))) + return false; - if (LA() == T_COLON_COLON) - ast->scope_token = consumeToken(); + NewExpressionAST *ast = new (_pool) NewExpressionAST; + if (LA() == T_COLON_COLON) + ast->scope_token = consumeToken(); - ast->new_token = consumeToken(); + ast->new_token = consumeToken(); - if (LA() == T_LPAREN) { - consumeToken(); - parseExpression(ast->expression); - if (LA() == T_RPAREN) - consumeToken(); + NewPlacementAST *new_placement = 0; + + if (parseNewPlacement(new_placement)) { + unsigned after_new_placement = cursor(); + + NewTypeIdAST *new_type_id = 0; + if (parseNewTypeId(new_type_id)) { + ast->new_placement = new_placement; + ast->new_type_id = new_type_id; + parseNewInitializer(ast->new_initializer); + // recognized new-placement.opt new-type-id new-initializer.opt + node = ast; + return true; } + rewind(after_new_placement); if (LA() == T_LPAREN) { - consumeToken(); - parseTypeId(ast->type_id); - if (LA() == T_RPAREN) - consumeToken(); - } else { - parseNewTypeId(ast->new_type_id); + unsigned lparen_token = consumeToken(); + ExpressionAST *type_id = 0; + if (parseTypeId(type_id) && LA() == T_RPAREN) { + ast->new_placement = new_placement; + ast->lparen_token = lparen_token; + ast->type_id = type_id; + ast->rparen_token = consumeToken(); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; + } } + } - parseNewInitializer(ast->new_initializer); - node = ast; - return true; + rewind(ast->new_token + 1); + + if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + ExpressionAST *type_id = 0; + if (parseTypeId(type_id) && LA() == T_RPAREN) { + ast->lparen_token = lparen_token; + ast->type_id = type_id; + ast->rparen_token = consumeToken(); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; + } } - return false; + + parseNewTypeId(ast->new_type_id); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; } bool Parser::parseNewTypeId(NewTypeIdAST *&node) @@ -3145,27 +3199,26 @@ bool Parser::parseNewTypeId(NewTypeIdAST *&node) NewTypeIdAST *ast = new (_pool) NewTypeIdAST; ast->type_specifier = typeSpec; - parseNewDeclarator(ast->new_declarator); + PtrOperatorAST **ptrop_it = &ast->ptr_operators; + while (parsePtrOperator(*ptrop_it)) + ptrop_it = &(*ptrop_it)->next; + NewArrayDeclaratorAST **it = &ast->new_array_declarators; + while (parseNewArrayDeclarator(*it)) + it = &(*it)->next; node = ast; return true; } -bool Parser::parseNewDeclarator(NewDeclaratorAST *&node) -{ - NewDeclaratorAST *ast = new (_pool) NewDeclaratorAST; - - PtrOperatorAST **ptr_operators_tail = &ast->ptr_operators; - while (parsePtrOperator(*ptr_operators_tail)) - ptr_operators_tail = &(*ptr_operators_tail)->next; - while (LA() == T_LBRACKET) { // ### create the AST - consumeToken(); - ExpressionAST *expression = 0; - parseExpression(expression); - unsigned rbracket_token = 0; - match(T_RBRACKET, &rbracket_token); - } +bool Parser::parseNewArrayDeclarator(NewArrayDeclaratorAST *&node) +{ + if (LA() != T_LBRACKET) + return false; + NewArrayDeclaratorAST *ast = new (_pool) NewArrayDeclaratorAST; + ast->lbracket_token = consumeToken(); + parseExpression(ast->expression); + match(T_RBRACKET, &ast->rbracket_token); node = ast; return true; } diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index e6a29d199e2..fbd2e7194f9 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -150,8 +150,9 @@ public: bool parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name, bool acceptTemplateId); bool parseNamespace(DeclarationAST *&node); bool parseNamespaceAliasDefinition(DeclarationAST *&node); - bool parseNewDeclarator(NewDeclaratorAST *&node); + bool parseNewArrayDeclarator(NewArrayDeclaratorAST *&node); bool parseNewExpression(ExpressionAST *&node); + bool parseNewPlacement(NewPlacementAST *&node); bool parseNewInitializer(NewInitializerAST *&node); bool parseNewTypeId(NewTypeIdAST *&node); bool parseOperator(OperatorAST *&node); diff --git a/src/shared/cplusplus/PrettyPrinter.cpp b/src/shared/cplusplus/PrettyPrinter.cpp index d6c604c3abb..8c00791ade1 100644 --- a/src/shared/cplusplus/PrettyPrinter.cpp +++ b/src/shared/cplusplus/PrettyPrinter.cpp @@ -764,15 +764,11 @@ bool PrettyPrinter::visit(NestedNameSpecifierAST *ast) return false; } -bool PrettyPrinter::visit(NewDeclaratorAST *ast) +bool PrettyPrinter::visit(NewArrayDeclaratorAST *ast) { - for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { - accept(it); - if (it->next) - out << ' '; - } - if (ast->declarator) - accept(ast->declarator); + out << '['; + accept(ast->expression); + out << ']'; return false; } @@ -782,25 +778,32 @@ bool PrettyPrinter::visit(NewExpressionAST *ast) out << "::"; out << "new"; out << ' '; - if (ast->expression) { - accept(ast->expression); - if (ast->type_id) - out << ' '; - } - if (ast->type_id) { + accept(ast->new_placement); + if (ast->new_placement) + out << ' '; + if (ast->lparen_token) { + out << '('; accept(ast->type_id); - if (ast->new_type_id) - out << ' '; - } - if (ast->new_type_id) { + out << ')'; + } else { accept(ast->new_type_id); - if (ast->new_initializer) - out << ' '; } accept(ast->new_initializer); return false; } +bool PrettyPrinter::visit(NewPlacementAST *ast) +{ + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + bool PrettyPrinter::visit(NewInitializerAST *ast) { out << '('; @@ -812,18 +815,16 @@ bool PrettyPrinter::visit(NewInitializerAST *ast) bool PrettyPrinter::visit(NewTypeIdAST *ast) { for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { - accept(it); - if (it->next) + if (it != ast->type_specifier) out << ' '; + accept(it); } - if (ast->type_specifier) - out << ' '; - if (ast->new_initializer) { - accept(ast->new_initializer); - if (ast->new_declarator) - out << ' '; + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + for (NewArrayDeclaratorAST *it = ast->new_array_declarators; it; it = it->next) { + accept(it); } - accept(ast->new_declarator); return false; } diff --git a/src/shared/cplusplus/PrettyPrinter.h b/src/shared/cplusplus/PrettyPrinter.h index c69ea2cf544..f20b8e360d6 100644 --- a/src/shared/cplusplus/PrettyPrinter.h +++ b/src/shared/cplusplus/PrettyPrinter.h @@ -106,7 +106,8 @@ protected: virtual bool visit(NestedDeclaratorAST *ast); virtual bool visit(NestedExpressionAST *ast); virtual bool visit(NestedNameSpecifierAST *ast); - virtual bool visit(NewDeclaratorAST *ast); + virtual bool visit(NewArrayDeclaratorAST *ast); + virtual bool visit(NewPlacementAST *ast); virtual bool visit(NewExpressionAST *ast); virtual bool visit(NewInitializerAST *ast); virtual bool visit(NewTypeIdAST *ast); diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 689da076ea1..e4ef03211d0 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -42,6 +42,8 @@ private slots: // expressions void simple_name(); void template_id(); + void new_expression_1(); + void new_expression_2(); // statements void if_statement(); @@ -91,6 +93,59 @@ void tst_AST::template_id() QCOMPARE(ast->asTemplateId()->greater_token, 4U); } +void tst_AST::new_expression_1() +{ + QSharedPointer<TranslationUnit> unit(parseExpression("\n" +"new char" + )); + + AST *ast = unit->ast(); + QVERIFY(ast != 0); + + NewExpressionAST *expr = ast->asNewExpression(); + QVERIFY(expr != 0); + + QCOMPARE(expr->scope_token, 0U); + QCOMPARE(expr->new_token, 1U); + QVERIFY(expr->new_placement == 0); + QCOMPARE(expr->lparen_token, 0U); + QVERIFY(expr->type_id == 0); + QCOMPARE(expr->rparen_token, 0U); + QVERIFY(expr->new_type_id != 0); + QVERIFY(expr->new_initializer == 0); + + QVERIFY(expr->new_type_id->type_specifier != 0); + QVERIFY(expr->new_type_id->ptr_operators == 0); + QVERIFY(expr->new_type_id->new_array_declarators == 0); +} + +void tst_AST::new_expression_2() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("\n" +"::new(__p) _Tp(__val);" + )); + + AST *ast = unit->ast(); + QVERIFY(ast != 0); + + ExpressionStatementAST *stmt = ast->asExpressionStatement(); + QVERIFY(stmt != 0); + QVERIFY(stmt->expression != 0); + QVERIFY(stmt->semicolon_token != 0); + + NewExpressionAST *expr = stmt->expression->asNewExpression(); + QVERIFY(expr != 0); + + QCOMPARE(expr->scope_token, 1U); + QCOMPARE(expr->new_token, 2U); + QVERIFY(expr->new_placement != 0); + QCOMPARE(expr->lparen_token, 0U); + QVERIFY(expr->type_id == 0); + QCOMPARE(expr->rparen_token, 0U); + QVERIFY(expr->new_type_id != 0); + QVERIFY(expr->new_initializer != 0); +} + void tst_AST::if_statement() { QSharedPointer<TranslationUnit> unit(parseStatement("if (a) b;")); -- GitLab