Files
qt-creator/tests/auto/cplusplus/ast/tst_ast.cpp
Nikolai Kosjar beac7b9539 C++: Fix highlighting after "invalid code"
For the semantic info document we do not expand function like macros and
because of that certain macro invocations lead to invalid code that we
need to handle, e.g.:

	Q_GLOBAL_STATIC(CppTools::SymbolFinder, symbolFinder)
	class Foo {};

This change makes parsing Foo in the semantic info document successfully
again, which affects highlighting of that class.

Change-Id: I389265ac64d3f0b8b8f406d38fa58d78820b14ba
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
2014-11-19 16:10:56 +01:00

1910 lines
70 KiB
C++

/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include <QtTest>
#include <QDebug>
#include <cplusplus/ASTVisitor.h>
#include <cplusplus/Control.h>
#include <cplusplus/Literals.h>
#include <cplusplus/Parser.h>
#include <cplusplus/AST.h>
//TESTED_COMPONENT=src/libs/cplusplus
using namespace CPlusPlus;
class tst_AST: public QObject
{
Q_OBJECT
Control control;
public:
TranslationUnit *parse(const QByteArray &source,
TranslationUnit::ParseMode mode,
bool blockErrors = false,
bool qtMocRun = false,
bool cxx11Enabled = false,
int retryParseDeclarationLimit
= TranslationUnit::defaultRetryParseDeclarationLimit())
{
const StringLiteral *fileId = control.stringLiteral("<stdin>");
LanguageFeatures features;
features.cxx11Enabled = cxx11Enabled;
features.objCEnabled = true;
features.qtEnabled = qtMocRun;
features.qtKeywordsEnabled = qtMocRun;
features.qtMocRunEnabled = qtMocRun;
TranslationUnit *unit = new TranslationUnit(&control, fileId);
unit->setLanguageFeatures(features);
unit->setRetryParseDeclarationLimit(retryParseDeclarationLimit);
unit->setSource(source.constData(), source.length());
unit->blockErrors(blockErrors);
unit->parse(mode);
// Sanity check: Visit all AST nodes
if (AST *ast = unit->ast()) {
ASTVisitor visitor(unit);
visitor.accept(ast);
}
return unit;
}
TranslationUnit *parseDeclaration(const QByteArray &source, bool blockErrors = false, bool qtMocRun = false)
{ return parse(source, TranslationUnit::ParseDeclaration, blockErrors, qtMocRun); }
TranslationUnit *parseExpression(const QByteArray &source)
{ return parse(source, TranslationUnit::ParseExpression); }
TranslationUnit *parseStatement(const QByteArray &source, bool cxx11Enabled = false)
{ return parse(source, TranslationUnit::ParseStatement, false, false, cxx11Enabled); }
class Diagnostic: public DiagnosticClient {
public:
int errorCount;
Diagnostic()
: errorCount(0)
{ }
virtual void report(int /*level*/,
const StringLiteral *fileName,
unsigned line, unsigned column,
const char *format, va_list ap)
{
++errorCount;
qDebug() << fileName->chars()<<':'<<line<<':'<<column<<' '<<QString().vsprintf(format, ap);
}
};
Diagnostic diag;
private slots:
void initTestCase();
void cleanup();
// line/column positions
void line_and_column_1();
// declarations
void gcc_attributes_1();
void gcc_attributes_2();
void gcc_attributes_3();
void crash_test_1();
void thread_local_1();
// expressions
void simple_name_1();
void template_id_1();
void new_expression_1();
void new_expression_2();
void condition_1();
void init_1();
void conditional_1();
void throw_1();
void templated_dtor_1();
void templated_dtor_2();
void templated_dtor_3();
void templated_dtor_4();
void templated_dtor_5();
// possible declaration-or-expression statements
void call_call_1();
// statements
void if_statement_1();
void if_statement_2();
void if_statement_3();
void if_else_statement();
void while_statement();
void while_condition_statement();
void for_statement();
void cpp_initializer_or_function_declaration();
void simple_declaration_1();
void function_call_1();
void function_call_2();
void function_call_3();
void function_call_4();
void nested_deref_expression();
void assignment_1();
void assignment_2();
// constructor declarations
void cpp_constructor_one_unamed_arg();
void cpp_constructor_one_unamed_arg_namespace();
void cpp_constructor_one_knowntype_arg();
void cpp_constructor_one_const_arg();
void cpp_constructor_one_ref_arg();
void cpp_constructor_one_named_arg();
void cpp_constructor_no_arg();
void cpp_constructor_multiple_args();
void cpp_constructor_function_try_catch();
// Q_PROPERTY
void cpp_qproperty();
void cpp_qproperty_data();
// objc++
void objc_simple_class();
void objc_attributes_followed_by_at_keyword();
void objc_protocol_forward_declaration_1();
void objc_protocol_definition_1();
void objc_method_attributes_1();
void objc_selector_error_recovery_1();
void objc_selector_error_recovery_2();
void objc_try_statement_1();
void objc_try_statement_2();
void objc_try_statement_3();
void objc_throw_statement();
// expressions with (square) brackets
void normal_array_access();
void array_access_with_nested_expression();
void objc_msg_send_expression();
void objc_msg_send_expression_without_selector();
// Qt "keywords"
void q_enum_1();
void declarationWithNewStatement();
void declarationWithNewStatement_data();
void incomplete_ast();
void unnamed_class();
void unnamed_class_data();
void expensiveExpression();
void invalidCode();
};
void tst_AST::gcc_attributes_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"static inline void *__attribute__((__always_inline__)) _mm_malloc(size_t size, size_t align);"
));
}
void tst_AST::gcc_attributes_2()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration(
"\nnamespace std __attribute__ ((__visibility__ (\"default\"))) {\n}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
NamespaceAST* ns = ast->asNamespace();
QVERIFY(ns);
QCOMPARE(unit->spell(ns->identifier_token), "std");
QVERIFY(ns->attribute_list);
QVERIFY(!ns->attribute_list->next);
QVERIFY(ns->attribute_list->value);
GnuAttributeSpecifierAST *attrSpec = ns->attribute_list->value->asGnuAttributeSpecifier();
QVERIFY(attrSpec);
QVERIFY(attrSpec->attribute_list);
QVERIFY(!attrSpec->attribute_list->next);
QVERIFY(attrSpec->attribute_list->value);
GnuAttributeAST *attr = attrSpec->attribute_list->value->asGnuAttribute();
QVERIFY(attr);
QCOMPARE(unit->spell(attr->identifier_token), "__visibility__");
QVERIFY(attr->expression_list);
QVERIFY(!attr->expression_list->next);
QVERIFY(attr->expression_list->value);
StringLiteralAST *e = attr->expression_list->value->asStringLiteral();
QVERIFY(e);
QVERIFY(!e->next);
QCOMPARE(unit->spell(e->literal_token), "default");
}
void tst_AST::gcc_attributes_3()
{
const char *inp = "\nnamespace std X {\n}\n";
QSharedPointer<TranslationUnit> unit(parseDeclaration(inp));
AST *ast = unit->ast();
QVERIFY(ast);
NamespaceAST* ns = ast->asNamespace();
QVERIFY(ns);
QCOMPARE(unit->spell(ns->identifier_token), "std");
QVERIFY(!ns->attribute_list);
QVERIFY(ns->linkage_body);
LinkageBodyAST *link = ns->linkage_body->asLinkageBody();
QVERIFY(link);
QCOMPARE(unit->tokenKind(link->lbrace_token), T_LBRACE);
QVERIFY(!link->declaration_list);
QCOMPARE(unit->tokenKind(link->rbrace_token), T_RBRACE);
}
void tst_AST::crash_test_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("decltype auto\n"));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::thread_local_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("__thread int i;\n"));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
QCOMPARE(Token::name(T_THREAD_LOCAL), "thread_local");
QCOMPARE(Token::name(T___THREAD), "__thread");
}
void tst_AST::simple_declaration_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("\n"
"a * b = 10;"
));
AST *ast = unit->ast();
QVERIFY(ast);
DeclarationStatementAST *declStmt = ast->asDeclarationStatement();
QVERIFY(declStmt);
}
void tst_AST::simple_name_1()
{
QSharedPointer<TranslationUnit> unit(parseExpression("a"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asIdExpression()->name->asSimpleName() != 0);
QCOMPARE(ast->asIdExpression()->name->asSimpleName()->identifier_token, 1U);
}
void tst_AST::template_id_1()
{
QSharedPointer<TranslationUnit> unit(parseExpression("list<10>"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asIdExpression()->name->asTemplateId() != 0);
QCOMPARE(ast->asIdExpression()->name->asTemplateId()->identifier_token, 1U);
QCOMPARE(ast->asIdExpression()->name->asTemplateId()->less_token, 2U);
QVERIFY(ast->asIdExpression()->name->asTemplateId()->template_argument_list != 0);
QVERIFY(ast->asIdExpression()->name->asTemplateId()->template_argument_list->value != 0);
QVERIFY(ast->asIdExpression()->name->asTemplateId()->template_argument_list->value->asNumericLiteral() != 0);
QCOMPARE(ast->asIdExpression()->name->asTemplateId()->template_argument_list->value->asNumericLiteral()->literal_token, 3U);
QVERIFY(ast->asIdExpression()->name->asTemplateId()->template_argument_list->next == 0);
QCOMPARE(ast->asIdExpression()->name->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_list != 0);
QVERIFY(expr->new_type_id->ptr_operator_list == 0);
QVERIFY(expr->new_type_id->new_array_declarator_list == 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::condition_1()
{
QSharedPointer<TranslationUnit> unit(parseExpression("\n"
"(x < 0 && y > (int) a)"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
NestedExpressionAST *nestedExpr = ast->asNestedExpression();
QVERIFY(nestedExpr);
QVERIFY(nestedExpr->expression);
BinaryExpressionAST *andExpr = nestedExpr->expression->asBinaryExpression();
QVERIFY(andExpr);
QCOMPARE(unit->tokenKind(andExpr->binary_op_token), T_AMPER_AMPER);
QVERIFY(andExpr->left_expression);
QVERIFY(andExpr->right_expression);
BinaryExpressionAST *ltExpr = andExpr->left_expression->asBinaryExpression();
QVERIFY(ltExpr);
QCOMPARE(unit->tokenKind(ltExpr->binary_op_token), T_LESS);
QVERIFY(ltExpr->left_expression);
QVERIFY(ltExpr->right_expression);
SimpleNameAST *x = ltExpr->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(x);
QCOMPARE(unit->spell(x->identifier_token), "x");
NumericLiteralAST *zero = ltExpr->right_expression->asNumericLiteral();
QVERIFY(zero);
QCOMPARE(unit->spell(zero->literal_token), "0");
BinaryExpressionAST *gtExpr = andExpr->right_expression->asBinaryExpression();
QVERIFY(gtExpr);
QCOMPARE(unit->tokenKind(gtExpr->binary_op_token), T_GREATER);
QVERIFY(gtExpr->left_expression);
QVERIFY(gtExpr->right_expression);
SimpleNameAST *y = gtExpr->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(y);
QCOMPARE(unit->spell(y->identifier_token), "y");
CastExpressionAST *cast = gtExpr->right_expression->asCastExpression();
QVERIFY(cast);
QVERIFY(cast->type_id);
QVERIFY(cast->expression);
TypeIdAST *intType = cast->type_id->asTypeId();
QVERIFY(intType);
// ### here we could check if the type is an actual int
SimpleNameAST *a = cast->expression->asIdExpression()->name->asSimpleName();
QVERIFY(a);
QCOMPARE(unit->spell(a->identifier_token), "a");
}
void tst_AST::init_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"x y[] = { X<10>, y };"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
}
void tst_AST::conditional_1()
{
QSharedPointer<TranslationUnit> unit(parseExpression("\n"
"(x < 0 && y > (int) a) ? x == 1 : y = 1"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ConditionalExpressionAST *conditional = ast->asConditionalExpression();
QVERIFY(conditional);
QVERIFY(conditional->condition);
QVERIFY(conditional->left_expression);
QVERIFY(conditional->right_expression);
NestedExpressionAST *nestedExpr = conditional->condition->asNestedExpression();
QVERIFY(nestedExpr);
QVERIFY(nestedExpr->expression);
BinaryExpressionAST *andExpr = nestedExpr->expression->asBinaryExpression();
QVERIFY(andExpr);
QCOMPARE(unit->tokenKind(andExpr->binary_op_token), T_AMPER_AMPER);
QVERIFY(andExpr->left_expression);
QVERIFY(andExpr->right_expression);
BinaryExpressionAST *ltExpr = andExpr->left_expression->asBinaryExpression();
QVERIFY(ltExpr);
QCOMPARE(unit->tokenKind(ltExpr->binary_op_token), T_LESS);
QVERIFY(ltExpr->left_expression);
QVERIFY(ltExpr->right_expression);
SimpleNameAST *x = ltExpr->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(x);
QCOMPARE(unit->spell(x->identifier_token), "x");
NumericLiteralAST *zero = ltExpr->right_expression->asNumericLiteral();
QVERIFY(zero);
QCOMPARE(unit->spell(zero->literal_token), "0");
BinaryExpressionAST *gtExpr = andExpr->right_expression->asBinaryExpression();
QVERIFY(gtExpr);
QCOMPARE(unit->tokenKind(gtExpr->binary_op_token), T_GREATER);
QVERIFY(gtExpr->left_expression);
QVERIFY(gtExpr->right_expression);
SimpleNameAST *y = gtExpr->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(y);
QCOMPARE(unit->spell(y->identifier_token), "y");
CastExpressionAST *cast = gtExpr->right_expression->asCastExpression();
QVERIFY(cast);
QVERIFY(cast->type_id);
QVERIFY(cast->expression);
TypeIdAST *intType = cast->type_id->asTypeId();
QVERIFY(intType);
QVERIFY(! (intType->declarator));
QVERIFY(intType->type_specifier_list);
QVERIFY(! (intType->type_specifier_list->next));
QVERIFY(intType->type_specifier_list->value);
SimpleSpecifierAST *intSpec = intType->type_specifier_list->value->asSimpleSpecifier();
QVERIFY(intSpec);
QCOMPARE(unit->spell(intSpec->specifier_token), "int");
SimpleNameAST *a = cast->expression->asIdExpression()->name->asSimpleName();
QVERIFY(a);
QCOMPARE(unit->spell(a->identifier_token), "a");
BinaryExpressionAST *equals = conditional->left_expression->asBinaryExpression();
QVERIFY(equals);
QCOMPARE(unit->tokenKind(equals->binary_op_token), T_EQUAL_EQUAL);
x = equals->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(x);
QCOMPARE(unit->spell(x->identifier_token), "x");
NumericLiteralAST *one = equals->right_expression->asNumericLiteral();
QVERIFY(one);
QCOMPARE(unit->spell(one->literal_token), "1");
BinaryExpressionAST *assignment = conditional->right_expression->asBinaryExpression();
QVERIFY(assignment);
QCOMPARE(unit->tokenKind(assignment->binary_op_token), T_EQUAL);
y = assignment->left_expression->asIdExpression()->name->asSimpleName();
QVERIFY(y);
QCOMPARE(unit->spell(y->identifier_token), "y");
one = assignment->right_expression->asNumericLiteral();
QVERIFY(one);
QCOMPARE(unit->spell(one->literal_token), "1");
}
void tst_AST::throw_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("throw 1;"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::templated_dtor_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a.b::~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
MemberAccessAST *mem = call->base_expression->asMemberAccess();
QVERIFY(mem);
QCOMPARE(unit->spell(mem->base_expression->asIdExpression()->name->asSimpleName()->identifier_token), "a");
QualifiedNameAST *qName = mem->member_name->asQualifiedName();
QVERIFY(qName);
QVERIFY(qName->nested_name_specifier_list);
QVERIFY(!qName->nested_name_specifier_list->next);
QVERIFY(qName->nested_name_specifier_list->value);
QVERIFY(qName->nested_name_specifier_list->value->class_or_namespace_name);
SimpleNameAST *bName = qName->nested_name_specifier_list->value->class_or_namespace_name->asSimpleName();
QVERIFY(bName);
QCOMPARE(unit->spell(bName->identifier_token), "b");
QVERIFY(qName->unqualified_name);
DestructorNameAST *dtor = qName->unqualified_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_2()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a.~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
MemberAccessAST *mem = call->base_expression->asMemberAccess();
QVERIFY(mem);
QCOMPARE(unit->spell(mem->base_expression->asIdExpression()->name->asSimpleName()->identifier_token), "a");
QVERIFY(mem->member_name);
DestructorNameAST *dtor = mem->member_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_3()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a::~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
IdExpressionAST *idExpr = call->base_expression->asIdExpression();
QVERIFY(idExpr);
QVERIFY(idExpr->name);
QualifiedNameAST *qName = idExpr->name->asQualifiedName();
QVERIFY(qName);
QVERIFY(qName->nested_name_specifier_list);
QVERIFY(!qName->nested_name_specifier_list->next);
QVERIFY(qName->nested_name_specifier_list->value);
QVERIFY(qName->nested_name_specifier_list->value->class_or_namespace_name);
SimpleNameAST *bName = qName->nested_name_specifier_list->value->class_or_namespace_name->asSimpleName();
QVERIFY(bName);
QCOMPARE(unit->spell(bName->identifier_token), "a");
QVERIFY(qName->unqualified_name);
DestructorNameAST *dtor = qName->unqualified_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_4()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
UnaryExpressionAST *u = e->expression->asUnaryExpression();
QVERIFY(u);
QCOMPARE(unit->tokenKind(u->unary_op_token), T_TILDE);
QVERIFY(u->expression);
CallAST *call = u->expression->asCall();
QVERIFY(call);
QVERIFY(call->base_expression);
IdExpressionAST *idExpr = call->base_expression->asIdExpression();
QVERIFY(idExpr);
QVERIFY(idExpr->name);
TemplateIdAST *tid = idExpr->name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_5()
{
QSharedPointer<TranslationUnit> unit(parseExpression(
"\n"
"~a < b()"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
BinaryExpressionAST *binExpr = ast->asBinaryExpression();
QVERIFY(binExpr);
QVERIFY(binExpr->left_expression);
UnaryExpressionAST *notExpr = binExpr->left_expression->asUnaryExpression();
QVERIFY(notExpr);
QCOMPARE(unit->tokenKind(notExpr->unary_op_token), T_TILDE);
CallAST *call = binExpr->right_expression->asCall();
QVERIFY(call->base_expression);
QVERIFY(!call->expression_list);
IdExpressionAST *bExpr = call->base_expression->asIdExpression();
QVERIFY(bExpr);
SimpleNameAST *bName = bExpr->name->asSimpleName();
QVERIFY(bName);
QCOMPARE(unit->spell(bName->identifier_token), "b");
}
void tst_AST::call_call_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("method()->call();"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *exprStmt = ast->asExpressionStatement();
QVERIFY(exprStmt);
ExpressionAST *expr = exprStmt->expression;
QVERIFY(expr);
CallAST *memberCall = expr->asCall();
QVERIFY(memberCall);
QVERIFY(memberCall->base_expression);
QVERIFY(!memberCall->expression_list);
MemberAccessAST *member_xs = memberCall->base_expression->asMemberAccess();
QVERIFY(member_xs);
QVERIFY(member_xs->member_name);
SimpleNameAST *member_name = member_xs->member_name->asSimpleName();
QVERIFY(member_name);
QVERIFY(member_name->identifier_token);
QCOMPARE(unit->spell(member_name->identifier_token), "call");
QCOMPARE(unit->tokenKind(member_xs->access_token), T_ARROW);
QVERIFY(member_xs->base_expression);
CallAST *method_call = member_xs->base_expression->asCall();
QVERIFY(method_call);
QVERIFY(!method_call->expression_list);
QVERIFY(method_call->base_expression);
IdExpressionAST *member_expr = method_call->base_expression->asIdExpression();
QVERIFY(member_expr);
QVERIFY(member_expr->name);
SimpleNameAST *member_name2 = member_expr->name->asSimpleName();
QVERIFY(member_name2);
QVERIFY(member_name2->identifier_token);
QCOMPARE(unit->spell(member_name2->identifier_token), "method");
}
void tst_AST::function_call_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("retranslateUi(blah);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::function_call_2()
{
QSharedPointer<TranslationUnit> unit(parseStatement("retranslateUi(10);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::function_call_3()
{
QSharedPointer<TranslationUnit> unit(parseStatement("advance();"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::function_call_4()
{
QSharedPointer<TranslationUnit> unit(parseStatement("checkPropertyAttribute(attrAst, propAttrs, ReadWrite);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::nested_deref_expression()
{
QSharedPointer<TranslationUnit> unit(parseStatement("(*blah);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::assignment_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("a(x) = 3;"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::assignment_2()
{
QSharedPointer<TranslationUnit> unit(parseStatement("(*blah) = 10;"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
QVERIFY(ast->asExpressionStatement());
}
void tst_AST::if_statement_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement("if (a) b;"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
IfStatementAST *stmt = ast->asIfStatement();
QVERIFY(stmt != 0);
QCOMPARE(stmt->if_token, 1U);
QCOMPARE(stmt->lparen_token, 2U);
QVERIFY(stmt->condition != 0);
QCOMPARE(stmt->rparen_token, 4U);
QVERIFY(stmt->statement != 0);
QCOMPARE(stmt->else_token, 0U);
QVERIFY(stmt->else_statement == 0);
// check the `then' statement1
ExpressionStatementAST *then_stmt = stmt->statement->asExpressionStatement();
QVERIFY(then_stmt != 0);
QVERIFY(then_stmt->expression != 0);
QCOMPARE(then_stmt->semicolon_token, 6U);
SimpleNameAST *id_expr = then_stmt->expression->asIdExpression()->name->asSimpleName();
QVERIFY(id_expr != 0);
QCOMPARE(id_expr->identifier_token, 5U);
}
void tst_AST::if_statement_2()
{
QSharedPointer<TranslationUnit> unit(parseStatement("if (x<0 && y>a);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
IfStatementAST *stmt = ast->asIfStatement();
QVERIFY(stmt != 0);
QVERIFY(stmt->condition);
QVERIFY(stmt->condition->asBinaryExpression());
QCOMPARE(unit->tokenKind(stmt->condition->asBinaryExpression()->binary_op_token), T_AMPER_AMPER);
}
void tst_AST::if_statement_3()
{
QSharedPointer<TranslationUnit> unit(parseStatement("if (x<0 && x<0 && x<0 && x<0 && x<0 && x<0 && x<0);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
IfStatementAST *stmt = ast->asIfStatement();
QVERIFY(stmt != 0);
QVERIFY(stmt->condition);
}
void tst_AST::if_else_statement()
{
QSharedPointer<TranslationUnit> unit(parseStatement("if (a) b; else c;"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
IfStatementAST *stmt = ast->asIfStatement();
QVERIFY(stmt != 0);
QCOMPARE(stmt->if_token, 1U);
QCOMPARE(stmt->lparen_token, 2U);
QVERIFY(stmt->condition != 0);
QCOMPARE(stmt->rparen_token, 4U);
QVERIFY(stmt->statement != 0);
QCOMPARE(stmt->else_token, 7U);
QVERIFY(stmt->else_statement != 0);
// check the `then' statement
ExpressionStatementAST *then_stmt = stmt->statement->asExpressionStatement();
QVERIFY(then_stmt != 0);
QVERIFY(then_stmt->expression != 0);
QCOMPARE(then_stmt->semicolon_token, 6U);
SimpleNameAST *a_id_expr = then_stmt->expression->asIdExpression()->name->asSimpleName();
QVERIFY(a_id_expr != 0);
QCOMPARE(a_id_expr->identifier_token, 5U);
// check the `then' statement
ExpressionStatementAST *else_stmt = stmt->else_statement->asExpressionStatement();
QVERIFY(else_stmt != 0);
QVERIFY(else_stmt->expression != 0);
QCOMPARE(else_stmt->semicolon_token, 9U);
SimpleNameAST *b_id_expr = else_stmt->expression->asIdExpression()->name->asSimpleName();
QVERIFY(b_id_expr != 0);
QCOMPARE(b_id_expr->identifier_token, 8U);
}
void tst_AST::while_statement()
{
QSharedPointer<TranslationUnit> unit(parseStatement("while (a) { }"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
WhileStatementAST *stmt = ast->asWhileStatement();
QVERIFY(stmt != 0);
QCOMPARE(stmt->while_token, 1U);
QCOMPARE(stmt->lparen_token, 2U);
QVERIFY(stmt->condition != 0);
QCOMPARE(stmt->rparen_token, 4U);
QVERIFY(stmt->statement != 0);
// check condition
QVERIFY(stmt->condition->asIdExpression()->name->asSimpleName() != 0);
QCOMPARE(stmt->condition->asIdExpression()->name->asSimpleName()->identifier_token, 3U);
// check the `body' statement
CompoundStatementAST *body_stmt = stmt->statement->asCompoundStatement();
QVERIFY(body_stmt != 0);
QCOMPARE(body_stmt->lbrace_token, 5U);
QVERIFY(body_stmt->statement_list == 0);
QCOMPARE(body_stmt->rbrace_token, 6U);
}
void tst_AST::while_condition_statement()
{
QSharedPointer<TranslationUnit> unit(parseStatement("while (int a = foo) { }"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
WhileStatementAST *stmt = ast->asWhileStatement();
QVERIFY(stmt != 0);
QCOMPARE(stmt->while_token, 1U);
QCOMPARE(stmt->lparen_token, 2U);
QVERIFY(stmt->condition != 0);
QCOMPARE(stmt->rparen_token, 7U);
QVERIFY(stmt->statement != 0);
// check condition
ConditionAST *condition = stmt->condition->asCondition();
QVERIFY(condition != 0);
QVERIFY(condition->type_specifier_list != 0);
QVERIFY(condition->type_specifier_list->value->asSimpleSpecifier() != 0);
QCOMPARE(condition->type_specifier_list->value->asSimpleSpecifier()->specifier_token, 3U);
QVERIFY(condition->type_specifier_list->next == 0);
QVERIFY(condition->declarator != 0);
QVERIFY(condition->declarator->core_declarator != 0);
QVERIFY(condition->declarator->core_declarator->asDeclaratorId() != 0);
QVERIFY(condition->declarator->core_declarator->asDeclaratorId()->name != 0);
QVERIFY(condition->declarator->core_declarator->asDeclaratorId()->name->asSimpleName() != 0);
QCOMPARE(condition->declarator->core_declarator->asDeclaratorId()->name->asSimpleName()->identifier_token, 4U);
QVERIFY(condition->declarator->postfix_declarator_list == 0);
QVERIFY(condition->declarator->initializer != 0);
QVERIFY(condition->declarator->initializer->asIdExpression()->name->asSimpleName() != 0);
QCOMPARE(condition->declarator->initializer->asIdExpression()->name->asSimpleName()->identifier_token, 6U);
// check the `body' statement
CompoundStatementAST *body_stmt = stmt->statement->asCompoundStatement();
QVERIFY(body_stmt != 0);
QCOMPARE(body_stmt->lbrace_token, 8U);
QVERIFY(body_stmt->statement_list == 0);
QCOMPARE(body_stmt->rbrace_token, 9U);
}
void tst_AST::for_statement()
{
QSharedPointer<TranslationUnit> unit(parseStatement("for (;;) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ForStatementAST *stmt = ast->asForStatement();
QVERIFY(stmt != 0);
QCOMPARE(stmt->for_token, 1U);
QCOMPARE(stmt->lparen_token, 2U);
QVERIFY(stmt->initializer != 0);
QVERIFY(stmt->initializer->asExpressionStatement() != 0);
QCOMPARE(stmt->initializer->asExpressionStatement()->semicolon_token, 3U);
QVERIFY(stmt->condition == 0);
QCOMPARE(stmt->semicolon_token, 4U);
QVERIFY(stmt->expression == 0);
QCOMPARE(stmt->rparen_token, 5U);
QVERIFY(stmt->statement != 0);
QVERIFY(stmt->statement->asCompoundStatement() != 0);
QCOMPARE(stmt->statement->asCompoundStatement()->lbrace_token, 6U);
QVERIFY(stmt->statement->asCompoundStatement()->statement_list == 0);
QCOMPARE(stmt->statement->asCompoundStatement()->rbrace_token, 7U);
}
void tst_AST::cpp_initializer_or_function_declaration()
{
QSharedPointer<TranslationUnit> unit(parseStatement("QFileInfo fileInfo(foo);"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
DeclarationStatementAST *stmt = ast->asDeclarationStatement();
QVERIFY(stmt != 0);
QVERIFY(stmt->declaration != 0);
SimpleDeclarationAST *simple_decl = stmt->declaration->asSimpleDeclaration();
QVERIFY(simple_decl != 0);
QVERIFY(simple_decl->decl_specifier_list != 0);
QVERIFY(simple_decl->decl_specifier_list->next == 0);
QVERIFY(simple_decl->declarator_list != 0);
QVERIFY(simple_decl->declarator_list->next == 0);
QCOMPARE(simple_decl->semicolon_token, 6U);
NamedTypeSpecifierAST *named_ty = simple_decl->decl_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(named_ty != 0);
QVERIFY(named_ty->name != 0);
SimpleNameAST *simple_named_ty = named_ty->name->asSimpleName();
QVERIFY(simple_named_ty != 0);
QCOMPARE(simple_named_ty->identifier_token, 1U);
DeclaratorAST *declarator = simple_decl->declarator_list->value;
QVERIFY(declarator != 0);
QVERIFY(declarator->core_declarator != 0);
QVERIFY(declarator->postfix_declarator_list != 0);
QVERIFY(declarator->postfix_declarator_list->next == 0);
QVERIFY(declarator->initializer == 0);
DeclaratorIdAST *decl_id = declarator->core_declarator->asDeclaratorId();
QVERIFY(decl_id != 0);
QVERIFY(decl_id->name != 0);
QVERIFY(decl_id->name->asSimpleName() != 0);
QCOMPARE(decl_id->name->asSimpleName()->identifier_token, 2U);
FunctionDeclaratorAST *fun_declarator = declarator->postfix_declarator_list->value->asFunctionDeclarator();
QVERIFY(fun_declarator != 0);
QCOMPARE(fun_declarator->lparen_token, 3U);
QVERIFY(fun_declarator->parameter_declaration_clause != 0);
QCOMPARE(fun_declarator->rparen_token, 5U);
// check the formal arguments
ParameterDeclarationClauseAST *param_clause = fun_declarator->parameter_declaration_clause;
QVERIFY(param_clause->parameter_declaration_list != 0);
QVERIFY(param_clause->parameter_declaration_list->next == 0);
QCOMPARE(param_clause->dot_dot_dot_token, 0U);
// check the parameter
ParameterDeclarationListAST *declarations = param_clause->parameter_declaration_list;
QVERIFY(declarations);
QVERIFY(declarations->value);
QVERIFY(! declarations->next);
ParameterDeclarationAST *param = declarations->value->asParameterDeclaration();
QVERIFY(param);
QVERIFY(param->type_specifier_list != 0);
QVERIFY(param->type_specifier_list->next == 0);
QVERIFY(param->type_specifier_list->value->asNamedTypeSpecifier() != 0);
QVERIFY(param->type_specifier_list->value->asNamedTypeSpecifier()->name != 0);
QVERIFY(param->type_specifier_list->value->asNamedTypeSpecifier()->name->asSimpleName() != 0);
QCOMPARE(param->type_specifier_list->value->asNamedTypeSpecifier()->name->asSimpleName()->identifier_token, 4U);
}
void tst_AST::cpp_constructor_one_unamed_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString /*name*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_one_unamed_arg_namespace()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("Foo::QFileInfo::QFileInfo(QString /*name*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_one_named_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString name) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_one_knowntype_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(int /*name*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_one_const_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(const QString /*name*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_one_ref_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString & /*name*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_no_arg()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo() {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause == 0);
}
void tst_AST::cpp_constructor_multiple_args()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString /*name*/, QString /*type*/) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_function_try_catch()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString name, QString type)"
" try : m_name(name), m_type(type) {}"
" catch (...) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->ctor_initializer != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_qproperty()
{
QFETCH(QByteArray, source);
QVERIFY(!source.isEmpty());
const QByteArray sourceWithinClass = "class C { " + source + " };";
QSharedPointer<TranslationUnit> unit(parseDeclaration(sourceWithinClass, false, true));
QVERIFY(unit->ast());
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::cpp_qproperty_data()
{
QTest::addColumn<QByteArray>("source");
QTest::newRow("read-final")
<< QByteArray("Q_PROPERTY(bool focus READ hasFocus FINAL)");
QTest::newRow("read-write-final")
<< QByteArray("Q_PROPERTY(bool focus READ hasFocus WRITE setFocus FINAL)");
QTest::newRow("member-final")
<< QByteArray("Q_PROPERTY(bool focus MEMBER m_focus FINAL)");
QTest::newRow("member-read-final")
<< QByteArray("Q_PROPERTY(bool focus MEMBER m_focus READ m_focus FINAL)");
QTest::newRow("member-read-write-final")
<< QByteArray("Q_PROPERTY(bool focus MEMBER m_focus READ hasFocus WRITE setFocus FINAL)");
QTest::newRow("all")
<< QByteArray("Q_PROPERTY(bool focus MEMBER m_focus READ hasFocus WRITE setFocus"
" RESET resetFocus NOTIFY focusChanged REVISION 1 DESIGNABLE true"
" SCRIPTABLE true STORED true USER true CONSTANT FINAL)");
}
void tst_AST::objc_simple_class()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"@interface Zoo {} +(id)alloc;-(id)init;@end\n"
"@implementation Zoo\n"
"+(id)alloc{}\n"
"-(id)init{}\n"
"@end\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_attributes_followed_by_at_keyword()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"__attribute__((deprecated)) @interface foo <bar>\n"
"{\n"
" int a, b;\n"
"}\n"
"+ (id) init;\n"
"- (id) init:(int)a foo:(int)b, c;\n"
"@end\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_protocol_forward_declaration_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n@protocol foo;"));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_protocol_definition_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n@protocol foo <ciao, bar> @end"));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_method_attributes_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"@interface Zoo\n"
"- (void) foo __attribute__((deprecated));\n"
"+ (void) bar __attribute__((unavailable));\n"
"@end\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
ObjCClassDeclarationAST *zoo = ast->asObjCClassDeclaration();
QVERIFY(zoo);
QVERIFY(zoo->interface_token); QVERIFY(! (zoo->implementation_token));
QVERIFY(zoo->class_name); QVERIFY(zoo->class_name->asSimpleName());
QCOMPARE(unit->spell(zoo->class_name->asSimpleName()->identifier_token), "Zoo");
DeclarationListAST *decls = zoo->member_declaration_list;
QVERIFY(decls->value);
QVERIFY(decls->next);
QVERIFY(decls->next->value);
QVERIFY(! (decls->next->next));
ObjCMethodDeclarationAST *fooDecl = decls->value->asObjCMethodDeclaration();
QVERIFY(fooDecl);
QVERIFY(! (fooDecl->function_body));
QVERIFY(fooDecl->semicolon_token);
ObjCMethodPrototypeAST *foo = fooDecl->method_prototype;
QVERIFY(foo);
QCOMPARE(unit->tokenKind(foo->method_type_token), T_MINUS);
QVERIFY(foo->type_name);
QVERIFY(foo->selector);
QVERIFY(foo->selector->selector_argument_list->value);
QVERIFY(!foo->selector->selector_argument_list->next);
QCOMPARE(unit->spell(foo->selector->selector_argument_list->value->name_token), "foo");
QVERIFY(foo->attribute_list);
QVERIFY(foo->attribute_list->value);
QVERIFY(! (foo->attribute_list->next));
GnuAttributeSpecifierAST *deprecatedSpec = foo->attribute_list->value->asGnuAttributeSpecifier();
QVERIFY(deprecatedSpec);
QCOMPARE(unit->tokenKind(deprecatedSpec->attribute_token), T___ATTRIBUTE__);
QVERIFY(deprecatedSpec->attribute_list);
QVERIFY(deprecatedSpec->attribute_list->value);
QVERIFY(! (deprecatedSpec->attribute_list->next));
GnuAttributeAST *deprecatedAttr = deprecatedSpec->attribute_list->value->asGnuAttribute();
QVERIFY(deprecatedAttr);
QVERIFY(! deprecatedAttr->expression_list);
QCOMPARE(unit->spell(deprecatedAttr->identifier_token), "deprecated");
ObjCMethodDeclarationAST *barDecl = decls->next->value->asObjCMethodDeclaration();
QVERIFY(barDecl);
QVERIFY(! (barDecl->function_body));
QVERIFY(barDecl->semicolon_token);
ObjCMethodPrototypeAST *bar = barDecl->method_prototype;
QVERIFY(bar);
QCOMPARE(unit->tokenKind(bar->method_type_token), T_PLUS);
QVERIFY(bar->type_name);
QVERIFY(bar->selector);
QVERIFY(bar->selector->selector_argument_list);
QVERIFY(bar->selector->selector_argument_list->value);
QVERIFY(!bar->selector->selector_argument_list->next);
QCOMPARE(unit->spell(bar->selector->selector_argument_list->value->name_token), "bar");
QVERIFY(bar->attribute_list);
QVERIFY(bar->attribute_list->value);
QVERIFY(! (bar->attribute_list->next));
GnuAttributeSpecifierAST *unavailableSpec = bar->attribute_list->value->asGnuAttributeSpecifier();
QVERIFY(unavailableSpec);
QCOMPARE(unit->tokenKind(unavailableSpec->attribute_token), T___ATTRIBUTE__);
QVERIFY(unavailableSpec->attribute_list);
QVERIFY(unavailableSpec->attribute_list->value);
QVERIFY(! (unavailableSpec->attribute_list->next));
GnuAttributeAST *unavailableAttr = unavailableSpec->attribute_list->value->asGnuAttribute();
QVERIFY(unavailableAttr);
QVERIFY(! unavailableAttr->expression_list);
QCOMPARE(unit->spell(unavailableAttr->identifier_token), "unavailable");
}
/*
@selector(foo)
@selector(foo:)
@selector(foo:bar:)
...
*/
void tst_AST::objc_selector_error_recovery_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"void tst() {\n"
" @selector(foo:\n"
" int i = 1;\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_selector_error_recovery_2()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"void tst() {\n"
" @selector(foo:bar);\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
}
void tst_AST::objc_try_statement_1()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"\n"
"void tst() {\n"
" @try {\n"
" something();\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::objc_try_statement_2()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"void tst() {\n"
" @try {\n"
" something();\n"
" } @catch (NSException *e) {\n"
" another_thing();\n"
" } @catch (UIException *e) { \n"
" one_more_thing();\n"
" } @finally {\n"
" nothing();\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::objc_try_statement_3()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"void tst() {\n"
" @try {\n"
" get_banana();\n"
" } @catch (...) {\n"
" printf(\"Oek?\");\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::objc_throw_statement()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"void tst() {\n"
" NSException *up = [NSException exceptionWithName:@\"NoException\"\n"
" reason:@\"No Reason :-)\"\n"
" userInfo:nil];\n"
" @throw up;\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::normal_array_access()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"int f() {\n"
" int a[10];\n"
" int b = 1;\n"
" return a[b];\n"
"}"
));
AST *ast = unit->ast();
QVERIFY(ast);
FunctionDefinitionAST *func = ast->asFunctionDefinition();
QVERIFY(func);
StatementListAST *bodyStatements = func->function_body->asCompoundStatement()->statement_list;
QVERIFY(bodyStatements);
QVERIFY(bodyStatements->next);
QVERIFY(bodyStatements->next->next);
QVERIFY(bodyStatements->next->next->value);
ExpressionAST *expr = bodyStatements->next->next->value->asReturnStatement()->expression;
QVERIFY(expr);
ArrayAccessAST *arrayExpr = expr->asArrayAccess();
QVERIFY(arrayExpr);
{ // check the left-hand side:
ExpressionAST *lhs = arrayExpr->base_expression;
QVERIFY(lhs);
SimpleNameAST *a = lhs->asIdExpression()->name->asSimpleName();
QVERIFY(a);
QCOMPARE(QLatin1String(unit->identifier(a->identifier_token)->chars()), QLatin1String("a"));
}
{ // check the right-hand side:
QVERIFY(arrayExpr->expression);
SimpleNameAST *b = arrayExpr->expression->asIdExpression()->name->asSimpleName();
QVERIFY(b);
QCOMPARE(QLatin1String(unit->identifier(b->identifier_token)->chars()), QLatin1String("b"));
}
}
void tst_AST::array_access_with_nested_expression()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"int f() {\n"
" int a[15];\n"
" int b = 1;\n"
" return (a)[b];\n"
"}"
));
AST *ast = unit->ast();
QVERIFY(ast);
FunctionDefinitionAST *func = ast->asFunctionDefinition();
QVERIFY(func);
StatementListAST *bodyStatements = func->function_body->asCompoundStatement()->statement_list;
QVERIFY(bodyStatements && bodyStatements->next && bodyStatements->next->next && bodyStatements->next->next->value);
ExpressionAST *expr = bodyStatements->next->next->value->asReturnStatement()->expression;
QVERIFY(expr);
CastExpressionAST *castExpr = expr->asCastExpression();
QVERIFY(!castExpr);
ArrayAccessAST *arrayExpr = expr->asArrayAccess();
QVERIFY(arrayExpr);
{ // check the LHS:
ExpressionAST *lhs = arrayExpr->base_expression;
QVERIFY(lhs);
NestedExpressionAST *nested_a = lhs->asNestedExpression();
QVERIFY(nested_a && nested_a->expression);
SimpleNameAST *a = nested_a->expression->asIdExpression()->name->asSimpleName();
QVERIFY(a);
QCOMPARE(QLatin1String(unit->identifier(a->identifier_token)->chars()), QLatin1String("a"));
}
{ // check the RHS:
QVERIFY(arrayExpr->expression);
SimpleNameAST *b = arrayExpr->expression->asIdExpression()->name->asSimpleName();
QVERIFY(b);
QCOMPARE(QLatin1String(unit->identifier(b->identifier_token)->chars()), QLatin1String("b"));
}
}
void tst_AST::objc_msg_send_expression()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"int f() {\n"
" NSObject *obj = [[[NSObject alloc] init] autorelease];\n"
" return [obj description];\n"
"}"
));
AST *ast = unit->ast();
QVERIFY(ast);
FunctionDefinitionAST *func = ast->asFunctionDefinition();
QVERIFY(func);
StatementListAST *bodyStatements = func->function_body->asCompoundStatement()->statement_list;
QVERIFY(bodyStatements && bodyStatements->next && !bodyStatements->next->next && bodyStatements->next->value);
{// check the NSObject declaration
DeclarationStatementAST *firstStatement = bodyStatements->value->asDeclarationStatement();
QVERIFY(firstStatement);
DeclarationAST *objDecl = firstStatement->declaration;
QVERIFY(objDecl);
SimpleDeclarationAST *simpleDecl = objDecl->asSimpleDeclaration();
QVERIFY(simpleDecl);
{// check the type (NSObject)
QVERIFY(simpleDecl->decl_specifier_list && !simpleDecl->decl_specifier_list->next);
NamedTypeSpecifierAST *namedType = simpleDecl->decl_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(namedType && namedType->name);
SimpleNameAST *typeName = namedType->name->asSimpleName();
QVERIFY(typeName);
QCOMPARE(QLatin1String(unit->identifier(typeName->identifier_token)->chars()), QLatin1String("NSObject"));
}
{// check the assignment
QVERIFY(simpleDecl->declarator_list && !simpleDecl->declarator_list->next);
DeclaratorAST *declarator = simpleDecl->declarator_list->value;
QVERIFY(declarator);
QVERIFY(!declarator->attribute_list);
QVERIFY(declarator->ptr_operator_list && !declarator->ptr_operator_list->next
&& declarator->ptr_operator_list->value->asPointer()
&& ! declarator->ptr_operator_list->value->asPointer()->cv_qualifier_list);
QVERIFY(declarator->core_declarator && declarator->core_declarator->asDeclaratorId());
NameAST *objNameId = declarator->core_declarator->asDeclaratorId()->name;
QVERIFY(objNameId && objNameId->asSimpleName());
QCOMPARE(QLatin1String(unit->identifier(objNameId->asSimpleName()->identifier_token)->chars()), QLatin1String("obj"));
QVERIFY(!declarator->postfix_declarator_list);
QVERIFY(!declarator->post_attribute_list);
ExpressionAST *initializer = declarator->initializer;
QVERIFY(initializer);
ObjCMessageExpressionAST *expr1 = initializer->asObjCMessageExpression();
QVERIFY(expr1 && expr1->receiver_expression && expr1->selector && !expr1->argument_list);
ObjCMessageExpressionAST *expr2 = expr1->receiver_expression->asObjCMessageExpression();
QVERIFY(expr2 && expr2->receiver_expression && expr2->selector && !expr2->argument_list);
ObjCMessageExpressionAST *expr3 = expr2->receiver_expression->asObjCMessageExpression();
QVERIFY(expr3 && expr3->receiver_expression && expr3->selector && !expr3->argument_list);
}
}
{// check the return statement
ExpressionAST *expr = bodyStatements->next->value->asReturnStatement()->expression;
QVERIFY(expr);
ObjCMessageExpressionAST *msgExpr = expr->asObjCMessageExpression();
QVERIFY(msgExpr);
QVERIFY(msgExpr->receiver_expression);
SimpleNameAST *receiver = msgExpr->receiver_expression->asIdExpression()->name->asSimpleName();
QVERIFY(receiver);
QCOMPARE(QLatin1String(unit->identifier(receiver->identifier_token)->chars()), QLatin1String("obj"));
QVERIFY(msgExpr->argument_list == 0);
QVERIFY(msgExpr->selector);
ObjCSelectorArgumentListAST *args = msgExpr->selector->selector_argument_list;
QVERIFY(args);
QVERIFY(args->value);
QVERIFY(! args->next);
QCOMPARE(QLatin1String(unit->identifier(args->value->name_token)->chars()), QLatin1String("description"));
}
}
void tst_AST::objc_msg_send_expression_without_selector()
{
// This test is to verify that no ObjCMessageExpressionAST element is created as the expression for the return statement.
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"int f() {\n"
" NSObject *obj = [[[NSObject alloc] init] autorelease];\n"
" return [obj];\n"
"}",
true));
AST *ast = unit->ast();
QVERIFY(ast);
FunctionDefinitionAST *func = ast->asFunctionDefinition();
QVERIFY(func);
StatementListAST *bodyStatements = func->function_body->asCompoundStatement()->statement_list;
QVERIFY(bodyStatements && bodyStatements->next);
QVERIFY(bodyStatements->next->value);
QVERIFY(bodyStatements->next->value->asReturnStatement());
QVERIFY(!bodyStatements->next->value->asReturnStatement()->expression);
}
void tst_AST::q_enum_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"class Tst {\n"
"Q_ENUMS(e)\n"
"public:\n"
"enum e { x, y };\n"
"};\n",
false, true));
QVERIFY(unit->ast());
SimpleDeclarationAST *tstDecl = unit->ast()->asSimpleDeclaration();
QVERIFY(tstDecl);
QVERIFY(! tstDecl->declarator_list);
QVERIFY(tstDecl->decl_specifier_list);
QVERIFY(tstDecl->decl_specifier_list->value);
QVERIFY(! tstDecl->decl_specifier_list->next);
ClassSpecifierAST *tst = tstDecl->decl_specifier_list->value->asClassSpecifier();
QVERIFY(tst);
QVERIFY(tst->member_specifier_list);
QVERIFY(tst->member_specifier_list->value);
QtEnumDeclarationAST *qtEnum = tst->member_specifier_list->value->asQtEnumDeclaration();
QVERIFY(qtEnum);
QVERIFY(qtEnum->enumerator_list);
QVERIFY(qtEnum->enumerator_list->value);
QVERIFY(! qtEnum->enumerator_list->next);
SimpleNameAST *e = qtEnum->enumerator_list->value->asSimpleName();
QVERIFY(e);
QCOMPARE(unit->spell(e->identifier_token), "e");
}
void tst_AST::declarationWithNewStatement()
{
QFETCH(QByteArray, source);
QSharedPointer<TranslationUnit> unit(parseStatement(source, true));
AST *ast = unit->ast();
QVERIFY(ast);
QVERIFY(ast->asDeclarationStatement());
}
void tst_AST::declarationWithNewStatement_data()
{
QTest::addColumn<QByteArray>("source");
typedef QByteArray _;
QTest::newRow("withoutParentheses") << _("Foo *foo = new Foo;");
QTest::newRow("withParentheses") << _("Foo *foo = new Foo();");
QTest::newRow("withParenthesesAndOneArgument") << _("Foo *foo = new Foo(1);");
}
void tst_AST::incomplete_ast()
{
QSharedPointer<TranslationUnit> unit(parseStatement("class A { virtual void a() =\n"));
AST *ast = unit->ast();
QVERIFY(ast);
}
static ClassSpecifierAST *classSpecifierInSimpleDeclaration(SimpleDeclarationAST *simpleDeclaration)
{
Q_ASSERT(simpleDeclaration);
SpecifierListAST *specifier = simpleDeclaration->decl_specifier_list;
Q_ASSERT(specifier);
Q_ASSERT(specifier->value);
return specifier->value->asClassSpecifier();
}
void tst_AST::unnamed_class()
{
QFETCH(QByteArray, source);
QVERIFY(!source.isEmpty());
QSharedPointer<TranslationUnit> unit(parseDeclaration(source));
QVERIFY(unit->ast());
SimpleDeclarationAST *simpleDeclaration = unit->ast()->asSimpleDeclaration();
QVERIFY(simpleDeclaration);
ClassSpecifierAST *clazz = classSpecifierInSimpleDeclaration(simpleDeclaration);
QVERIFY(clazz);
QVERIFY(clazz->name);
QVERIFY(clazz->name->asAnonymousName());
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::unnamed_class_data()
{
QTest::addColumn<QByteArray>("source");
typedef QByteArray _;
QTest::newRow("unnamed-only") << _("class {};");
QTest::newRow("unnamed-derived") << _("class : B {};");
QTest::newRow("unnamed-__attribute__") << _("class __attribute__((aligned(8))){};");
}
void tst_AST::expensiveExpression()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"void f()\n"
"{\n"
"(g1\n"
"(g2\n"
"(g3\n"
"(g4\n"
"(g5\n"
"(g6\n"
"(g7\n"
"(g8\n"
"(g9\n"
"(g10\n"
"(g11\n"
"(g12\n"
"(g13\n"
"(g14\n"
"(g15\n"
"(g16\n"
"(g17\n"
"(g18\n"
"(g19\n"
"(g20\n"
"(g21\n"
"(g22\n"
"(g23\n"
"(g24\n"
"(g25\n"
"(g26\n"
"(g27\n"
"(g28\n"
"(g29\n"
"(g30\n"
"(g31(0))))))))))))))))))))))))))))))));\n"
"}\n"));
QVERIFY(unit->ast());
}
void tst_AST::invalidCode()
{
const QByteArray invalidCode = "static inValidLine()\n"
"class Foo {};\n";
QSharedPointer<TranslationUnit> unit(parse(invalidCode, TranslationUnit::ParseTranlationUnit,
false, false, false, 1000));
QVERIFY(unit->ast());
TranslationUnitAST *unitAST = unit->ast()->asTranslationUnit();
QVERIFY(unitAST->declaration_list);
QVERIFY(unitAST->declaration_list->value);
SimpleDeclarationAST *simpleDecl = unitAST->declaration_list->value->asSimpleDeclaration();
QVERIFY(simpleDecl);
QVERIFY(simpleDecl->decl_specifier_list);
QVERIFY(simpleDecl->decl_specifier_list->value);
ClassSpecifierAST *classSpecifier = simpleDecl->decl_specifier_list->value->asClassSpecifier();
QVERIFY(classSpecifier);
QVERIFY(diag.errorCount != 0);
}
void tst_AST::initTestCase()
{
control.setDiagnosticClient(&diag);
}
void tst_AST::cleanup()
{
diag.errorCount = 0;
}
void tst_AST::line_and_column_1()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
"int i;\n",
false, true));
unsigned line, column = 0;
QVERIFY(unit->ast());
QVERIFY(unit->tokenAt(1).is(T_INT));
unit->getTokenPosition(1, &line, &column);
QEXPECT_FAIL("", "See QTCREATORBUG-9799.", Continue);
QCOMPARE(line, 2U);
QCOMPARE(column, 1U);
}
QTEST_APPLESS_MAIN(tst_AST)
#include "tst_ast.moc"