diff --git a/src/tools/cplusplus/generate-ast.cpp b/src/tools/cplusplus/generate-ast.cpp
index e9a50d219df74ff04b7e7da52668ab38268ffc99..bbde757934c7d611031def385aa2985766f68e12 100644
--- a/src/tools/cplusplus/generate-ast.cpp
+++ b/src/tools/cplusplus/generate-ast.cpp
@@ -735,6 +735,138 @@ protected:
     }
 };
 
+class GenerateDumpers: protected ASTVisitor
+{
+    QTextStream out;
+
+public:
+    GenerateDumpers(QFile *file, TranslationUnit *unit)
+        : ASTVisitor(unit), out(file)
+    { }
+
+    static void go(const QString &fileName, TranslationUnit *unit)
+    {
+        QFile file(fileName);
+        if (! file.open(QFile::WriteOnly)) {
+            std::cerr << "Cannot open dumpers file." << std::endl;
+            return;
+        }
+
+        GenerateDumpers d(&file, unit);
+        d.out << copyrightHeader
+                << generatedHeader
+                << endl;
+
+
+        d.accept(unit->ast());
+
+        file.close();
+    }
+
+protected:
+    using ASTVisitor::visit;
+
+    QMap<QByteArray, ClassSpecifierAST *> classMap;
+
+    QByteArray id_cast(NameAST *name)
+    {
+        if (! name)
+            return QByteArray();
+
+        const Identifier *id = identifier(name->asSimpleName()->identifier_token);
+
+        return QByteArray::fromRawData(id->chars(), id->size());
+    }
+
+    void visitMembers(Class *klass)
+    {
+        for (unsigned i = 0; i < klass->memberCount(); ++i) {
+            Symbol *member = klass->memberAt(i);
+            if (! member->name())
+                continue;
+
+            const Identifier *id = member->name()->identifier();
+
+            if (! id)
+                continue;
+
+            const QByteArray memberName = QByteArray::fromRawData(id->chars(), id->size());
+            if (member->type().isUnsigned() && memberName.endsWith("_token")) {
+                out << "    if (ast->" << memberName << ")" << endl;
+                out << "        terminal(ast->" << memberName << ", ast);" << endl;
+            } else if (PointerType *ptrTy = member->type()->asPointerType()) {
+                if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
+                    QByteArray typeName = namedTy->name()->identifier()->chars();
+
+                    if (typeName.endsWith("ListAST")) {
+                        out << "    for (" << typeName << " *iter = ast->" << memberName << "; iter; iter = iter->next)" << endl
+                            << "        nonterminal(iter->value);" << endl;
+                    } else if (typeName.endsWith("AST")) {
+                        out << "    nonterminal(ast->" << memberName << ");" << endl;
+                    }
+                }
+            }
+        }
+
+        for (unsigned i = 0; i < klass->baseClassCount(); ++i) {
+            const QByteArray baseClassName = klass->baseClassAt(i)->identifier()->chars();
+
+            if (ClassSpecifierAST *baseClassSpec = classMap.value(baseClassName, 0)) {
+                visitMembers(baseClassSpec->symbol);
+            }
+        }
+    }
+
+    bool checkMethod(Symbol *cloneMethod) const
+    {
+        Declaration *decl = cloneMethod->asDeclaration();
+        if (! decl)
+            return false;
+
+        Function *funTy = decl->type()->asFunctionType();
+        if (! funTy)
+            return false;
+
+        else if (funTy->isPureVirtual())
+            return false;
+
+        return true;
+    }
+
+    virtual bool visit(ClassSpecifierAST *ast)
+    {
+        Class *klass = ast->symbol;
+        const QByteArray className = id_cast(ast->name);
+        if (! className.endsWith("AST"))
+            return false;
+
+        const Identifier *clone_id = control()->findOrInsertIdentifier("clone");
+        Symbol *cloneMethod = klass->members()->lookat(clone_id);
+        for (; cloneMethod; cloneMethod = cloneMethod->next()) {
+            if (cloneMethod->identifier() != clone_id)
+                continue;
+
+            if (checkMethod(cloneMethod))
+                break;
+        }
+
+        if (! cloneMethod)
+            return true;
+
+        classMap.insert(className, ast);
+
+        out << "virtual bool visit(" << className.constData() << " *ast)" << endl
+            << "{" << endl;
+
+        visitMembers(klass);
+
+        out << "    return false;" << endl
+            << "}" << endl << endl;
+
+        return false;
+    }
+};
+
 class RemoveCastMethods: protected ASTVisitor
 {
 public:
@@ -1093,7 +1225,7 @@ void generateAST_cpp(const Snapshot &snapshot, const QDir &cplusplusDir)
     }
 }
 
-QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
+QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, const QString &dumpersFile)
 {
     QStringList astDerivedClasses;
 
@@ -1193,6 +1325,9 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir)
 
     generateAST_cpp(snapshot, cplusplusDir);
 
+    if (!dumpersFile.isEmpty())
+        GenerateDumpers::go(dumpersFile, AST_h_document->translationUnit());
+
     return astDerivedClasses;
 }
 
@@ -1393,8 +1528,9 @@ int main(int argc, char *argv[])
     QStringList files = app.arguments();
     files.removeFirst();
 
-    if (files.isEmpty()) {
+    if (files.size() != 1 && files.size() != 2) {
         std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl;
+        std::cerr << "   or: cplusplus [path to C++ front-end] [dumpers file name]" << std::endl;
         return EXIT_FAILURE;
     }
 
@@ -1405,8 +1541,12 @@ int main(int argc, char *argv[])
         return EXIT_FAILURE;
     }
 
+    QString dumpersFile;
+    if (files.size() == 2)
+        dumpersFile = files.last();
+
     Snapshot snapshot;
-    QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir);
+    QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, dumpersFile);
     astDerivedClasses.sort();
     generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
 
diff --git a/tests/manual/cplusplus-dump/dumpers.inc b/tests/manual/cplusplus-dump/dumpers.inc
new file mode 100644
index 0000000000000000000000000000000000000000..8e414f5f830a5a6fdfd804c22c490a6eb13ccfe5
--- /dev/null
+++ b/tests/manual/cplusplus-dump/dumpers.inc
@@ -0,0 +1,1607 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is automatically generated.
+// Changes will be lost.
+//
+
+
+virtual bool visit(ObjCSelectorArgumentAST *ast)
+{
+    if (ast->name_token)
+        terminal(ast->name_token, ast);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCSelectorAST *ast)
+{
+    for (ObjCSelectorArgumentListAST *iter = ast->selector_argument_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(SimpleSpecifierAST *ast)
+{
+    if (ast->specifier_token)
+        terminal(ast->specifier_token, ast);
+    return false;
+}
+
+virtual bool visit(AttributeSpecifierAST *ast)
+{
+    if (ast->attribute_token)
+        terminal(ast->attribute_token, ast);
+    if (ast->first_lparen_token)
+        terminal(ast->first_lparen_token, ast);
+    if (ast->second_lparen_token)
+        terminal(ast->second_lparen_token, ast);
+    for (AttributeListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->first_rparen_token)
+        terminal(ast->first_rparen_token, ast);
+    if (ast->second_rparen_token)
+        terminal(ast->second_rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(AttributeAST *ast)
+{
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->tag_token)
+        terminal(ast->tag_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(TypeofSpecifierAST *ast)
+{
+    if (ast->typeof_token)
+        terminal(ast->typeof_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(DeclaratorAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->core_declarator);
+    for (PostfixDeclaratorListAST *iter = ast->postfix_declarator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (SpecifierListAST *iter = ast->post_attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->equals_token)
+        terminal(ast->equals_token, ast);
+    nonterminal(ast->initializer);
+    return false;
+}
+
+virtual bool visit(SimpleDeclarationAST *ast)
+{
+    if (ast->qt_invokable_token)
+        terminal(ast->qt_invokable_token, ast);
+    for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (DeclaratorListAST *iter = ast->declarator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(EmptyDeclarationAST *ast)
+{
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(AccessDeclarationAST *ast)
+{
+    if (ast->access_specifier_token)
+        terminal(ast->access_specifier_token, ast);
+    if (ast->slots_token)
+        terminal(ast->slots_token, ast);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    return false;
+}
+
+virtual bool visit(QtObjectTagAST *ast)
+{
+    if (ast->q_object_token)
+        terminal(ast->q_object_token, ast);
+    return false;
+}
+
+virtual bool visit(QtPrivateSlotAST *ast)
+{
+    if (ast->q_private_slot_token)
+        terminal(ast->q_private_slot_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->dptr_token)
+        terminal(ast->dptr_token, ast);
+    if (ast->dptr_lparen_token)
+        terminal(ast->dptr_lparen_token, ast);
+    if (ast->dptr_rparen_token)
+        terminal(ast->dptr_rparen_token, ast);
+    if (ast->comma_token)
+        terminal(ast->comma_token, ast);
+    for (SpecifierListAST *iter = ast->type_specifiers; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(QtPropertyDeclarationItemAST *ast)
+{
+    if (ast->item_name_token)
+        terminal(ast->item_name_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(QtPropertyDeclarationAST *ast)
+{
+    if (ast->property_specifier_token)
+        terminal(ast->property_specifier_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->type_id);
+    nonterminal(ast->property_name);
+    for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_items; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(QtEnumDeclarationAST *ast)
+{
+    if (ast->enum_specifier_token)
+        terminal(ast->enum_specifier_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(QtFlagsDeclarationAST *ast)
+{
+    if (ast->flags_specifier_token)
+        terminal(ast->flags_specifier_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (NameListAST *iter = ast->flag_enums_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(QtInterfaceNameAST *ast)
+{
+    nonterminal(ast->interface_name);
+    for (NameListAST *iter = ast->constraint_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(QtInterfacesDeclarationAST *ast)
+{
+    if (ast->interfaces_token)
+        terminal(ast->interfaces_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (QtInterfaceNameListAST *iter = ast->interface_name_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(AsmDefinitionAST *ast)
+{
+    if (ast->asm_token)
+        terminal(ast->asm_token, ast);
+    if (ast->volatile_token)
+        terminal(ast->volatile_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(BaseSpecifierAST *ast)
+{
+    if (ast->virtual_token)
+        terminal(ast->virtual_token, ast);
+    if (ast->access_specifier_token)
+        terminal(ast->access_specifier_token, ast);
+    nonterminal(ast->name);
+    return false;
+}
+
+virtual bool visit(CompoundExpressionAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->statement);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(CompoundLiteralAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->initializer);
+    return false;
+}
+
+virtual bool visit(QtMethodAST *ast)
+{
+    if (ast->method_token)
+        terminal(ast->method_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->declarator);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(QtMemberDeclarationAST *ast)
+{
+    if (ast->q_token)
+        terminal(ast->q_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(BinaryExpressionAST *ast)
+{
+    nonterminal(ast->left_expression);
+    if (ast->binary_op_token)
+        terminal(ast->binary_op_token, ast);
+    nonterminal(ast->right_expression);
+    return false;
+}
+
+virtual bool visit(CastExpressionAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(ClassSpecifierAST *ast)
+{
+    if (ast->classkey_token)
+        terminal(ast->classkey_token, ast);
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->name);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    for (BaseSpecifierListAST *iter = ast->base_clause_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (DeclarationListAST *iter = ast->member_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(CaseStatementAST *ast)
+{
+    if (ast->case_token)
+        terminal(ast->case_token, ast);
+    nonterminal(ast->expression);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(CompoundStatementAST *ast)
+{
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (StatementListAST *iter = ast->statement_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(ConditionAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    return false;
+}
+
+virtual bool visit(ConditionalExpressionAST *ast)
+{
+    nonterminal(ast->condition);
+    if (ast->question_token)
+        terminal(ast->question_token, ast);
+    nonterminal(ast->left_expression);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    nonterminal(ast->right_expression);
+    return false;
+}
+
+virtual bool visit(CppCastExpressionAST *ast)
+{
+    if (ast->cast_token)
+        terminal(ast->cast_token, ast);
+    if (ast->less_token)
+        terminal(ast->less_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->greater_token)
+        terminal(ast->greater_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(CtorInitializerAST *ast)
+{
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    for (MemInitializerListAST *iter = ast->member_initializer_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    return false;
+}
+
+virtual bool visit(DeclarationStatementAST *ast)
+{
+    nonterminal(ast->declaration);
+    return false;
+}
+
+virtual bool visit(DeclaratorIdAST *ast)
+{
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    nonterminal(ast->name);
+    return false;
+}
+
+virtual bool visit(NestedDeclaratorAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->declarator);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(FunctionDeclaratorAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->parameters);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->exception_specification);
+    nonterminal(ast->trailing_return_type);
+    nonterminal(ast->as_cpp_initializer);
+    return false;
+}
+
+virtual bool visit(ArrayDeclaratorAST *ast)
+{
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    return false;
+}
+
+virtual bool visit(DeleteExpressionAST *ast)
+{
+    if (ast->scope_token)
+        terminal(ast->scope_token, ast);
+    if (ast->delete_token)
+        terminal(ast->delete_token, ast);
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(DoStatementAST *ast)
+{
+    if (ast->do_token)
+        terminal(ast->do_token, ast);
+    nonterminal(ast->statement);
+    if (ast->while_token)
+        terminal(ast->while_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(NamedTypeSpecifierAST *ast)
+{
+    nonterminal(ast->name);
+    return false;
+}
+
+virtual bool visit(ElaboratedTypeSpecifierAST *ast)
+{
+    if (ast->classkey_token)
+        terminal(ast->classkey_token, ast);
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->name);
+    return false;
+}
+
+virtual bool visit(EnumSpecifierAST *ast)
+{
+    if (ast->enum_token)
+        terminal(ast->enum_token, ast);
+    nonterminal(ast->name);
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (EnumeratorListAST *iter = ast->enumerator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(EnumeratorAST *ast)
+{
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    if (ast->equal_token)
+        terminal(ast->equal_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(ExceptionDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    return false;
+}
+
+virtual bool visit(ExceptionSpecificationAST *ast)
+{
+    if (ast->throw_token)
+        terminal(ast->throw_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    for (ExpressionListAST *iter = ast->type_id_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(ExpressionOrDeclarationStatementAST *ast)
+{
+    nonterminal(ast->expression);
+    nonterminal(ast->declaration);
+    return false;
+}
+
+virtual bool visit(ExpressionStatementAST *ast)
+{
+    nonterminal(ast->expression);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(FunctionDefinitionAST *ast)
+{
+    if (ast->qt_invokable_token)
+        terminal(ast->qt_invokable_token, ast);
+    for (SpecifierListAST *iter = ast->decl_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    nonterminal(ast->ctor_initializer);
+    nonterminal(ast->function_body);
+    return false;
+}
+
+virtual bool visit(ForeachStatementAST *ast)
+{
+    if (ast->foreach_token)
+        terminal(ast->foreach_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    nonterminal(ast->initializer);
+    if (ast->comma_token)
+        terminal(ast->comma_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(ForStatementAST *ast)
+{
+    if (ast->for_token)
+        terminal(ast->for_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->initializer);
+    nonterminal(ast->condition);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(IfStatementAST *ast)
+{
+    if (ast->if_token)
+        terminal(ast->if_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->condition);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    if (ast->else_token)
+        terminal(ast->else_token, ast);
+    nonterminal(ast->else_statement);
+    return false;
+}
+
+virtual bool visit(ArrayInitializerAST *ast)
+{
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(LabeledStatementAST *ast)
+{
+    if (ast->label_token)
+        terminal(ast->label_token, ast);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(LinkageBodyAST *ast)
+{
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(LinkageSpecificationAST *ast)
+{
+    if (ast->extern_token)
+        terminal(ast->extern_token, ast);
+    if (ast->extern_type_token)
+        terminal(ast->extern_type_token, ast);
+    nonterminal(ast->declaration);
+    return false;
+}
+
+virtual bool visit(MemInitializerAST *ast)
+{
+    nonterminal(ast->name);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(NestedNameSpecifierAST *ast)
+{
+    nonterminal(ast->class_or_namespace_name);
+    if (ast->scope_token)
+        terminal(ast->scope_token, ast);
+    return false;
+}
+
+virtual bool visit(QualifiedNameAST *ast)
+{
+    if (ast->global_scope_token)
+        terminal(ast->global_scope_token, ast);
+    for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->unqualified_name);
+    return false;
+}
+
+virtual bool visit(OperatorFunctionIdAST *ast)
+{
+    if (ast->operator_token)
+        terminal(ast->operator_token, ast);
+    nonterminal(ast->op);
+    return false;
+}
+
+virtual bool visit(ConversionFunctionIdAST *ast)
+{
+    if (ast->operator_token)
+        terminal(ast->operator_token, ast);
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(SimpleNameAST *ast)
+{
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    return false;
+}
+
+virtual bool visit(DestructorNameAST *ast)
+{
+    if (ast->tilde_token)
+        terminal(ast->tilde_token, ast);
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    return false;
+}
+
+virtual bool visit(TemplateIdAST *ast)
+{
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    if (ast->less_token)
+        terminal(ast->less_token, ast);
+    for (TemplateArgumentListAST *iter = ast->template_argument_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->greater_token)
+        terminal(ast->greater_token, ast);
+    return false;
+}
+
+virtual bool visit(NamespaceAST *ast)
+{
+    if (ast->namespace_token)
+        terminal(ast->namespace_token, ast);
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->linkage_body);
+    return false;
+}
+
+virtual bool visit(NamespaceAliasDefinitionAST *ast)
+{
+    if (ast->namespace_token)
+        terminal(ast->namespace_token, ast);
+    if (ast->namespace_name_token)
+        terminal(ast->namespace_name_token, ast);
+    if (ast->equal_token)
+        terminal(ast->equal_token, ast);
+    nonterminal(ast->name);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(NewPlacementAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(NewArrayDeclaratorAST *ast)
+{
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    return false;
+}
+
+virtual bool visit(NewExpressionAST *ast)
+{
+    if (ast->scope_token)
+        terminal(ast->scope_token, ast);
+    if (ast->new_token)
+        terminal(ast->new_token, ast);
+    nonterminal(ast->new_placement);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->new_type_id);
+    nonterminal(ast->new_initializer);
+    return false;
+}
+
+virtual bool visit(NewInitializerAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(NewTypeIdAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (PtrOperatorListAST *iter = ast->ptr_operator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (NewArrayDeclaratorListAST *iter = ast->new_array_declarator_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(OperatorAST *ast)
+{
+    if (ast->op_token)
+        terminal(ast->op_token, ast);
+    if (ast->open_token)
+        terminal(ast->open_token, ast);
+    if (ast->close_token)
+        terminal(ast->close_token, ast);
+    return false;
+}
+
+virtual bool visit(ParameterDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    if (ast->equal_token)
+        terminal(ast->equal_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(ParameterDeclarationClauseAST *ast)
+{
+    for (DeclarationListAST *iter = ast->parameter_declaration_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    return false;
+}
+
+virtual bool visit(CallAST *ast)
+{
+    nonterminal(ast->base_expression);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(ArrayAccessAST *ast)
+{
+    nonterminal(ast->base_expression);
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    return false;
+}
+
+virtual bool visit(PostIncrDecrAST *ast)
+{
+    nonterminal(ast->base_expression);
+    if (ast->incr_decr_token)
+        terminal(ast->incr_decr_token, ast);
+    return false;
+}
+
+virtual bool visit(MemberAccessAST *ast)
+{
+    nonterminal(ast->base_expression);
+    if (ast->access_token)
+        terminal(ast->access_token, ast);
+    if (ast->template_token)
+        terminal(ast->template_token, ast);
+    nonterminal(ast->member_name);
+    return false;
+}
+
+virtual bool visit(TypeidExpressionAST *ast)
+{
+    if (ast->typeid_token)
+        terminal(ast->typeid_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(TypenameCallExpressionAST *ast)
+{
+    if (ast->typename_token)
+        terminal(ast->typename_token, ast);
+    nonterminal(ast->name);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(TypeConstructorCallAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(PointerToMemberAST *ast)
+{
+    if (ast->global_scope_token)
+        terminal(ast->global_scope_token, ast);
+    for (NestedNameSpecifierListAST *iter = ast->nested_name_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->star_token)
+        terminal(ast->star_token, ast);
+    for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(PointerAST *ast)
+{
+    if (ast->star_token)
+        terminal(ast->star_token, ast);
+    for (SpecifierListAST *iter = ast->cv_qualifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(ReferenceAST *ast)
+{
+    if (ast->reference_token)
+        terminal(ast->reference_token, ast);
+    return false;
+}
+
+virtual bool visit(BreakStatementAST *ast)
+{
+    if (ast->break_token)
+        terminal(ast->break_token, ast);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ContinueStatementAST *ast)
+{
+    if (ast->continue_token)
+        terminal(ast->continue_token, ast);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(GotoStatementAST *ast)
+{
+    if (ast->goto_token)
+        terminal(ast->goto_token, ast);
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ReturnStatementAST *ast)
+{
+    if (ast->return_token)
+        terminal(ast->return_token, ast);
+    nonterminal(ast->expression);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(SizeofExpressionAST *ast)
+{
+    if (ast->sizeof_token)
+        terminal(ast->sizeof_token, ast);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(NumericLiteralAST *ast)
+{
+    if (ast->literal_token)
+        terminal(ast->literal_token, ast);
+    return false;
+}
+
+virtual bool visit(BoolLiteralAST *ast)
+{
+    if (ast->literal_token)
+        terminal(ast->literal_token, ast);
+    return false;
+}
+
+virtual bool visit(ThisExpressionAST *ast)
+{
+    if (ast->this_token)
+        terminal(ast->this_token, ast);
+    return false;
+}
+
+virtual bool visit(NestedExpressionAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(StringLiteralAST *ast)
+{
+    if (ast->literal_token)
+        terminal(ast->literal_token, ast);
+    nonterminal(ast->next);
+    return false;
+}
+
+virtual bool visit(SwitchStatementAST *ast)
+{
+    if (ast->switch_token)
+        terminal(ast->switch_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->condition);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(TemplateDeclarationAST *ast)
+{
+    if (ast->export_token)
+        terminal(ast->export_token, ast);
+    if (ast->template_token)
+        terminal(ast->template_token, ast);
+    if (ast->less_token)
+        terminal(ast->less_token, ast);
+    for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->greater_token)
+        terminal(ast->greater_token, ast);
+    nonterminal(ast->declaration);
+    return false;
+}
+
+virtual bool visit(ThrowExpressionAST *ast)
+{
+    if (ast->throw_token)
+        terminal(ast->throw_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(TranslationUnitAST *ast)
+{
+    for (DeclarationListAST *iter = ast->declaration_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(TryBlockStatementAST *ast)
+{
+    if (ast->try_token)
+        terminal(ast->try_token, ast);
+    nonterminal(ast->statement);
+    for (CatchClauseListAST *iter = ast->catch_clause_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(CatchClauseAST *ast)
+{
+    if (ast->catch_token)
+        terminal(ast->catch_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->exception_declaration);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(TypeIdAST *ast)
+{
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    return false;
+}
+
+virtual bool visit(TypenameTypeParameterAST *ast)
+{
+    if (ast->classkey_token)
+        terminal(ast->classkey_token, ast);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    nonterminal(ast->name);
+    if (ast->equal_token)
+        terminal(ast->equal_token, ast);
+    nonterminal(ast->type_id);
+    return false;
+}
+
+virtual bool visit(TemplateTypeParameterAST *ast)
+{
+    if (ast->template_token)
+        terminal(ast->template_token, ast);
+    if (ast->less_token)
+        terminal(ast->less_token, ast);
+    for (DeclarationListAST *iter = ast->template_parameter_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->greater_token)
+        terminal(ast->greater_token, ast);
+    if (ast->class_token)
+        terminal(ast->class_token, ast);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    nonterminal(ast->name);
+    if (ast->equal_token)
+        terminal(ast->equal_token, ast);
+    nonterminal(ast->type_id);
+    return false;
+}
+
+virtual bool visit(UnaryExpressionAST *ast)
+{
+    if (ast->unary_op_token)
+        terminal(ast->unary_op_token, ast);
+    nonterminal(ast->expression);
+    return false;
+}
+
+virtual bool visit(UsingAST *ast)
+{
+    if (ast->using_token)
+        terminal(ast->using_token, ast);
+    if (ast->typename_token)
+        terminal(ast->typename_token, ast);
+    nonterminal(ast->name);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(UsingDirectiveAST *ast)
+{
+    if (ast->using_token)
+        terminal(ast->using_token, ast);
+    if (ast->namespace_token)
+        terminal(ast->namespace_token, ast);
+    nonterminal(ast->name);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(WhileStatementAST *ast)
+{
+    if (ast->while_token)
+        terminal(ast->while_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->condition);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(ObjCClassForwardDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->class_token)
+        terminal(ast->class_token, ast);
+    for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCClassDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->interface_token)
+        terminal(ast->interface_token, ast);
+    if (ast->implementation_token)
+        terminal(ast->implementation_token, ast);
+    nonterminal(ast->class_name);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->category_name);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    if (ast->colon_token)
+        terminal(ast->colon_token, ast);
+    nonterminal(ast->superclass);
+    nonterminal(ast->protocol_refs);
+    nonterminal(ast->inst_vars_decl);
+    for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->end_token)
+        terminal(ast->end_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCProtocolForwardDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->protocol_token)
+        terminal(ast->protocol_token, ast);
+    for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCProtocolDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->protocol_token)
+        terminal(ast->protocol_token, ast);
+    nonterminal(ast->name);
+    nonterminal(ast->protocol_refs);
+    for (DeclarationListAST *iter = ast->member_declaration_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->end_token)
+        terminal(ast->end_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCProtocolRefsAST *ast)
+{
+    if (ast->less_token)
+        terminal(ast->less_token, ast);
+    for (NameListAST *iter = ast->identifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->greater_token)
+        terminal(ast->greater_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCMessageArgumentAST *ast)
+{
+    nonterminal(ast->parameter_value_expression);
+    return false;
+}
+
+virtual bool visit(ObjCMessageExpressionAST *ast)
+{
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    nonterminal(ast->receiver_expression);
+    nonterminal(ast->selector);
+    for (ObjCMessageArgumentListAST *iter = ast->argument_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCProtocolExpressionAST *ast)
+{
+    if (ast->protocol_token)
+        terminal(ast->protocol_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->identifier_token)
+        terminal(ast->identifier_token, ast);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCTypeNameAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    if (ast->type_qualifier_token)
+        terminal(ast->type_qualifier_token, ast);
+    nonterminal(ast->type_id);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCEncodeExpressionAST *ast)
+{
+    if (ast->encode_token)
+        terminal(ast->encode_token, ast);
+    nonterminal(ast->type_name);
+    return false;
+}
+
+virtual bool visit(ObjCSelectorExpressionAST *ast)
+{
+    if (ast->selector_token)
+        terminal(ast->selector_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->selector);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCInstanceVariablesDeclarationAST *ast)
+{
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (DeclarationListAST *iter = ast->instance_variable_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCVisibilityDeclarationAST *ast)
+{
+    if (ast->visibility_token)
+        terminal(ast->visibility_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCPropertyAttributeAST *ast)
+{
+    if (ast->attribute_identifier_token)
+        terminal(ast->attribute_identifier_token, ast);
+    if (ast->equals_token)
+        terminal(ast->equals_token, ast);
+    nonterminal(ast->method_selector);
+    return false;
+}
+
+virtual bool visit(ObjCPropertyDeclarationAST *ast)
+{
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->property_token)
+        terminal(ast->property_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (ObjCPropertyAttributeListAST *iter = ast->property_attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->simple_declaration);
+    return false;
+}
+
+virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
+{
+    nonterminal(ast->type_name);
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->param_name);
+    return false;
+}
+
+virtual bool visit(ObjCMethodPrototypeAST *ast)
+{
+    if (ast->method_type_token)
+        terminal(ast->method_type_token, ast);
+    nonterminal(ast->type_name);
+    nonterminal(ast->selector);
+    for (ObjCMessageArgumentDeclarationListAST *iter = ast->argument_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->dot_dot_dot_token)
+        terminal(ast->dot_dot_dot_token, ast);
+    for (SpecifierListAST *iter = ast->attribute_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(ObjCMethodDeclarationAST *ast)
+{
+    nonterminal(ast->method_prototype);
+    nonterminal(ast->function_body);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCSynthesizedPropertyAST *ast)
+{
+    if (ast->property_identifier_token)
+        terminal(ast->property_identifier_token, ast);
+    if (ast->equals_token)
+        terminal(ast->equals_token, ast);
+    if (ast->alias_identifier_token)
+        terminal(ast->alias_identifier_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *ast)
+{
+    if (ast->synthesized_token)
+        terminal(ast->synthesized_token, ast);
+    for (ObjCSynthesizedPropertyListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCDynamicPropertiesDeclarationAST *ast)
+{
+    if (ast->dynamic_token)
+        terminal(ast->dynamic_token, ast);
+    for (NameListAST *iter = ast->property_identifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->semicolon_token)
+        terminal(ast->semicolon_token, ast);
+    return false;
+}
+
+virtual bool visit(ObjCFastEnumerationAST *ast)
+{
+    if (ast->for_token)
+        terminal(ast->for_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    for (SpecifierListAST *iter = ast->type_specifier_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    nonterminal(ast->initializer);
+    if (ast->in_token)
+        terminal(ast->in_token, ast);
+    nonterminal(ast->fast_enumeratable_expression);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(ObjCSynchronizedStatementAST *ast)
+{
+    if (ast->synchronized_token)
+        terminal(ast->synchronized_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->synchronized_object);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(LambdaExpressionAST *ast)
+{
+    nonterminal(ast->lambda_introducer);
+    nonterminal(ast->lambda_declarator);
+    nonterminal(ast->statement);
+    return false;
+}
+
+virtual bool visit(LambdaIntroducerAST *ast)
+{
+    if (ast->lbracket_token)
+        terminal(ast->lbracket_token, ast);
+    nonterminal(ast->lambda_capture);
+    if (ast->rbracket_token)
+        terminal(ast->rbracket_token, ast);
+    return false;
+}
+
+virtual bool visit(LambdaCaptureAST *ast)
+{
+    if (ast->default_capture_token)
+        terminal(ast->default_capture_token, ast);
+    for (CaptureListAST *iter = ast->capture_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    return false;
+}
+
+virtual bool visit(CaptureAST *ast)
+{
+    return false;
+}
+
+virtual bool visit(LambdaDeclaratorAST *ast)
+{
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->parameter_declaration_clause);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->mutable_token)
+        terminal(ast->mutable_token, ast);
+    nonterminal(ast->exception_specification);
+    nonterminal(ast->trailing_return_type);
+    return false;
+}
+
+virtual bool visit(TrailingReturnTypeAST *ast)
+{
+    if (ast->arrow_token)
+        terminal(ast->arrow_token, ast);
+    for (SpecifierListAST *iter = ast->attributes; iter; iter = iter->next)
+        nonterminal(iter->value);
+    for (SpecifierListAST *iter = ast->type_specifiers; iter; iter = iter->next)
+        nonterminal(iter->value);
+    nonterminal(ast->declarator);
+    return false;
+}
+
+virtual bool visit(BracedInitializerAST *ast)
+{
+    if (ast->lbrace_token)
+        terminal(ast->lbrace_token, ast);
+    for (ExpressionListAST *iter = ast->expression_list; iter; iter = iter->next)
+        nonterminal(iter->value);
+    if (ast->comma_token)
+        terminal(ast->comma_token, ast);
+    if (ast->rbrace_token)
+        terminal(ast->rbrace_token, ast);
+    return false;
+}
+
diff --git a/tests/manual/cplusplus-dump/main.cpp b/tests/manual/cplusplus-dump/main.cpp
index a87adfe364b4b090ed58da56e2c98b0a47ffe1cc..c45d1b4718a26c85fe709d86e7ee1b74ccce29ff 100644
--- a/tests/manual/cplusplus-dump/main.cpp
+++ b/tests/manual/cplusplus-dump/main.cpp
@@ -73,13 +73,14 @@ public:
         basename.append(".ast.dot");
         out.open(basename.constData());
 
-        out << "digraph AST {" << std::endl;
+        out << "digraph AST { ordering=out;" << std::endl;
         // std::cout << "rankdir = \"LR\";" << std::endl;
         accept(ast);
 
-        foreach (const QByteArray &terminalShape, _terminalShapes) {
-            out << std::string(terminalShape) << " [shape=rect]" << std::endl;
-        }
+        typedef QPair<QByteArray, QByteArray> Pair;
+
+        foreach (const Pair &conn, _connections)
+            out << conn.first.constData() << " -> " << conn.second.constData() << std::endl;
 
         alignTerminals();
 
@@ -88,6 +89,10 @@ public:
         std::cout << basename.constData() << std::endl;
     }
 
+    // the following file can be generated by using:
+    //    generate-ast <path to cpp stuff> <path to dumpers.inc>
+#include "dumpers.inc"
+
 protected:
     void alignTerminals() {
         out<<"{ rank=same;" << std::endl;
@@ -97,59 +102,47 @@ protected:
         out<<"}"<<std::endl;
     }
 
-    QByteArray addTerminalInfo(AST *ast) const {
-        if (SimpleNameAST *simpleName = ast->asSimpleName()) {
-            return spell(simpleName->identifier_token);
-        } else if (BinaryExpressionAST *binExpr = ast->asBinaryExpression()) {
-            return spell(binExpr->binary_op_token);
-        } else if (SimpleSpecifierAST *simpleSpec = ast->asSimpleSpecifier()) {
-            return spell(simpleSpec->specifier_token);
-        } else if (NumericLiteralAST *numLit = ast->asNumericLiteral()) {
-            return spell(numLit->literal_token);
-        } else if (StringLiteralAST *strLit = ast->asStringLiteral()) {
-            return spell(strLit->literal_token);
-        } else if (BoolLiteralAST *boolLit = ast->asBoolLiteral()) {
-            return spell(boolLit->literal_token);
-        } else if (ObjCSelectorArgumentAST *selArg = ast->asObjCSelectorArgument()) {
-            QByteArray t = spell(selArg->name_token);
-            if (selArg->colon_token)
-                t.append(spell(selArg->colon_token));
-            return t;
-        } else if (AttributeAST *attr = ast->asAttribute()) {
-            return spell(attr->identifier_token);
-        } else {
-            return QByteArray();
-        }
-    }
-
-    std::string name(AST *ast) {
+    static QByteArray name(AST *ast) {
         QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 11;
         name.truncate(name.length() - 3);
-        name = QByteArray::number(_id.value(ast)) + ". " + name;
 
-        QByteArray info = addTerminalInfo(ast);
-        if (!info.isEmpty()) {
-            name.append("\\n");
-            name.append(info);
-        }
-        name.prepend('"');
-        name.append('"');
+        return name;
+    }
+
+    void terminal(unsigned token, AST *node) {
+        static int count = 1;
+        QByteArray id = 't' + QByteArray::number(count++);
+        _connections.append(qMakePair(_id[node], id));
+
+        QByteArray t;
+        t.append(id);
+        t.append(" [label = \"");
+        t.append(spell(token));
+        t.append("\" shape=rect]");
+        _terminalShapes.append(t);
+    }
 
-        if (!info.isEmpty())
-            _terminalShapes.insert(name);
+    virtual void nonterminal(AST *ast) {
+        accept(ast);
+    }
 
-        return std::string(name);
+    virtual void node(AST *ast) {
+        out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << std::endl;
     }
 
     virtual bool preVisit(AST *ast) {
         static int count = 1;
-        _id[ast] = count++;
+        const QByteArray id = 'n' + QByteArray::number(count++);
+        _id[ast] = id;
+
 
         if (! _stack.isEmpty())
-            out << name(_stack.last()) << " -> " << name(ast) << ";" << std::endl;
+            _connections.append(qMakePair(_id[_stack.last()], id));
 
         _stack.append(ast);
 
+        node(ast);
+
         return true;
     }
 
@@ -158,9 +151,10 @@ protected:
     }
 
 private:
-    QHash<AST *, int> _id;
+    QHash<AST *, QByteArray> _id;
+    QList<QPair<QByteArray, QByteArray> > _connections;
     QList<AST *> _stack;
-    QSet<QByteArray> _terminalShapes;
+    QList<QByteArray> _terminalShapes;
     std::ofstream out;
 };
 
@@ -183,7 +177,7 @@ public:
         basename.append(".symbols.dot");
         out.open(basename.constData());
 
-        out << "digraph Symbols {" << std::endl;
+        out << "digraph Symbols { ordering=out;" << std::endl;
         // std::cout << "rankdir = \"LR\";" << std::endl;
         accept(s);