summaryrefslogtreecommitdiff
path: root/src/shared/cplusplus
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/cplusplus')
-rw-r--r--src/shared/cplusplus/AST.cpp3985
-rw-r--r--src/shared/cplusplus/AST.h1989
-rw-r--r--src/shared/cplusplus/ASTVisitor.cpp105
-rw-r--r--src/shared/cplusplus/ASTVisitor.h200
-rw-r--r--src/shared/cplusplus/ASTfwd.h178
-rw-r--r--src/shared/cplusplus/Array.cpp34
-rw-r--r--src/shared/cplusplus/Array.h135
-rw-r--r--src/shared/cplusplus/CPlusPlusForwardDeclarations.h140
-rw-r--r--src/shared/cplusplus/CheckDeclaration.cpp374
-rw-r--r--src/shared/cplusplus/CheckDeclaration.h106
-rw-r--r--src/shared/cplusplus/CheckDeclarator.cpp258
-rw-r--r--src/shared/cplusplus/CheckDeclarator.h110
-rw-r--r--src/shared/cplusplus/CheckExpression.cpp369
-rw-r--r--src/shared/cplusplus/CheckExpression.h127
-rw-r--r--src/shared/cplusplus/CheckName.cpp348
-rw-r--r--src/shared/cplusplus/CheckName.h92
-rw-r--r--src/shared/cplusplus/CheckSpecifier.cpp392
-rw-r--r--src/shared/cplusplus/CheckSpecifier.h95
-rw-r--r--src/shared/cplusplus/CheckStatement.cpp239
-rw-r--r--src/shared/cplusplus/CheckStatement.h102
-rw-r--r--src/shared/cplusplus/Control.cpp636
-rw-r--r--src/shared/cplusplus/Control.h180
-rw-r--r--src/shared/cplusplus/CoreTypes.cpp237
-rw-r--r--src/shared/cplusplus/CoreTypes.h217
-rw-r--r--src/shared/cplusplus/DiagnosticClient.cpp63
-rw-r--r--src/shared/cplusplus/DiagnosticClient.h86
-rw-r--r--src/shared/cplusplus/FullySpecifiedType.cpp204
-rw-r--r--src/shared/cplusplus/FullySpecifiedType.h158
-rw-r--r--src/shared/cplusplus/Keywords.cpp1348
-rw-r--r--src/shared/cplusplus/Keywords.kwgen86
-rw-r--r--src/shared/cplusplus/Lexer.cpp680
-rw-r--r--src/shared/cplusplus/Lexer.h159
-rw-r--r--src/shared/cplusplus/LiteralTable.cpp34
-rw-r--r--src/shared/cplusplus/LiteralTable.h181
-rw-r--r--src/shared/cplusplus/Literals.cpp138
-rw-r--r--src/shared/cplusplus/Literals.h122
-rw-r--r--src/shared/cplusplus/MemoryPool.cpp130
-rw-r--r--src/shared/cplusplus/MemoryPool.h120
-rw-r--r--src/shared/cplusplus/Name.cpp133
-rw-r--r--src/shared/cplusplus/Name.h103
-rw-r--r--src/shared/cplusplus/NameVisitor.cpp67
-rw-r--r--src/shared/cplusplus/NameVisitor.h86
-rw-r--r--src/shared/cplusplus/Names.cpp262
-rw-r--r--src/shared/cplusplus/Names.h241
-rw-r--r--src/shared/cplusplus/ObjectiveCAtKeywords.cpp464
-rw-r--r--src/shared/cplusplus/Parser.cpp3810
-rw-r--r--src/shared/cplusplus/Parser.h292
-rw-r--r--src/shared/cplusplus/PrettyPrinter.cpp1293
-rw-r--r--src/shared/cplusplus/PrettyPrinter.h163
-rw-r--r--src/shared/cplusplus/Scope.cpp310
-rw-r--r--src/shared/cplusplus/Scope.h198
-rw-r--r--src/shared/cplusplus/Semantic.cpp198
-rw-r--r--src/shared/cplusplus/Semantic.h109
-rw-r--r--src/shared/cplusplus/SemanticCheck.cpp72
-rw-r--r--src/shared/cplusplus/SemanticCheck.h78
-rw-r--r--src/shared/cplusplus/Symbol.cpp421
-rw-r--r--src/shared/cplusplus/Symbol.h266
-rw-r--r--src/shared/cplusplus/SymbolVisitor.cpp66
-rw-r--r--src/shared/cplusplus/SymbolVisitor.h90
-rw-r--r--src/shared/cplusplus/Symbols.cpp484
-rw-r--r--src/shared/cplusplus/Symbols.h338
-rw-r--r--src/shared/cplusplus/Token.cpp140
-rw-r--r--src/shared/cplusplus/Token.h336
-rw-r--r--src/shared/cplusplus/TranslationUnit.cpp474
-rw-r--r--src/shared/cplusplus/TranslationUnit.h201
-rw-r--r--src/shared/cplusplus/Type.cpp198
-rw-r--r--src/shared/cplusplus/Type.h124
-rw-r--r--src/shared/cplusplus/TypeVisitor.cpp67
-rw-r--r--src/shared/cplusplus/TypeVisitor.h92
-rw-r--r--src/shared/cplusplus/cplusplus.pri77
70 files changed, 25410 insertions, 0 deletions
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
new file mode 100644
index 0000000000..3d710db366
--- /dev/null
+++ b/src/shared/cplusplus/AST.cpp
@@ -0,0 +1,3985 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "AST.h"
+#include "ASTVisitor.h"
+#include "MemoryPool.h"
+
+#include <cassert>
+#include <cstddef>
+#include <algorithm>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+AST::AST()
+{ }
+
+AST::~AST()
+{ assert(0); }
+
+AccessDeclarationAST *AST::asAccessDeclaration()
+{ return dynamic_cast<AccessDeclarationAST *>(this); }
+
+ArrayAccessAST *AST::asArrayAccess()
+{ return dynamic_cast<ArrayAccessAST *>(this); }
+
+ArrayDeclaratorAST *AST::asArrayDeclarator()
+{ return dynamic_cast<ArrayDeclaratorAST *>(this); }
+
+ArrayInitializerAST *AST::asArrayInitializer()
+{ return dynamic_cast<ArrayInitializerAST *>(this); }
+
+AsmDefinitionAST *AST::asAsmDefinition()
+{ return dynamic_cast<AsmDefinitionAST *>(this); }
+
+AttributeAST *AST::asAttribute()
+{ return dynamic_cast<AttributeAST *>(this); }
+
+AttributeSpecifierAST *AST::asAttributeSpecifier()
+{ return dynamic_cast<AttributeSpecifierAST *>(this); }
+
+BaseSpecifierAST *AST::asBaseSpecifier()
+{ return dynamic_cast<BaseSpecifierAST *>(this); }
+
+QtMethodAST *AST::asQtMethod()
+{ return dynamic_cast<QtMethodAST *>(this); }
+
+BinaryExpressionAST *AST::asBinaryExpression()
+{ return dynamic_cast<BinaryExpressionAST *>(this); }
+
+BoolLiteralAST *AST::asBoolLiteral()
+{ return dynamic_cast<BoolLiteralAST *>(this); }
+
+BreakStatementAST *AST::asBreakStatement()
+{ return dynamic_cast<BreakStatementAST *>(this); }
+
+CallAST *AST::asCall()
+{ return dynamic_cast<CallAST *>(this); }
+
+CaseStatementAST *AST::asCaseStatement()
+{ return dynamic_cast<CaseStatementAST *>(this); }
+
+CastExpressionAST *AST::asCastExpression()
+{ return dynamic_cast<CastExpressionAST *>(this); }
+
+CatchClauseAST *AST::asCatchClause()
+{ return dynamic_cast<CatchClauseAST *>(this); }
+
+ClassSpecifierAST *AST::asClassSpecifier()
+{ return dynamic_cast<ClassSpecifierAST *>(this); }
+
+CompoundLiteralAST *AST::asCompoundLiteral()
+{ return dynamic_cast<CompoundLiteralAST *>(this); }
+
+CompoundStatementAST *AST::asCompoundStatement()
+{ return dynamic_cast<CompoundStatementAST *>(this); }
+
+ConditionAST *AST::asCondition()
+{ return dynamic_cast<ConditionAST *>(this); }
+
+ConditionalExpressionAST *AST::asConditionalExpression()
+{ return dynamic_cast<ConditionalExpressionAST *>(this); }
+
+ContinueStatementAST *AST::asContinueStatement()
+{ return dynamic_cast<ContinueStatementAST *>(this); }
+
+ConversionFunctionIdAST *AST::asConversionFunctionId()
+{ return dynamic_cast<ConversionFunctionIdAST *>(this); }
+
+CoreDeclaratorAST *AST::asCoreDeclarator()
+{ return dynamic_cast<CoreDeclaratorAST *>(this); }
+
+CppCastExpressionAST *AST::asCppCastExpression()
+{ return dynamic_cast<CppCastExpressionAST *>(this); }
+
+CtorInitializerAST *AST::asCtorInitializer()
+{ return dynamic_cast<CtorInitializerAST *>(this); }
+
+DeclarationAST *AST::asDeclaration()
+{ return dynamic_cast<DeclarationAST *>(this); }
+
+DeclarationStatementAST *AST::asDeclarationStatement()
+{ return dynamic_cast<DeclarationStatementAST *>(this); }
+
+DeclaratorAST *AST::asDeclarator()
+{ return dynamic_cast<DeclaratorAST *>(this); }
+
+DeclaratorIdAST *AST::asDeclaratorId()
+{ return dynamic_cast<DeclaratorIdAST *>(this); }
+
+DeclaratorListAST *AST::asDeclaratorList()
+{ return dynamic_cast<DeclaratorListAST *>(this); }
+
+DeleteExpressionAST *AST::asDeleteExpression()
+{ return dynamic_cast<DeleteExpressionAST *>(this); }
+
+DestructorNameAST *AST::asDestructorName()
+{ return dynamic_cast<DestructorNameAST *>(this); }
+
+DoStatementAST *AST::asDoStatement()
+{ return dynamic_cast<DoStatementAST *>(this); }
+
+ElaboratedTypeSpecifierAST *AST::asElaboratedTypeSpecifier()
+{ return dynamic_cast<ElaboratedTypeSpecifierAST *>(this); }
+
+EmptyDeclarationAST *AST::asEmptyDeclaration()
+{ return dynamic_cast<EmptyDeclarationAST *>(this); }
+
+EnumSpecifierAST *AST::asEnumSpecifier()
+{ return dynamic_cast<EnumSpecifierAST *>(this); }
+
+EnumeratorAST *AST::asEnumerator()
+{ return dynamic_cast<EnumeratorAST *>(this); }
+
+ExceptionDeclarationAST *AST::asExceptionDeclaration()
+{ return dynamic_cast<ExceptionDeclarationAST *>(this); }
+
+ExceptionSpecificationAST *AST::asExceptionSpecification()
+{ return dynamic_cast<ExceptionSpecificationAST *>(this); }
+
+ExpressionAST *AST::asExpression()
+{ return dynamic_cast<ExpressionAST *>(this); }
+
+ExpressionListAST *AST::asExpressionList()
+{ return dynamic_cast<ExpressionListAST *>(this); }
+
+ExpressionOrDeclarationStatementAST *AST::asExpressionOrDeclarationStatement()
+{ return dynamic_cast<ExpressionOrDeclarationStatementAST *>(this); }
+
+ExpressionStatementAST *AST::asExpressionStatement()
+{ return dynamic_cast<ExpressionStatementAST *>(this); }
+
+ForStatementAST *AST::asForStatement()
+{ return dynamic_cast<ForStatementAST *>(this); }
+
+FunctionDeclaratorAST *AST::asFunctionDeclarator()
+{ return dynamic_cast<FunctionDeclaratorAST *>(this); }
+
+FunctionDefinitionAST *AST::asFunctionDefinition()
+{ return dynamic_cast<FunctionDefinitionAST *>(this); }
+
+GotoStatementAST *AST::asGotoStatement()
+{ return dynamic_cast<GotoStatementAST *>(this); }
+
+IfStatementAST *AST::asIfStatement()
+{ return dynamic_cast<IfStatementAST *>(this); }
+
+LabeledStatementAST *AST::asLabeledStatement()
+{ return dynamic_cast<LabeledStatementAST *>(this); }
+
+LinkageBodyAST *AST::asLinkageBody()
+{ return dynamic_cast<LinkageBodyAST *>(this); }
+
+LinkageSpecificationAST *AST::asLinkageSpecification()
+{ return dynamic_cast<LinkageSpecificationAST *>(this); }
+
+MemInitializerAST *AST::asMemInitializer()
+{ return dynamic_cast<MemInitializerAST *>(this); }
+
+MemberAccessAST *AST::asMemberAccess()
+{ return dynamic_cast<MemberAccessAST *>(this); }
+
+NameAST *AST::asName()
+{ return dynamic_cast<NameAST *>(this); }
+
+NamedTypeSpecifierAST *AST::asNamedTypeSpecifier()
+{ return dynamic_cast<NamedTypeSpecifierAST *>(this); }
+
+NamespaceAST *AST::asNamespace()
+{ return dynamic_cast<NamespaceAST *>(this); }
+
+NamespaceAliasDefinitionAST *AST::asNamespaceAliasDefinition()
+{ return dynamic_cast<NamespaceAliasDefinitionAST *>(this); }
+
+NestedDeclaratorAST *AST::asNestedDeclarator()
+{ return dynamic_cast<NestedDeclaratorAST *>(this); }
+
+NestedExpressionAST *AST::asNestedExpression()
+{ return dynamic_cast<NestedExpressionAST *>(this); }
+
+NestedNameSpecifierAST *AST::asNestedNameSpecifier()
+{ return dynamic_cast<NestedNameSpecifierAST *>(this); }
+
+NewDeclaratorAST *AST::asNewDeclarator()
+{ return dynamic_cast<NewDeclaratorAST *>(this); }
+
+NewExpressionAST *AST::asNewExpression()
+{ return dynamic_cast<NewExpressionAST *>(this); }
+
+NewInitializerAST *AST::asNewInitializer()
+{ return dynamic_cast<NewInitializerAST *>(this); }
+
+NewTypeIdAST *AST::asNewTypeId()
+{ return dynamic_cast<NewTypeIdAST *>(this); }
+
+NumericLiteralAST *AST::asNumericLiteral()
+{ return dynamic_cast<NumericLiteralAST *>(this); }
+
+OperatorAST *AST::asOperator()
+{ return dynamic_cast<OperatorAST *>(this); }
+
+OperatorFunctionIdAST *AST::asOperatorFunctionId()
+{ return dynamic_cast<OperatorFunctionIdAST *>(this); }
+
+ParameterDeclarationAST *AST::asParameterDeclaration()
+{ return dynamic_cast<ParameterDeclarationAST *>(this); }
+
+ParameterDeclarationClauseAST *AST::asParameterDeclarationClause()
+{ return dynamic_cast<ParameterDeclarationClauseAST *>(this); }
+
+PointerAST *AST::asPointer()
+{ return dynamic_cast<PointerAST *>(this); }
+
+PointerToMemberAST *AST::asPointerToMember()
+{ return dynamic_cast<PointerToMemberAST *>(this); }
+
+PostIncrDecrAST *AST::asPostIncrDecr()
+{ return dynamic_cast<PostIncrDecrAST *>(this); }
+
+PostfixAST *AST::asPostfix()
+{ return dynamic_cast<PostfixAST *>(this); }
+
+PostfixDeclaratorAST *AST::asPostfixDeclarator()
+{ return dynamic_cast<PostfixDeclaratorAST *>(this); }
+
+PostfixExpressionAST *AST::asPostfixExpression()
+{ return dynamic_cast<PostfixExpressionAST *>(this); }
+
+PtrOperatorAST *AST::asPtrOperator()
+{ return dynamic_cast<PtrOperatorAST *>(this); }
+
+QualifiedNameAST *AST::asQualifiedName()
+{ return dynamic_cast<QualifiedNameAST *>(this); }
+
+ReferenceAST *AST::asReference()
+{ return dynamic_cast<ReferenceAST *>(this); }
+
+ReturnStatementAST *AST::asReturnStatement()
+{ return dynamic_cast<ReturnStatementAST *>(this); }
+
+SimpleDeclarationAST *AST::asSimpleDeclaration()
+{ return dynamic_cast<SimpleDeclarationAST *>(this); }
+
+SimpleNameAST *AST::asSimpleName()
+{ return dynamic_cast<SimpleNameAST *>(this); }
+
+SimpleSpecifierAST *AST::asSimpleSpecifier()
+{ return dynamic_cast<SimpleSpecifierAST *>(this); }
+
+SizeofExpressionAST *AST::asSizeofExpression()
+{ return dynamic_cast<SizeofExpressionAST *>(this); }
+
+SpecifierAST *AST::asSpecifier()
+{ return dynamic_cast<SpecifierAST *>(this); }
+
+StatementAST *AST::asStatement()
+{ return dynamic_cast<StatementAST *>(this); }
+
+StringLiteralAST *AST::asStringLiteral()
+{ return dynamic_cast<StringLiteralAST *>(this); }
+
+SwitchStatementAST *AST::asSwitchStatement()
+{ return dynamic_cast<SwitchStatementAST *>(this); }
+
+TemplateArgumentListAST *AST::asTemplateArgumentList()
+{ return dynamic_cast<TemplateArgumentListAST *>(this); }
+
+TemplateDeclarationAST *AST::asTemplateDeclaration()
+{ return dynamic_cast<TemplateDeclarationAST *>(this); }
+
+TemplateIdAST *AST::asTemplateId()
+{ return dynamic_cast<TemplateIdAST *>(this); }
+
+TemplateTypeParameterAST *AST::asTemplateTypeParameter()
+{ return dynamic_cast<TemplateTypeParameterAST *>(this); }
+
+ThisExpressionAST *AST::asThisExpression()
+{ return dynamic_cast<ThisExpressionAST *>(this); }
+
+ThrowExpressionAST *AST::asThrowExpression()
+{ return dynamic_cast<ThrowExpressionAST *>(this); }
+
+TranslationUnitAST *AST::asTranslationUnit()
+{ return dynamic_cast<TranslationUnitAST *>(this); }
+
+TryBlockStatementAST *AST::asTryBlockStatement()
+{ return dynamic_cast<TryBlockStatementAST *>(this); }
+
+TypeConstructorCallAST *AST::asTypeConstructorCall()
+{ return dynamic_cast<TypeConstructorCallAST *>(this); }
+
+TypeIdAST *AST::asTypeId()
+{ return dynamic_cast<TypeIdAST *>(this); }
+
+TypeidExpressionAST *AST::asTypeidExpression()
+{ return dynamic_cast<TypeidExpressionAST *>(this); }
+
+TypenameCallExpressionAST *AST::asTypenameCallExpression()
+{ return dynamic_cast<TypenameCallExpressionAST *>(this); }
+
+TypenameTypeParameterAST *AST::asTypenameTypeParameter()
+{ return dynamic_cast<TypenameTypeParameterAST *>(this); }
+
+TypeofSpecifierAST *AST::asTypeofSpecifier()
+{ return dynamic_cast<TypeofSpecifierAST *>(this); }
+
+UnaryExpressionAST *AST::asUnaryExpression()
+{ return dynamic_cast<UnaryExpressionAST *>(this); }
+
+UsingAST *AST::asUsing()
+{ return dynamic_cast<UsingAST *>(this); }
+
+UsingDirectiveAST *AST::asUsingDirective()
+{ return dynamic_cast<UsingDirectiveAST *>(this); }
+
+WhileStatementAST *AST::asWhileStatement()
+{ return dynamic_cast<WhileStatementAST *>(this); }
+
+void AST::accept(ASTVisitor *visitor)
+{
+ if (visitor->preVisit(this))
+ accept0(visitor);
+ visitor->postVisit(this);
+}
+
+unsigned AttributeSpecifierAST::firstToken() const
+{
+ return attribute_token;
+}
+
+unsigned AttributeSpecifierAST::lastToken() const
+{
+ if (second_rparen_token)
+ return second_rparen_token + 1;
+ else if (first_rparen_token)
+ return first_rparen_token + 1;
+ else if (attributes)
+ return attributes->lastToken();
+ else if (second_lparen_token)
+ return second_lparen_token + 1;
+ else if (first_lparen_token)
+ return first_lparen_token + 1;
+ return attribute_token + 1;
+}
+
+AttributeSpecifierAST *AttributeSpecifierAST::clone(MemoryPool *pool) const
+{
+ AttributeSpecifierAST *ast = new (pool) AttributeSpecifierAST;
+ ast->attribute_token = attribute_token;
+ ast->first_lparen_token = first_lparen_token;
+ ast->second_lparen_token = second_lparen_token;
+ if (attributes)
+ ast->attributes = attributes->clone(pool);
+ ast->first_rparen_token = first_rparen_token;
+ ast->second_rparen_token = second_rparen_token;
+ return ast;
+}
+
+void AttributeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (AttributeAST *attr = attributes; attr; attr = attr->next)
+ accept(attr, visitor);
+ }
+}
+
+unsigned AttributeAST::firstToken() const
+{
+ return identifier_token;
+}
+
+unsigned AttributeAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+
+ for (ExpressionListAST *it = expression_list;
+ it->expression && it->next; it = it->next) {
+ if (! it->next && it->expression) {
+ return it->expression->lastToken();
+ }
+ }
+
+ if (tag_token)
+ return tag_token + 1;
+
+ if (lparen_token)
+ return lparen_token + 1;
+
+ return identifier_token + 1;
+}
+
+AttributeAST *AttributeAST::clone(MemoryPool *pool) const
+{
+ AttributeAST *ast = new (pool) AttributeAST;
+ ast->identifier_token = identifier_token;
+ ast->lparen_token = lparen_token;
+ ast->tag_token = tag_token;
+ if (expression_list)
+ ast->expression_list = expression_list->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void AttributeAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ExpressionListAST *it = expression_list; it; it = it->next)
+ accept(it->expression, visitor);
+ }
+}
+
+AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
+{
+ AccessDeclarationAST *ast = new (pool) AccessDeclarationAST;
+ ast->access_specifier_token = access_specifier_token;
+ ast->slots_token = slots_token;
+ ast->colon_token = colon_token;
+ return ast;
+}
+
+void AccessDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned AccessDeclarationAST::firstToken() const
+{
+ return access_specifier_token;
+}
+
+unsigned AccessDeclarationAST::lastToken() const
+{
+ if (colon_token)
+ return colon_token + 1;
+ else if (slots_token)
+ return slots_token + 1;
+ return access_specifier_token + 1;
+}
+
+ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
+{
+ ArrayAccessAST *ast = new (pool) ArrayAccessAST;
+ ast->lbracket_token = lbracket_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rbracket_token = rbracket_token;
+ return ast;
+}
+
+void ArrayAccessAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned ArrayAccessAST::firstToken() const
+{
+ return lbracket_token;
+}
+
+unsigned ArrayAccessAST::lastToken() const
+{
+ if (rbracket_token)
+ return rbracket_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return lbracket_token + 1;
+}
+
+ArrayDeclaratorAST *ArrayDeclaratorAST::clone(MemoryPool *pool) const
+{
+ ArrayDeclaratorAST *ast = new (pool) ArrayDeclaratorAST;
+ ast->lbracket_token = lbracket_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rbracket_token = rbracket_token;
+ return ast;
+}
+
+void ArrayDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(this->expression, visitor);
+ }
+}
+
+unsigned ArrayDeclaratorAST::firstToken() const
+{
+ return lbracket_token;
+}
+
+unsigned ArrayDeclaratorAST::lastToken() const
+{
+ if (rbracket_token)
+ return rbracket_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return lbracket_token + 1;
+}
+
+ArrayInitializerAST *ArrayInitializerAST::clone(MemoryPool *pool) const
+{
+ ArrayInitializerAST *ast = new (pool) ArrayInitializerAST;
+ ast->lbrace_token = lbrace_token;
+ if (expression_list)
+ ast->expression_list = expression_list->clone(pool);
+ ast->rbrace_token = rbrace_token;
+ return ast;
+}
+
+void ArrayInitializerAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ExpressionListAST *expr = expression_list; expr; expr = expr->next)
+ accept(expr->expression, visitor);
+ }
+}
+
+unsigned ArrayInitializerAST::firstToken() const
+{
+ return lbrace_token;
+}
+
+unsigned ArrayInitializerAST::lastToken() const
+{
+ if (rbrace_token)
+ return rbrace_token + 1;
+
+ for (ExpressionListAST *it = expression_list; it; it = it->next) {
+ if (! it->next && it->expression)
+ return it->expression->lastToken();
+ }
+
+ return lbrace_token + 1;
+}
+
+AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
+{
+ AsmDefinitionAST *ast = new (pool) AsmDefinitionAST;
+ ast->asm_token = asm_token;
+ if (cv_qualifier_seq)
+ ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+ ast->lparen_token = lparen_token;
+ ast->rparen_token = rparen_token;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void AsmDefinitionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = cv_qualifier_seq; spec;
+ spec = spec->next)
+ accept(spec, visitor);
+ }
+}
+
+unsigned AsmDefinitionAST::firstToken() const
+{
+ return asm_token;
+}
+
+unsigned AsmDefinitionAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (lparen_token)
+ return lparen_token + 1;
+ for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return asm_token + 1;
+}
+
+BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const
+{
+ BaseSpecifierAST *ast = new (pool) BaseSpecifierAST;
+ ast->token_virtual = token_virtual;
+ ast->token_access_specifier = token_access_specifier;
+ if (name)
+ ast->name = name->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void BaseSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned BaseSpecifierAST::firstToken() const
+{
+ if (token_virtual && token_access_specifier)
+ return std::min(token_virtual, token_access_specifier);
+ return name->firstToken();
+}
+
+unsigned BaseSpecifierAST::lastToken() const
+{
+ if (name)
+ return name->lastToken();
+ else if (token_virtual && token_access_specifier)
+ return std::min(token_virtual, token_access_specifier) + 1;
+ else if (token_virtual)
+ return token_virtual + 1;
+ else if (token_access_specifier)
+ return token_access_specifier + 1;
+ // assert?
+ return 0;
+}
+
+unsigned QtMethodAST::firstToken() const
+{ return method_token; }
+
+unsigned QtMethodAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (declarator)
+ return declarator->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ return method_token + 1;
+}
+
+QtMethodAST *QtMethodAST::clone(MemoryPool *pool) const
+{
+ QtMethodAST *ast = new (pool) QtMethodAST;
+ ast->method_token = method_token;
+ ast->lparen_token = lparen_token;
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void QtMethodAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarator, visitor);
+ }
+}
+
+BinaryExpressionAST *BinaryExpressionAST::clone(MemoryPool *pool) const
+{
+ BinaryExpressionAST *ast = new (pool) BinaryExpressionAST;
+ if (left_expression)
+ ast->left_expression = left_expression->clone(pool);
+ ast->binary_op_token = binary_op_token;
+ if (right_expression)
+ ast->right_expression = right_expression->clone(pool);
+ return ast;
+}
+
+void BinaryExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left_expression, visitor);
+ accept(right_expression, visitor);
+ }
+}
+
+unsigned BinaryExpressionAST::firstToken() const
+{
+ return left_expression->firstToken();
+}
+
+unsigned BinaryExpressionAST::lastToken() const
+{
+ if (right_expression)
+ return right_expression->lastToken();
+ else if (binary_op_token)
+ return binary_op_token + 1;
+ return left_expression->lastToken();
+}
+
+BoolLiteralAST *BoolLiteralAST::clone(MemoryPool *pool) const
+{
+ BoolLiteralAST *ast = new (pool) BoolLiteralAST;
+ ast->token = token;
+ return ast;
+}
+
+void BoolLiteralAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned BoolLiteralAST::firstToken() const
+{
+ return token;
+}
+
+unsigned BoolLiteralAST::lastToken() const
+{
+ return token + 1;
+}
+
+CompoundLiteralAST *CompoundLiteralAST::clone(MemoryPool *pool) const
+{
+ CompoundLiteralAST *ast = new (pool) CompoundLiteralAST;
+ ast->lparen_token = lparen_token;
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (initializer)
+ ast->initializer = initializer->clone(pool);
+ return ast;
+}
+
+void CompoundLiteralAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(type_id, visitor);
+ accept(initializer, visitor);
+ }
+}
+
+unsigned CompoundLiteralAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned CompoundLiteralAST::lastToken() const
+{
+ if (initializer)
+ return initializer->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (type_id)
+ return type_id->lastToken();
+ return lparen_token + 1;
+}
+
+BreakStatementAST *BreakStatementAST::clone(MemoryPool *pool) const
+{
+ BreakStatementAST *ast = new (pool) BreakStatementAST;
+ ast->break_token = break_token;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void BreakStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned BreakStatementAST::firstToken() const
+{
+ return break_token;
+}
+
+unsigned BreakStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ return break_token + 1;
+}
+
+CallAST *CallAST::clone(MemoryPool *pool) const
+{
+ CallAST *ast = new (pool) CallAST;
+ ast->lparen_token = lparen_token;
+ if (expression_list)
+ ast->expression_list = expression_list;
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void CallAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ExpressionListAST *expr = expression_list;
+ expr; expr = expr->next)
+ accept(expr->expression, visitor);
+ }
+}
+
+unsigned CallAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned CallAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ for (ExpressionListAST *it = expression_list; it; it = it->next) {
+ if (! it->next && it->expression)
+ return it->expression->lastToken();
+ }
+ return lparen_token + 1;
+}
+
+CaseStatementAST *CaseStatementAST::clone(MemoryPool *pool) const
+{
+ CaseStatementAST *ast = new (pool) CaseStatementAST;
+ ast->case_token = case_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->colon_token = colon_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ return ast;
+}
+
+void CaseStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned CaseStatementAST::firstToken() const
+{
+ return case_token;
+}
+
+unsigned CaseStatementAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (colon_token)
+ return colon_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return case_token + 1;
+}
+
+CastExpressionAST *CastExpressionAST::clone(MemoryPool *pool) const
+{
+ CastExpressionAST *ast = new (pool) CastExpressionAST;
+ ast->lparen_token = lparen_token;
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void CastExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned CastExpressionAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned CastExpressionAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (type_id)
+ return type_id->lastToken();
+ return lparen_token + 1;
+}
+
+CatchClauseAST *CatchClauseAST::clone(MemoryPool *pool) const
+{
+ CatchClauseAST *ast = new (pool) CatchClauseAST;
+ ast->catch_token = catch_token;
+ ast->lparen_token = lparen_token;
+ if (exception_declaration)
+ ast->exception_declaration = exception_declaration->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void CatchClauseAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(exception_declaration, visitor);
+ accept(statement, visitor);
+ }
+}
+
+unsigned CatchClauseAST::firstToken() const
+{
+ return catch_token;
+}
+
+unsigned CatchClauseAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ for (DeclarationAST *it = exception_declaration; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ if (lparen_token)
+ return lparen_token + 1;
+
+ return catch_token + 1;
+}
+
+ClassSpecifierAST *ClassSpecifierAST::clone(MemoryPool *pool) const
+{
+ ClassSpecifierAST *ast = new (pool) ClassSpecifierAST;
+ ast->classkey_token = classkey_token;
+ if (attributes)
+ ast->attributes = attributes->clone(pool);
+ if (name)
+ ast->name = name->clone(pool);
+ ast->colon_token = colon_token;
+ if (base_clause)
+ ast->base_clause = base_clause->clone(pool);
+ ast->lbrace_token = lbrace_token;
+ if (member_specifiers)
+ ast->member_specifiers = member_specifiers->clone(pool);
+ ast->rbrace_token = rbrace_token;
+ return ast;
+}
+
+void ClassSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = attributes; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(name, visitor);
+ for (BaseSpecifierAST *spec = base_clause; spec; spec = spec->next)
+ accept(spec, visitor);
+ for (DeclarationAST *decl = member_specifiers; decl; decl = decl->next)
+ accept(decl, visitor);
+ }
+}
+
+unsigned ClassSpecifierAST::firstToken() const
+{
+ return classkey_token;
+}
+
+unsigned ClassSpecifierAST::lastToken() const
+{
+ if (rbrace_token)
+ return rbrace_token + 1;
+
+ for (DeclarationAST *it = member_specifiers; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (lbrace_token)
+ return lbrace_token + 1;
+
+ for (BaseSpecifierAST *it = base_clause; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (colon_token)
+ return colon_token + 1;
+
+ if (name)
+ return name->lastToken();
+
+ for (SpecifierAST *it = attributes; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return classkey_token + 1;
+}
+
+CompoundStatementAST *CompoundStatementAST::clone(MemoryPool *pool) const
+{
+ CompoundStatementAST *ast = new (pool) CompoundStatementAST;
+ ast->lbrace_token = lbrace_token;
+ if (statements)
+ ast->statements = statements->clone(pool);
+ ast->rbrace_token = rbrace_token;
+ return ast;
+}
+
+void CompoundStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (StatementAST *stmt = statements; stmt; stmt = stmt->next)
+ accept(stmt, visitor);
+ }
+}
+
+unsigned CompoundStatementAST::firstToken() const
+{
+ return lbrace_token;
+}
+
+unsigned CompoundStatementAST::lastToken() const
+{
+ if (rbrace_token)
+ return rbrace_token + 1;
+
+ for (StatementAST *it = statements; it ; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return lbrace_token + 1;
+}
+
+ConditionAST *ConditionAST::clone(MemoryPool *pool) const
+{
+ ConditionAST *ast = new (pool) ConditionAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ return ast;
+}
+
+void ConditionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(declarator, visitor);
+ }
+}
+
+unsigned ConditionAST::firstToken() const
+{
+ if (type_specifier)
+ return type_specifier->firstToken();
+
+ return declarator->firstToken();
+}
+
+unsigned ConditionAST::lastToken() const
+{
+ if (declarator)
+ return declarator->lastToken();
+
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ // ### assert?
+ return 0;
+}
+
+ConditionalExpressionAST *ConditionalExpressionAST::clone(MemoryPool *pool) const
+{
+ ConditionalExpressionAST *ast = new (pool) ConditionalExpressionAST;
+ if (condition)
+ ast->condition = condition->clone(pool);
+ ast->question_token = question_token;
+ if (left_expression)
+ ast->left_expression = left_expression->clone(pool);
+ ast->colon_token = colon_token;
+ if (right_expression)
+ ast->right_expression = right_expression->clone(pool);
+ return ast;
+}
+
+void ConditionalExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(left_expression, visitor);
+ accept(right_expression, visitor);
+ }
+}
+
+unsigned ConditionalExpressionAST::firstToken() const
+{
+ return condition->firstToken();
+}
+
+unsigned ConditionalExpressionAST::lastToken() const
+{
+ if (right_expression)
+ return right_expression->lastToken();
+ else if (colon_token)
+ return colon_token + 1;
+ else if (left_expression)
+ return left_expression->lastToken();
+ else if (question_token)
+ return question_token + 1;
+ else if (condition)
+ return condition->lastToken();
+ // ### assert?
+ return 0;
+}
+
+ContinueStatementAST *ContinueStatementAST::clone(MemoryPool *pool) const
+{
+ ContinueStatementAST *ast = new (pool) ContinueStatementAST;
+ ast->continue_token = continue_token;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void ContinueStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned ContinueStatementAST::firstToken() const
+{
+ return continue_token;
+}
+
+unsigned ContinueStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ return continue_token + 1;
+}
+
+ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
+{
+ ConversionFunctionIdAST *ast = new (pool) ConversionFunctionIdAST;
+ ast->operator_token = operator_token;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (ptr_operators)
+ ast->ptr_operators = ptr_operators->clone(pool);
+ return ast;
+}
+
+void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op;
+ ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next))
+ accept(ptr_op, visitor);
+ }
+}
+
+unsigned ConversionFunctionIdAST::firstToken() const
+{
+ return operator_token;
+}
+
+unsigned ConversionFunctionIdAST::lastToken() const
+{
+ for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return operator_token + 1;
+}
+
+CppCastExpressionAST *CppCastExpressionAST::clone(MemoryPool *pool) const
+{
+ CppCastExpressionAST *ast = new (pool) CppCastExpressionAST;
+ ast->cast_token = cast_token;
+ ast->less_token = less_token;
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ ast->greater_token = greater_token;
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void CppCastExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(type_id, visitor);
+ accept(expression, visitor);
+ }
+}
+
+unsigned CppCastExpressionAST::firstToken() const
+{
+ return cast_token;
+}
+
+unsigned CppCastExpressionAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ else if (greater_token)
+ return greater_token + 1;
+ else if (type_id)
+ return type_id->lastToken();
+ else if (less_token)
+ return less_token + 1;
+ return cast_token + 1;
+}
+
+CtorInitializerAST *CtorInitializerAST::clone(MemoryPool *pool) const
+{
+ CtorInitializerAST *ast = new (pool) CtorInitializerAST;
+ ast->colon_token = colon_token;
+ if (member_initializers)
+ ast->member_initializers = member_initializers->clone(pool);
+ return ast;
+}
+
+void CtorInitializerAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (MemInitializerAST *mem_init = member_initializers;
+ mem_init; mem_init = mem_init->next)
+ accept(mem_init, visitor);
+ }
+}
+
+unsigned CtorInitializerAST::firstToken() const
+{
+ return colon_token;
+}
+
+unsigned CtorInitializerAST::lastToken() const
+{
+ for (MemInitializerAST *it = member_initializers; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return colon_token + 1;
+}
+
+DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const
+{
+ DeclaratorAST *ast = new (pool) DeclaratorAST;
+ if (ptr_operators)
+ ast->ptr_operators = ptr_operators->clone(pool);
+ if (core_declarator)
+ ast->core_declarator = core_declarator->clone(pool);
+ if (postfix_declarators)
+ ast->postfix_declarators = postfix_declarators->clone(pool);
+ if (attributes)
+ ast->attributes = attributes->clone(pool);
+ if (initializer)
+ ast->initializer = initializer->clone(pool);
+ return ast;
+}
+
+void DeclaratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; ptr_op = ptr_op->next) {
+ accept(ptr_op, visitor);
+ }
+ accept(core_declarator, visitor);
+ for (PostfixDeclaratorAST *fx = postfix_declarators; fx; fx = fx->next) {
+ accept(fx, visitor);
+ }
+ accept(attributes, visitor);
+ accept(initializer, visitor);
+ }
+}
+
+unsigned DeclaratorAST::firstToken() const
+{
+ if (ptr_operators)
+ return ptr_operators->firstToken();
+ else if (core_declarator)
+ return core_declarator->firstToken();
+ else if (postfix_declarators)
+ return postfix_declarators->firstToken();
+ else if (attributes)
+ return attributes->firstToken();
+ else if (initializer)
+ return initializer->firstToken();
+ // ### assert?
+ return 0;
+}
+
+unsigned DeclaratorAST::lastToken() const
+{
+ if (initializer)
+ return initializer->lastToken();
+
+ for (SpecifierAST *it = attributes; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ for (PostfixDeclaratorAST *it = postfix_declarators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (core_declarator)
+ return core_declarator->lastToken();
+
+ for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ // ### assert?
+ return 0;
+}
+
+DeclarationStatementAST *DeclarationStatementAST::clone(MemoryPool *pool) const
+{
+ DeclarationStatementAST *ast = new (pool) DeclarationStatementAST;
+ if (declaration)
+ ast->declaration = declaration->clone(pool);
+ return ast;
+}
+
+void DeclarationStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ }
+}
+
+unsigned DeclarationStatementAST::firstToken() const
+{
+ return declaration->firstToken();
+}
+
+unsigned DeclarationStatementAST::lastToken() const
+{
+ return declaration->lastToken();
+}
+
+DeclaratorIdAST *DeclaratorIdAST::clone(MemoryPool *pool) const
+{
+ DeclaratorIdAST *ast = new (pool) DeclaratorIdAST;
+ if (name)
+ ast->name = name->clone(pool);
+ return ast;
+}
+
+void DeclaratorIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned DeclaratorIdAST::firstToken() const
+{
+ return name->firstToken();
+}
+
+unsigned DeclaratorIdAST::lastToken() const
+{
+ return name->lastToken();
+}
+
+DeclaratorListAST *DeclaratorListAST::clone(MemoryPool *pool) const
+{
+ DeclaratorListAST *ast = new (pool) DeclaratorListAST;
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void DeclaratorListAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (DeclaratorListAST *it = this; it; it = it->next)
+ accept(it->declarator, visitor);
+ }
+}
+
+unsigned DeclaratorListAST::firstToken() const
+{
+ return declarator->firstToken();
+}
+
+unsigned DeclaratorListAST::lastToken() const
+{
+ for (const DeclaratorListAST *it = this; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return 0;
+}
+
+DeleteExpressionAST *DeleteExpressionAST::clone(MemoryPool *pool) const
+{
+ DeleteExpressionAST *ast = new (pool) DeleteExpressionAST;
+ ast->scope_token = scope_token;
+ ast->delete_token = delete_token;
+ ast->lbracket_token = lbracket_token;
+ ast->rbracket_token = rbracket_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void DeleteExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned DeleteExpressionAST::firstToken() const
+{
+ if (scope_token)
+ return scope_token;
+ return delete_token;
+}
+
+unsigned DeleteExpressionAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ else if (rbracket_token)
+ return rbracket_token + 1;
+ else if (lbracket_token)
+ return lbracket_token + 1;
+ else if (delete_token)
+ return delete_token + 1;
+ return scope_token + 1;
+}
+
+DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const
+{
+ DestructorNameAST *ast = new (pool) DestructorNameAST;
+ ast->tilde_token = tilde_token;
+ ast->identifier_token = identifier_token;
+ return ast;
+}
+
+void DestructorNameAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned DestructorNameAST::firstToken() const
+{
+ return tilde_token;
+}
+
+unsigned DestructorNameAST::lastToken() const
+{
+ if (identifier_token)
+ return identifier_token + 1;
+ return tilde_token + 1;
+}
+
+DoStatementAST *DoStatementAST::clone(MemoryPool *pool) const
+{
+ DoStatementAST *ast = new (pool) DoStatementAST;
+ ast->do_token = do_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ ast->while_token = while_token;
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void DoStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(expression, visitor);
+ }
+}
+
+unsigned DoStatementAST::firstToken() const
+{
+ return do_token;
+}
+
+unsigned DoStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ else if (while_token)
+ return while_token + 1;
+ else if (statement)
+ return statement->lastToken();
+ return do_token + 1;
+}
+
+ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+ ElaboratedTypeSpecifierAST *ast = new (pool) ElaboratedTypeSpecifierAST;
+ ast->classkey_token = classkey_token;
+ if (name)
+ ast->name = name->clone(pool);
+ return ast;
+}
+
+void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned ElaboratedTypeSpecifierAST::firstToken() const
+{
+ return classkey_token;
+}
+
+unsigned ElaboratedTypeSpecifierAST::lastToken() const
+{
+ if (name)
+ return name->lastToken();
+ return classkey_token + 1;
+}
+
+EmptyDeclarationAST *EmptyDeclarationAST::clone(MemoryPool *pool) const
+{
+ EmptyDeclarationAST *ast = new (pool) EmptyDeclarationAST;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void EmptyDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned EmptyDeclarationAST::firstToken() const
+{
+ return semicolon_token;
+}
+
+unsigned EmptyDeclarationAST::lastToken() const
+{
+ return semicolon_token + 1;
+}
+
+EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const
+{
+ EnumSpecifierAST *ast = new (pool) EnumSpecifierAST;
+ ast->enum_token = enum_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->lbrace_token = lbrace_token;
+ if (enumerators)
+ ast->enumerators = enumerators->clone(pool);
+ ast->rbrace_token = rbrace_token;
+ return ast;
+}
+
+void EnumSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ for (EnumeratorAST *enumerator = enumerators; enumerator;
+ enumerator = enumerator->next)
+ accept(enumerator, visitor);
+ }
+}
+
+unsigned EnumSpecifierAST::firstToken() const
+{
+ return enum_token;
+}
+
+unsigned EnumSpecifierAST::lastToken() const
+{
+ if (rbrace_token)
+ return rbrace_token + 1;
+
+ for (EnumeratorAST *it = enumerators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (lbrace_token)
+ return lbrace_token + 1;
+ if (name)
+ return name->lastToken();
+
+ return enum_token + 1;
+}
+
+EnumeratorAST *EnumeratorAST::clone(MemoryPool *pool) const
+{
+ EnumeratorAST *ast = new (pool) EnumeratorAST;
+ ast->identifier_token = identifier_token;
+ ast->equal_token = equal_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void EnumeratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned EnumeratorAST::firstToken() const
+{
+ return identifier_token;
+}
+
+unsigned EnumeratorAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ else if (equal_token)
+ return equal_token + 1;
+ return identifier_token + 1;
+}
+
+ExceptionDeclarationAST *ExceptionDeclarationAST::clone(MemoryPool *pool) const
+{
+ ExceptionDeclarationAST *ast = new (pool) ExceptionDeclarationAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ ast->dot_dot_dot_token = dot_dot_dot_token;
+ return ast;
+}
+
+void ExceptionDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(declarator, visitor);
+ }
+}
+
+unsigned ExceptionDeclarationAST::firstToken() const
+{
+ if (type_specifier)
+ return type_specifier->firstToken();
+ if (declarator)
+ return declarator->firstToken();
+ return dot_dot_dot_token;
+}
+
+unsigned ExceptionDeclarationAST::lastToken() const
+{
+ if (dot_dot_dot_token)
+ return dot_dot_dot_token + 1;
+ else if (declarator)
+ return declarator->lastToken();
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return 0;
+}
+
+ExceptionSpecificationAST *ExceptionSpecificationAST::clone(MemoryPool *pool) const
+{
+ ExceptionSpecificationAST *ast = new (pool) ExceptionSpecificationAST;
+ ast->throw_token = throw_token;
+ ast->lparen_token = lparen_token;
+ ast->dot_dot_dot_token = dot_dot_dot_token;
+ if (type_ids)
+ ast->type_ids = type_ids->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void ExceptionSpecificationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ExpressionListAST *type_id = type_ids; type_id;
+ type_id = type_id->next)
+ accept(type_id->expression, visitor);
+ }
+}
+
+unsigned ExceptionSpecificationAST::firstToken() const
+{
+ return throw_token;
+}
+
+unsigned ExceptionSpecificationAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+
+ for (ExpressionListAST *it = type_ids; it; it = it->next) {
+ if (! it->next && it->expression)
+ return it->expression->lastToken();
+ }
+
+ if (dot_dot_dot_token)
+ return dot_dot_dot_token + 1;
+ else if (lparen_token)
+ return lparen_token + 1;
+
+ return throw_token + 1;
+}
+
+ExpressionListAST *ExpressionListAST::clone(MemoryPool *pool) const
+{
+ ExpressionListAST *ast = new (pool) ExpressionListAST;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void ExpressionListAST::accept0(ASTVisitor *visitor)
+{
+ for (const ExpressionListAST *it = this; it; it = it->next) {
+ accept(it->expression, visitor);
+ }
+}
+
+unsigned ExpressionListAST::firstToken() const
+{
+ return expression->firstToken();
+}
+
+unsigned ExpressionListAST::lastToken() const
+{
+ for (const ExpressionListAST *it = this; it; it = it->next) {
+ if (! it->next)
+ return it->expression->lastToken();
+ }
+ return 0;
+}
+
+ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatementAST::clone(MemoryPool *pool) const
+{
+ ExpressionOrDeclarationStatementAST *ast = new (pool) ExpressionOrDeclarationStatementAST;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ if (declaration)
+ ast->declaration = declaration->clone(pool);
+ return ast;
+}
+
+void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ accept(expression, visitor);
+ }
+}
+
+unsigned ExpressionOrDeclarationStatementAST::firstToken() const
+{
+ return declaration->firstToken();
+}
+
+unsigned ExpressionOrDeclarationStatementAST::lastToken() const
+{
+ return declaration->lastToken();
+}
+
+ExpressionStatementAST *ExpressionStatementAST::clone(MemoryPool *pool) const
+{
+ ExpressionStatementAST *ast = new (pool) ExpressionStatementAST;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void ExpressionStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned ExpressionStatementAST::firstToken() const
+{
+ if (expression)
+ return expression->firstToken();
+ return semicolon_token;
+}
+
+unsigned ExpressionStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ // ### assert?
+ return 0;
+}
+
+ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const
+{
+ ForStatementAST *ast = new (pool) ForStatementAST;
+ ast->for_token = for_token;
+ ast->lparen_token = lparen_token;
+ if (initializer)
+ ast->initializer = initializer->clone(pool);
+ if (condition)
+ ast->condition = condition->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ return ast;
+}
+
+void ForStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initializer, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+}
+
+unsigned ForStatementAST::firstToken() const
+{
+ return for_token;
+}
+
+unsigned ForStatementAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ else if (semicolon_token)
+ return semicolon_token + 1;
+ else if (condition)
+ return condition->lastToken();
+ else if (initializer)
+ return initializer->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+
+ return for_token + 1;
+}
+
+FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const
+{
+ FunctionDeclaratorAST *ast = new (pool) FunctionDeclaratorAST;
+ ast->lparen_token = lparen_token;
+ if (parameters)
+ ast->parameters = parameters->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (cv_qualifier_seq)
+ ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+ if (exception_specification)
+ ast->exception_specification = exception_specification->clone(pool);
+ return ast;
+}
+
+void FunctionDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned FunctionDeclaratorAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned FunctionDeclaratorAST::lastToken() const
+{
+ if (exception_specification)
+ return exception_specification->lastToken();
+
+ for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (parameters)
+ return parameters->lastToken();
+
+ return lparen_token + 1;
+}
+
+FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const
+{
+ FunctionDefinitionAST *ast = new (pool) FunctionDefinitionAST;
+ if (decl_specifier_seq)
+ ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ if (ctor_initializer)
+ ast->ctor_initializer = ctor_initializer->clone(pool);
+ if (function_body)
+ ast->function_body = function_body->clone(pool);
+ return ast;
+}
+
+void FunctionDefinitionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = decl_specifier_seq; spec;
+ spec = spec->next)
+ accept(spec, visitor);
+ accept(declarator, visitor);
+ accept(ctor_initializer, visitor);
+ accept(function_body, visitor);
+ }
+}
+
+unsigned FunctionDefinitionAST::firstToken() const
+{
+ if (decl_specifier_seq)
+ return decl_specifier_seq->firstToken();
+ else if (declarator)
+ return declarator->firstToken();
+ else if (ctor_initializer)
+ return ctor_initializer->firstToken();
+ return function_body->firstToken();
+}
+
+unsigned FunctionDefinitionAST::lastToken() const
+{
+ if (function_body)
+ return function_body->lastToken();
+ else if (ctor_initializer)
+ return ctor_initializer->lastToken();
+ if (declarator)
+ return declarator->lastToken();
+
+ for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ // ### assert
+ return 0;
+}
+
+GotoStatementAST *GotoStatementAST::clone(MemoryPool *pool) const
+{
+ GotoStatementAST *ast = new (pool) GotoStatementAST;
+ ast->goto_token = goto_token;
+ ast->identifier_token = identifier_token;
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void GotoStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned GotoStatementAST::firstToken() const
+{
+ return goto_token;
+}
+
+unsigned GotoStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (identifier_token)
+ return identifier_token + 1;
+ else if (goto_token)
+ return goto_token + 1;
+ return 0;
+}
+
+IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const
+{
+ IfStatementAST *ast = new (pool) IfStatementAST;
+ ast->if_token = if_token;
+ ast->lparen_token = lparen_token;
+ if (condition)
+ ast->condition = condition->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ ast->else_token = else_token;
+ if (else_statement)
+ ast->else_statement = else_statement->clone(pool);
+ return ast;
+}
+
+void IfStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(statement, visitor);
+ accept(else_statement, visitor);
+ }
+}
+
+unsigned IfStatementAST::firstToken() const
+{
+ return if_token;
+}
+
+unsigned IfStatementAST::lastToken() const
+{
+ if (else_statement)
+ return else_statement->lastToken();
+ else if (else_token)
+ return else_token + 1;
+ else if (statement)
+ return statement->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (condition)
+ return condition->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ return if_token + 1;
+}
+
+LabeledStatementAST *LabeledStatementAST::clone(MemoryPool *pool) const
+{
+ LabeledStatementAST *ast = new (pool) LabeledStatementAST;
+ ast->label_token = label_token;
+ ast->colon_token = colon_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ return ast;
+}
+
+void LabeledStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+}
+
+unsigned LabeledStatementAST::firstToken() const
+{
+ return label_token;
+}
+
+unsigned LabeledStatementAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (colon_token)
+ return colon_token + 1;
+ return label_token + 1;
+}
+
+LinkageBodyAST *LinkageBodyAST::clone(MemoryPool *pool) const
+{
+ LinkageBodyAST *ast = new (pool) LinkageBodyAST;
+ ast->lbrace_token = lbrace_token;
+ if (declarations)
+ ast->declarations = declarations->clone(pool);
+ ast->rbrace_token = rbrace_token;
+ return ast;
+}
+
+void LinkageBodyAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (DeclarationAST *decl = declarations; decl;
+ decl = decl->next)
+ accept(decl, visitor);
+ }
+}
+
+unsigned LinkageBodyAST::firstToken() const
+{
+ return lbrace_token;
+}
+
+unsigned LinkageBodyAST::lastToken() const
+{
+ if (rbrace_token)
+ return rbrace_token + 1;
+
+ for (DeclarationAST *it = declarations; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return lbrace_token + 1;
+}
+
+LinkageSpecificationAST *LinkageSpecificationAST::clone(MemoryPool *pool) const
+{
+ LinkageSpecificationAST *ast = new (pool) LinkageSpecificationAST;
+ ast->extern_token = extern_token;
+ ast->extern_type = extern_type;
+ if (declaration)
+ ast->declaration = declaration->clone(pool);
+ return ast;
+}
+
+void LinkageSpecificationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ }
+}
+
+unsigned LinkageSpecificationAST::firstToken() const
+{
+ return extern_token;
+}
+
+unsigned LinkageSpecificationAST::lastToken() const
+{
+ if (declaration)
+ return declaration->lastToken();
+ else if (extern_type)
+ return extern_type + 1;
+ return extern_token + 1;
+}
+
+MemInitializerAST *MemInitializerAST::clone(MemoryPool *pool) const
+{
+ MemInitializerAST *ast = new (pool) MemInitializerAST;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void MemInitializerAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned MemInitializerAST::firstToken() const
+{
+ return name->firstToken();
+}
+
+unsigned MemInitializerAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ return name->lastToken();
+}
+
+MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const
+{
+ MemberAccessAST *ast = new (pool) MemberAccessAST;
+ ast->access_token = access_token;
+ ast->template_token = template_token;
+ if (member_name)
+ ast->member_name = member_name->clone(pool);
+ return ast;
+}
+
+void MemberAccessAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(member_name, visitor);
+ }
+}
+
+unsigned MemberAccessAST::firstToken() const
+{
+ return access_token;
+}
+
+unsigned MemberAccessAST::lastToken() const
+{
+ if (member_name)
+ return member_name->lastToken();
+ else if (template_token)
+ return template_token + 1;
+ return access_token + 1;
+}
+
+NamedTypeSpecifierAST *NamedTypeSpecifierAST::clone(MemoryPool *pool) const
+{
+ NamedTypeSpecifierAST *ast = new (pool) NamedTypeSpecifierAST;
+ if (name)
+ ast->name = name->clone(pool);
+ return ast;
+}
+
+void NamedTypeSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned NamedTypeSpecifierAST::firstToken() const
+{
+ return name->firstToken();
+}
+
+unsigned NamedTypeSpecifierAST::lastToken() const
+{
+ return name->lastToken();
+}
+
+NamespaceAST *NamespaceAST::clone(MemoryPool *pool) const
+{
+ NamespaceAST *ast = new (pool) NamespaceAST;
+ ast->namespace_token = namespace_token;
+ ast->identifier_token = identifier_token;
+ if (attributes)
+ ast->attributes = attributes->clone(pool);
+ if (linkage_body)
+ ast->linkage_body = linkage_body->clone(pool);
+ return ast;
+}
+
+void NamespaceAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *attr = attributes; attr; attr = attr->next) {
+ accept(attr, visitor);
+ }
+ accept(linkage_body, visitor);
+ }
+}
+
+unsigned NamespaceAST::firstToken() const
+{
+ return namespace_token;
+}
+
+unsigned NamespaceAST::lastToken() const
+{
+ if (linkage_body)
+ return linkage_body->lastToken();
+
+ for (SpecifierAST *it = attributes; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (identifier_token)
+ return identifier_token + 1;
+
+ return namespace_token + 1;
+}
+
+NamespaceAliasDefinitionAST *NamespaceAliasDefinitionAST::clone(MemoryPool *pool) const
+{
+ NamespaceAliasDefinitionAST *ast = new (pool) NamespaceAliasDefinitionAST;
+ ast->namespace_token = namespace_token;
+ ast->namespace_name = namespace_name;
+ ast->equal_token = equal_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void NamespaceAliasDefinitionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned NamespaceAliasDefinitionAST::firstToken() const
+{
+ return namespace_token;
+}
+
+unsigned NamespaceAliasDefinitionAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (name)
+ return name->lastToken();
+ else if (equal_token)
+ return equal_token + 1;
+ else if (namespace_name)
+ return namespace_name + 1;
+ return namespace_token + 1;
+}
+
+NestedDeclaratorAST *NestedDeclaratorAST::clone(MemoryPool *pool) const
+{
+ NestedDeclaratorAST *ast = new (pool) NestedDeclaratorAST;
+ ast->lparen_token = lparen_token;
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarator, visitor);
+ }
+}
+
+unsigned NestedDeclaratorAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned NestedDeclaratorAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (declarator)
+ return declarator->lastToken();
+ return lparen_token + 1;
+}
+
+NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const
+{
+ NestedExpressionAST *ast = new (pool) NestedExpressionAST;
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void NestedExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned NestedExpressionAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned NestedExpressionAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return lparen_token + 1;
+}
+
+NestedNameSpecifierAST *NestedNameSpecifierAST::clone(MemoryPool *pool) const
+{
+ NestedNameSpecifierAST *ast = new (pool) NestedNameSpecifierAST;
+ if (class_or_namespace_name)
+ ast->class_or_namespace_name = class_or_namespace_name->clone(pool);
+ ast->scope_token = scope_token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void NestedNameSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(class_or_namespace_name, visitor);
+ accept(next, visitor); // ### I'm not 100% sure about this.
+ }
+}
+
+unsigned NestedNameSpecifierAST::firstToken() const
+{
+ return class_or_namespace_name->firstToken();
+}
+
+unsigned NestedNameSpecifierAST::lastToken() const
+{
+ if (scope_token)
+ return scope_token + 1;
+ return class_or_namespace_name->lastToken();
+}
+
+NewDeclaratorAST *NewDeclaratorAST::clone(MemoryPool *pool) const
+{
+ NewDeclaratorAST *ast = new (pool) NewDeclaratorAST;
+ if (ptr_operators)
+ ast->ptr_operators = ptr_operators->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ return ast;
+}
+
+void NewDeclaratorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op;
+ ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next)) {
+ accept(ptr_op, visitor);
+ }
+
+ accept(declarator, visitor);
+ }
+}
+
+unsigned NewDeclaratorAST::firstToken() const
+{
+ return ptr_operators->firstToken();
+}
+
+unsigned NewDeclaratorAST::lastToken() const
+{
+ if (declarator)
+ return declarator->lastToken();
+
+ for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return 0;
+}
+
+NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const
+{
+ NewExpressionAST *ast = new (pool) NewExpressionAST;
+ ast->scope_token = scope_token;
+ ast->new_token = new_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ if (new_type_id)
+ ast->new_type_id = new_type_id->clone(pool);
+ if (new_initializer)
+ ast->new_initializer = new_initializer->clone(pool);
+ return ast;
+}
+
+void NewExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(type_id, visitor);
+ accept(new_type_id, visitor);
+ accept(new_initializer, visitor);
+ }
+}
+
+unsigned NewExpressionAST::firstToken() const
+{
+ if (scope_token)
+ return scope_token;
+ return new_token;
+}
+
+unsigned NewExpressionAST::lastToken() const
+{
+ if (new_initializer)
+ return new_initializer->lastToken();
+ else if (new_type_id)
+ return new_type_id->lastToken();
+ else if (type_id)
+ return type_id->lastToken();
+ else if (expression)
+ return expression->lastToken();
+ else if (new_token)
+ return new_token + 1;
+ else if (scope_token)
+ return scope_token + 1;
+ // ### assert?
+ return 0;
+}
+
+NewInitializerAST *NewInitializerAST::clone(MemoryPool *pool) const
+{
+ NewInitializerAST *ast = new (pool) NewInitializerAST;
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void NewInitializerAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned NewInitializerAST::firstToken() const
+{
+ return lparen_token;
+}
+
+unsigned NewInitializerAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return lparen_token + 1;
+}
+
+TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const
+{
+ TypeIdAST *ast = new (pool) TypeIdAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ return ast;
+}
+
+NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const
+{
+ NewTypeIdAST *ast = new (pool) NewTypeIdAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (new_initializer)
+ ast->new_initializer = new_initializer->clone(pool);
+ if (new_declarator)
+ ast->new_declarator = new_declarator->clone(pool);
+ return ast;
+}
+
+void NewTypeIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(new_initializer, visitor);
+ accept(new_declarator, visitor);
+ }
+}
+
+unsigned NewTypeIdAST::firstToken() const
+{
+ return type_specifier->firstToken();
+}
+
+unsigned NewTypeIdAST::lastToken() const
+{
+ if (new_declarator)
+ return new_declarator->lastToken();
+ else if (new_initializer)
+ return new_initializer->lastToken();
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ // ### assert?
+ return 0;
+}
+
+NumericLiteralAST *NumericLiteralAST::clone(MemoryPool *pool) const
+{
+ NumericLiteralAST *ast = new (pool) NumericLiteralAST;
+ ast->token = token;
+ return ast;
+}
+
+void NumericLiteralAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned NumericLiteralAST::firstToken() const
+{
+ return token;
+}
+
+unsigned NumericLiteralAST::lastToken() const
+{
+ return token + 1;
+}
+
+OperatorAST *OperatorAST::clone(MemoryPool *pool) const
+{
+ OperatorAST *ast = new (pool) OperatorAST;
+ ast->op_token = op_token;
+ ast->open_token = open_token;
+ ast->close_token = close_token;
+ return ast;
+}
+
+void OperatorAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned OperatorAST::firstToken() const
+{
+ return op_token;
+}
+
+unsigned OperatorAST::lastToken() const
+{
+ if (close_token)
+ return close_token + 1;
+ else if (open_token)
+ return open_token + 1;
+ return op_token + 1;
+}
+
+OperatorFunctionIdAST *OperatorFunctionIdAST::clone(MemoryPool *pool) const
+{
+ OperatorFunctionIdAST *ast = new (pool) OperatorFunctionIdAST;
+ ast->operator_token = operator_token;
+ if (op)
+ ast->op = op->clone(pool);
+ return ast;
+}
+
+void OperatorFunctionIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(op, visitor);
+ }
+}
+
+unsigned OperatorFunctionIdAST::firstToken() const
+{
+ return operator_token;
+}
+
+unsigned OperatorFunctionIdAST::lastToken() const
+{
+ if (op)
+ return op->lastToken();
+ return operator_token + 1;
+}
+
+ParameterDeclarationAST *ParameterDeclarationAST::clone(MemoryPool *pool) const
+{
+ ParameterDeclarationAST *ast = new (pool) ParameterDeclarationAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ if (declarator)
+ ast->declarator = declarator->clone(pool);
+ ast->equal_token = equal_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void ParameterDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(declarator, visitor);
+ accept(expression, visitor);
+ }
+}
+
+unsigned ParameterDeclarationAST::firstToken() const
+{
+ return type_specifier->firstToken();
+}
+
+unsigned ParameterDeclarationAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ else if (equal_token)
+ return equal_token + 1;
+ else if (declarator)
+ return declarator->lastToken();
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ // ### assert?
+ return 0;
+}
+
+ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *pool) const
+{
+ ParameterDeclarationClauseAST *ast = new (pool) ParameterDeclarationClauseAST;
+ if (parameter_declarations)
+ ast->parameter_declarations = parameter_declarations;
+ ast->dot_dot_dot_token = dot_dot_dot_token;
+ return ast;
+}
+
+void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (DeclarationAST *param = parameter_declarations; param;
+ param = param->next)
+ accept(param, visitor);
+ }
+}
+
+unsigned ParameterDeclarationClauseAST::firstToken() const
+{
+ if (parameter_declarations)
+ return parameter_declarations->firstToken();
+ return dot_dot_dot_token;
+}
+
+unsigned ParameterDeclarationClauseAST::lastToken() const
+{
+ if (dot_dot_dot_token)
+ return dot_dot_dot_token + 1;
+ return parameter_declarations->lastToken();
+}
+
+PointerAST *PointerAST::clone(MemoryPool *pool) const
+{
+ PointerAST *ast = new (pool) PointerAST;
+ ast->star_token = star_token;
+ if (cv_qualifier_seq)
+ ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+ return ast;
+}
+
+void PointerAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = cv_qualifier_seq; spec;
+ spec = spec->next)
+ accept(spec, visitor);
+ }
+}
+
+unsigned PointerAST::firstToken() const
+{
+ return star_token;
+}
+
+unsigned PointerAST::lastToken() const
+{
+ for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return star_token + 1;
+}
+
+PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const
+{
+ PointerToMemberAST *ast = new (pool) PointerToMemberAST;
+ ast->global_scope_token = global_scope_token;
+ if (nested_name_specifier)
+ ast->nested_name_specifier = nested_name_specifier->clone(pool);
+ ast->star_token = star_token;
+ if (cv_qualifier_seq)
+ ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+ return ast;
+}
+
+void PointerToMemberAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(nested_name_specifier, visitor);
+ for (SpecifierAST *spec = cv_qualifier_seq; spec;
+ spec = spec->next)
+ accept(spec, visitor);
+ }
+}
+
+unsigned PointerToMemberAST::firstToken() const
+{
+ if (global_scope_token)
+ return global_scope_token;
+ else if (nested_name_specifier)
+ return nested_name_specifier->firstToken();
+ return star_token;
+}
+
+unsigned PointerToMemberAST::lastToken() const
+{
+ for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (star_token)
+ return star_token + 1;
+
+ for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (global_scope_token)
+ return global_scope_token + 1;
+
+ return 0;
+}
+
+PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
+{
+ PostIncrDecrAST *ast = new (pool) PostIncrDecrAST;
+ ast->incr_decr_token = incr_decr_token;
+ return ast;
+}
+
+void PostIncrDecrAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned PostIncrDecrAST::firstToken() const
+{
+ return incr_decr_token;
+}
+
+unsigned PostIncrDecrAST::lastToken() const
+{
+ return incr_decr_token + 1;
+}
+
+PostfixExpressionAST *PostfixExpressionAST::clone(MemoryPool *pool) const
+{
+ PostfixExpressionAST *ast = new (pool) PostfixExpressionAST;
+ if (base_expression)
+ ast->base_expression = base_expression->clone(pool);
+ if (postfix_expressions)
+ ast->postfix_expressions = postfix_expressions->clone(pool);
+ return ast;
+}
+
+void PostfixExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base_expression, visitor);
+ for (PostfixAST *fx = postfix_expressions; fx; fx = fx->next)
+ accept(fx, visitor);
+ }
+}
+
+unsigned PostfixExpressionAST::firstToken() const
+{
+ return base_expression->firstToken();
+}
+
+unsigned PostfixExpressionAST::lastToken() const
+{
+ for (PostfixAST *it = postfix_expressions; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return base_expression->lastToken();
+}
+
+QualifiedNameAST *QualifiedNameAST::clone(MemoryPool *pool) const
+{
+ QualifiedNameAST *ast = new (pool) QualifiedNameAST;
+ ast->global_scope_token = global_scope_token;
+ if (nested_name_specifier)
+ ast->nested_name_specifier = nested_name_specifier->clone(pool);
+ if (unqualified_name)
+ ast->unqualified_name = unqualified_name->clone(pool);
+ return ast;
+}
+
+void QualifiedNameAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(nested_name_specifier, visitor);
+ accept(unqualified_name, visitor);
+ }
+}
+
+unsigned QualifiedNameAST::firstToken() const
+{
+ if (global_scope_token)
+ return global_scope_token;
+ else if (nested_name_specifier)
+ return nested_name_specifier->firstToken();
+ return unqualified_name->firstToken();
+}
+
+unsigned QualifiedNameAST::lastToken() const
+{
+ if (unqualified_name)
+ return unqualified_name->lastToken();
+
+ for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (global_scope_token)
+ return global_scope_token + 1;
+
+ return 0;
+}
+
+ReferenceAST *ReferenceAST::clone(MemoryPool *pool) const
+{
+ ReferenceAST *ast = new (pool) ReferenceAST;
+ ast->amp_token = amp_token;
+ return ast;
+}
+
+void ReferenceAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned ReferenceAST::firstToken() const
+{
+ return amp_token;
+}
+
+unsigned ReferenceAST::lastToken() const
+{
+ return amp_token + 1;
+}
+
+ReturnStatementAST *ReturnStatementAST::clone(MemoryPool *pool) const
+{
+ ReturnStatementAST *ast = new (pool) ReturnStatementAST;
+ ast->return_token = return_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void ReturnStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned ReturnStatementAST::firstToken() const
+{
+ return return_token;
+}
+
+unsigned ReturnStatementAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ return return_token + 1;
+}
+
+SimpleDeclarationAST *SimpleDeclarationAST::clone(MemoryPool *pool) const
+{
+ SimpleDeclarationAST *ast = new (pool) SimpleDeclarationAST;
+ if (decl_specifier_seq)
+ ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
+ if (declarators)
+ ast->declarators = declarators->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void SimpleDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = decl_specifier_seq; spec;
+ spec = spec->next)
+ accept(spec, visitor);
+ accept(declarators, visitor);
+ }
+}
+
+unsigned SimpleDeclarationAST::firstToken() const
+{
+ if (decl_specifier_seq)
+ return decl_specifier_seq->firstToken();
+ else if (declarators)
+ return declarators->firstToken();
+ return semicolon_token;
+}
+
+unsigned SimpleDeclarationAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+
+ for (DeclaratorListAST *it = declarators; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return 0;
+}
+
+SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
+{
+ SimpleNameAST *ast = new (pool) SimpleNameAST;
+ ast->identifier_token = identifier_token;
+ return ast;
+}
+
+void SimpleNameAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned SimpleNameAST::firstToken() const
+{
+ return identifier_token;
+}
+
+unsigned SimpleNameAST::lastToken() const
+{
+ return identifier_token + 1;
+}
+
+void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
+{
+ SimpleSpecifierAST *ast = new (pool) SimpleSpecifierAST;
+ ast->specifier_token = specifier_token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+unsigned SimpleSpecifierAST::firstToken() const
+{
+ return specifier_token;
+}
+
+unsigned SimpleSpecifierAST::lastToken() const
+{
+ return specifier_token + 1;
+}
+
+TypeofSpecifierAST *TypeofSpecifierAST::clone(MemoryPool *pool) const
+{
+ TypeofSpecifierAST *ast = new (pool) TypeofSpecifierAST;
+ ast->typeof_token = typeof_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void TypeofSpecifierAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned TypeofSpecifierAST::firstToken() const
+{
+ return typeof_token;
+}
+
+unsigned TypeofSpecifierAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ return typeof_token + 1;
+}
+
+SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
+{
+ SizeofExpressionAST *ast = new (pool) SizeofExpressionAST;
+ ast->sizeof_token = sizeof_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void SizeofExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned SizeofExpressionAST::firstToken() const
+{
+ return sizeof_token;
+}
+
+unsigned SizeofExpressionAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ return sizeof_token + 1;
+}
+
+StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const
+{
+ StringLiteralAST *ast = new (pool) StringLiteralAST;
+ ast->token = token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void StringLiteralAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(next, visitor);
+ }
+}
+
+unsigned StringLiteralAST::firstToken() const
+{
+ return token;
+}
+
+unsigned StringLiteralAST::lastToken() const
+{
+ if (next)
+ return next->lastToken();
+ return token + 1;
+}
+
+SwitchStatementAST *SwitchStatementAST::clone(MemoryPool *pool) const
+{
+ SwitchStatementAST *ast = new (pool) SwitchStatementAST;
+ ast->switch_token = switch_token;
+ ast->lparen_token = lparen_token;
+ if (condition)
+ ast->condition = condition->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ return ast;
+}
+
+void SwitchStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(statement, visitor);
+ }
+}
+
+unsigned SwitchStatementAST::firstToken() const
+{
+ return switch_token;
+}
+
+unsigned SwitchStatementAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (condition)
+ return condition->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ return switch_token + 1;
+}
+
+TemplateArgumentListAST *TemplateArgumentListAST::clone(MemoryPool *pool) const
+{
+ TemplateArgumentListAST *ast = new (pool) TemplateArgumentListAST;
+ if (template_argument)
+ ast->template_argument = template_argument->clone(pool);
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void TemplateArgumentListAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(template_argument, visitor);
+ accept(next, visitor);
+ }
+}
+
+unsigned TemplateArgumentListAST::firstToken() const
+{
+ return template_argument->firstToken();
+}
+
+unsigned TemplateArgumentListAST::lastToken() const
+{
+ for (const TemplateArgumentListAST *it = this; it; it = it->next) {
+ if (! it->next && it->template_argument)
+ return it->template_argument->lastToken();
+ }
+ return 0;
+}
+
+TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
+{
+ TemplateDeclarationAST *ast = new (pool) TemplateDeclarationAST;
+ ast->export_token = export_token;
+ ast->template_token = template_token;
+ ast->less_token = less_token;
+ if (template_parameters)
+ ast->template_parameters = template_parameters->clone(pool);
+ ast->greater_token = greater_token;
+ if (declaration)
+ ast->declaration = declaration->clone(pool);
+ return ast;
+}
+
+void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (DeclarationAST *param = template_parameters; param;
+ param = param->next)
+ accept(param, visitor);
+ accept(declaration, visitor);
+ }
+}
+
+unsigned TemplateDeclarationAST::firstToken() const
+{
+ if (export_token)
+ return export_token;
+ return template_token;
+}
+
+unsigned TemplateDeclarationAST::lastToken() const
+{
+ if (declaration)
+ return declaration->lastToken();
+ else if (greater_token)
+ return greater_token + 1;
+
+ for (DeclarationAST *it = template_parameters; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (less_token)
+ return less_token + 1;
+ else if (template_token)
+ return template_token + 1;
+ else if (export_token)
+ return export_token + 1;
+
+ return 0;
+}
+
+TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const
+{
+ TemplateIdAST *ast = new (pool) TemplateIdAST;
+ ast->identifier_token = identifier_token;
+ ast->less_token = less_token;
+ if (template_arguments)
+ ast->template_arguments = template_arguments->clone(pool);
+ ast->greater_token = greater_token;
+ return ast;
+}
+
+void TemplateIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) {
+ accept(it, visitor);
+ }
+ }
+}
+
+unsigned TemplateIdAST::firstToken() const
+{
+ return identifier_token;
+}
+
+unsigned TemplateIdAST::lastToken() const
+{
+ if (greater_token)
+ return greater_token + 1;
+
+ for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) {
+ if (! it->next && it->template_argument)
+ return it->template_argument->lastToken();
+ }
+
+ if (less_token)
+ return less_token + 1;
+
+ return identifier_token + 1;
+}
+
+TemplateTypeParameterAST *TemplateTypeParameterAST::clone(MemoryPool *pool) const
+{
+ TemplateTypeParameterAST *ast = new (pool) TemplateTypeParameterAST;
+ ast->template_token = template_token;
+ ast->less_token = less_token;
+ if (template_parameters)
+ ast->template_parameters = template_parameters->clone(pool);
+ ast->greater_token = greater_token;
+ ast->class_token = class_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->equal_token = equal_token;
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ return ast;
+}
+
+void TemplateTypeParameterAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned TemplateTypeParameterAST::firstToken() const
+{
+ return template_token;
+}
+
+unsigned TemplateTypeParameterAST::lastToken() const
+{
+ if (type_id)
+ return type_id->lastToken();
+ else if (equal_token)
+ return equal_token + 1;
+ else if (name)
+ return name->lastToken();
+ else if (class_token)
+ return class_token + 1;
+ else if (greater_token)
+ return greater_token + 1;
+
+ for (DeclarationAST *it = template_parameters; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (less_token)
+ return less_token + 1;
+
+ return template_token + 1;
+}
+
+ThisExpressionAST *ThisExpressionAST::clone(MemoryPool *pool) const
+{
+ ThisExpressionAST *ast = new (pool) ThisExpressionAST;
+ ast->this_token = this_token;
+ return ast;
+}
+
+void ThisExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned ThisExpressionAST::firstToken() const
+{
+ return this_token;
+}
+
+unsigned ThisExpressionAST::lastToken() const
+{
+ return this_token + 1;
+}
+
+ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
+{
+ ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
+ ast->throw_token = throw_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void ThrowExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned ThrowExpressionAST::firstToken() const
+{
+ return throw_token;
+}
+
+unsigned ThrowExpressionAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ return throw_token + 1;
+}
+
+TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const
+{
+ TranslationUnitAST *ast = new (pool) TranslationUnitAST;
+ if (declarations)
+ ast->declarations = declarations->clone(pool);
+ return ast;
+}
+
+void TranslationUnitAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (DeclarationAST *decl = declarations; decl;
+ decl = decl->next)
+ accept(decl, visitor);
+ }
+}
+
+unsigned TranslationUnitAST::firstToken() const
+{
+ return declarations->firstToken();
+}
+
+unsigned TranslationUnitAST::lastToken() const
+{
+ for (DeclarationAST *it = declarations; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+ return 0;
+}
+
+TryBlockStatementAST *TryBlockStatementAST::clone(MemoryPool *pool) const
+{
+ TryBlockStatementAST *ast = new (pool) TryBlockStatementAST;
+ ast->try_token = try_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ if (catch_clause_seq)
+ ast->catch_clause_seq = catch_clause_seq->clone(pool);
+ return ast;
+}
+
+void TryBlockStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(catch_clause_seq, visitor);
+ }
+}
+
+unsigned TryBlockStatementAST::firstToken() const
+{
+ return try_token;
+}
+
+unsigned TryBlockStatementAST::lastToken() const
+{
+ for (CatchClauseAST *it = catch_clause_seq; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (statement)
+ return statement->lastToken();
+
+ return try_token + 1;
+}
+
+TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const
+{
+ TypeConstructorCallAST *ast = new (pool) TypeConstructorCallAST;
+ if (type_specifier)
+ ast->type_specifier = type_specifier->clone(pool);
+ ast->lparen_token = lparen_token;
+ if (expression_list)
+ ast->expression_list = expression_list;
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void TypeConstructorCallAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ for (ExpressionListAST *expr = expression_list;expr;
+ expr = expr->next)
+ accept(expr->expression, visitor);
+ }
+}
+
+unsigned TypeConstructorCallAST::firstToken() const
+{
+ return type_specifier->firstToken();
+}
+
+unsigned TypeConstructorCallAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+
+ for (ExpressionListAST *it = expression_list; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (lparen_token)
+ return lparen_token + 1;
+
+
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return 0;
+}
+
+void TypeIdAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
+ accept(spec, visitor);
+ accept(declarator, visitor);
+ }
+}
+
+unsigned TypeIdAST::firstToken() const
+{
+ return type_specifier->firstToken();
+}
+
+unsigned TypeIdAST::lastToken() const
+{
+ if (declarator)
+ return declarator->lastToken();
+
+ for (SpecifierAST *it = type_specifier; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return 0;
+}
+
+TypeidExpressionAST *TypeidExpressionAST::clone(MemoryPool *pool) const
+{
+ TypeidExpressionAST *ast = new (pool) TypeidExpressionAST;
+ ast->typeid_token = typeid_token;
+ ast->lparen_token = lparen_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void TypeidExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned TypeidExpressionAST::firstToken() const
+{
+ return typeid_token;
+}
+
+unsigned TypeidExpressionAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+ else if (expression)
+ return expression->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+
+ return typeid_token + 1;
+}
+
+TypenameCallExpressionAST *TypenameCallExpressionAST::clone(MemoryPool *pool) const
+{
+ TypenameCallExpressionAST *ast = new (pool) TypenameCallExpressionAST;
+ ast->typename_token = typename_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->lparen_token = lparen_token;
+ if (expression_list)
+ ast->expression_list = expression_list;
+ ast->rparen_token = rparen_token;
+ return ast;
+}
+
+void TypenameCallExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ for (ExpressionListAST *expr = expression_list;expr;
+ expr = expr->next)
+ accept(expr->expression, visitor);
+ }
+}
+
+unsigned TypenameCallExpressionAST::firstToken() const
+{
+ return typename_token;
+}
+
+unsigned TypenameCallExpressionAST::lastToken() const
+{
+ if (rparen_token)
+ return rparen_token + 1;
+
+ for (ExpressionListAST *it = expression_list; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ if (lparen_token)
+ return lparen_token + 1;
+ else if (name)
+ return name->lastToken();
+
+ return typename_token + 1;
+}
+
+TypenameTypeParameterAST *TypenameTypeParameterAST::clone(MemoryPool *pool) const
+{
+ TypenameTypeParameterAST *ast = new (pool) TypenameTypeParameterAST;
+ ast->classkey_token = classkey_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->equal_token = equal_token;
+ if (type_id)
+ ast->type_id = type_id->clone(pool);
+ return ast;
+}
+
+void TypenameTypeParameterAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ accept(type_id, visitor);
+ }
+}
+
+unsigned TypenameTypeParameterAST::firstToken() const
+{
+ return classkey_token;
+}
+
+unsigned TypenameTypeParameterAST::lastToken() const
+{
+ if (type_id)
+ return type_id->lastToken();
+ else if (equal_token)
+ return equal_token + 1;
+ else if (name)
+ return name->lastToken();
+ return classkey_token + 1;
+}
+
+UnaryExpressionAST *UnaryExpressionAST::clone(MemoryPool *pool) const
+{
+ UnaryExpressionAST *ast = new (pool) UnaryExpressionAST;
+ ast->unary_op_token = unary_op_token;
+ if (expression)
+ ast->expression = expression->clone(pool);
+ return ast;
+}
+
+void UnaryExpressionAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+}
+
+unsigned UnaryExpressionAST::firstToken() const
+{
+ return unary_op_token;
+}
+
+unsigned UnaryExpressionAST::lastToken() const
+{
+ if (expression)
+ return expression->lastToken();
+ return unary_op_token + 1;
+}
+
+UsingAST *UsingAST::clone(MemoryPool *pool) const
+{
+ UsingAST *ast = new (pool) UsingAST;
+ ast->using_token = using_token;
+ ast->typename_token = typename_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void UsingAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned UsingAST::firstToken() const
+{
+ return using_token;
+}
+
+unsigned UsingAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (name)
+ return name->lastToken();
+ else if (typename_token)
+ return typename_token + 1;
+ return using_token + 1;
+}
+
+UsingDirectiveAST *UsingDirectiveAST::clone(MemoryPool *pool) const
+{
+ UsingDirectiveAST *ast = new (pool) UsingDirectiveAST;
+ ast->using_token = using_token;
+ ast->namespace_token = namespace_token;
+ if (name)
+ ast->name = name->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void UsingDirectiveAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(name, visitor);
+ }
+}
+
+unsigned UsingDirectiveAST::firstToken() const
+{
+ return using_token;
+}
+
+unsigned UsingDirectiveAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+ else if (name)
+ return name->lastToken();
+ else if (namespace_token)
+ return namespace_token + 1;
+ return using_token + 1;
+}
+
+WhileStatementAST *WhileStatementAST::clone(MemoryPool *pool) const
+{
+ WhileStatementAST *ast = new (pool) WhileStatementAST;
+ ast->while_token = while_token;
+ ast->lparen_token = lparen_token;
+ if (condition)
+ ast->condition = condition->clone(pool);
+ ast->rparen_token = rparen_token;
+ if (statement)
+ ast->statement = statement->clone(pool);
+ return ast;
+}
+
+void WhileStatementAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(condition, visitor);
+ accept(statement, visitor);
+ }
+}
+
+unsigned WhileStatementAST::firstToken() const
+{
+ return while_token;
+}
+
+unsigned WhileStatementAST::lastToken() const
+{
+ if (statement)
+ return statement->lastToken();
+ else if (rparen_token)
+ return rparen_token + 1;
+ else if (condition)
+ return condition->lastToken();
+ else if (lparen_token)
+ return lparen_token + 1;
+ return while_token + 1;
+}
+
+// ObjC++
+unsigned IdentifierListAST::firstToken() const
+{
+ return identifier_token;
+}
+
+unsigned IdentifierListAST::lastToken() const
+{
+ for (const IdentifierListAST *it = this; it; it = it->next) {
+ if (! it->next && it->identifier_token) {
+ return it->identifier_token + 1;
+ }
+ }
+ // ### assert?
+ return 0;
+}
+
+IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const
+{
+ IdentifierListAST *ast = new (pool) IdentifierListAST;
+ ast->identifier_token = identifier_token;
+ if (next)
+ ast->next = next->clone(pool);
+ return ast;
+}
+
+void IdentifierListAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+}
+
+unsigned ObjCClassDeclarationAST::firstToken() const
+{
+ if (attributes)
+ return attributes->firstToken();
+ return class_token;
+}
+
+unsigned ObjCClassDeclarationAST::lastToken() const
+{
+ if (semicolon_token)
+ return semicolon_token + 1;
+
+ for (IdentifierListAST *it = identifier_list; it; it = it->next) {
+ if (! it->next && it->identifier_token)
+ return it->identifier_token + 1;
+ }
+
+ for (SpecifierAST *it = attributes; it; it = it->next) {
+ if (! it->next)
+ return it->lastToken();
+ }
+
+ return class_token + 1;
+}
+
+ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
+{
+ ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST;
+ if (attributes)
+ ast->attributes = attributes->clone(pool);
+ ast->class_token = class_token;
+ if (identifier_list)
+ ast->identifier_list = identifier_list->clone(pool);
+ ast->semicolon_token = semicolon_token;
+ return ast;
+}
+
+void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SpecifierAST *it = attributes; it; it = it->next) {
+ accept(it, visitor);
+ }
+ }
+}
+
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
new file mode 100644
index 0000000000..d7f346c5b0
--- /dev/null
+++ b/src/shared/cplusplus/AST.h
@@ -0,0 +1,1989 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_AST_H
+#define CPLUSPLUS_AST_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "MemoryPool.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT AST: public Managed
+{
+ AST(const AST &other);
+ void operator =(const AST &other);
+
+public:
+ AST();
+ virtual ~AST();
+
+ void accept(ASTVisitor *visitor);
+
+ static void accept(AST *ast, ASTVisitor *visitor)
+ { if (ast) ast->accept(visitor); }
+
+ virtual unsigned firstToken() const = 0;
+ virtual unsigned lastToken() const = 0;
+
+ AccessDeclarationAST *asAccessDeclaration();
+ ArrayAccessAST *asArrayAccess();
+ ArrayDeclaratorAST *asArrayDeclarator();
+ ArrayInitializerAST *asArrayInitializer();
+ AsmDefinitionAST *asAsmDefinition();
+ AttributeAST *asAttribute();
+ AttributeSpecifierAST *asAttributeSpecifier();
+ BaseSpecifierAST *asBaseSpecifier();
+ QtMethodAST *asQtMethod();
+ BinaryExpressionAST *asBinaryExpression();
+ BoolLiteralAST *asBoolLiteral();
+ BreakStatementAST *asBreakStatement();
+ CallAST *asCall();
+ CaseStatementAST *asCaseStatement();
+ CastExpressionAST *asCastExpression();
+ CatchClauseAST *asCatchClause();
+ ClassSpecifierAST *asClassSpecifier();
+ CompoundLiteralAST *asCompoundLiteral();
+ CompoundStatementAST *asCompoundStatement();
+ ConditionAST *asCondition();
+ ConditionalExpressionAST *asConditionalExpression();
+ ContinueStatementAST *asContinueStatement();
+ ConversionFunctionIdAST *asConversionFunctionId();
+ CoreDeclaratorAST *asCoreDeclarator();
+ CppCastExpressionAST *asCppCastExpression();
+ CtorInitializerAST *asCtorInitializer();
+ DeclarationAST *asDeclaration();
+ DeclarationStatementAST *asDeclarationStatement();
+ DeclaratorAST *asDeclarator();
+ DeclaratorIdAST *asDeclaratorId();
+ DeclaratorListAST *asDeclaratorList();
+ DeleteExpressionAST *asDeleteExpression();
+ DestructorNameAST *asDestructorName();
+ DoStatementAST *asDoStatement();
+ ElaboratedTypeSpecifierAST *asElaboratedTypeSpecifier();
+ EmptyDeclarationAST *asEmptyDeclaration();
+ EnumSpecifierAST *asEnumSpecifier();
+ EnumeratorAST *asEnumerator();
+ ExceptionDeclarationAST *asExceptionDeclaration();
+ ExceptionSpecificationAST *asExceptionSpecification();
+ ExpressionAST *asExpression();
+ ExpressionListAST *asExpressionList();
+ ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement();
+ ExpressionStatementAST *asExpressionStatement();
+ ForStatementAST *asForStatement();
+ FunctionDeclaratorAST *asFunctionDeclarator();
+ FunctionDefinitionAST *asFunctionDefinition();
+ GotoStatementAST *asGotoStatement();
+ IfStatementAST *asIfStatement();
+ LabeledStatementAST *asLabeledStatement();
+ LinkageBodyAST *asLinkageBody();
+ LinkageSpecificationAST *asLinkageSpecification();
+ MemInitializerAST *asMemInitializer();
+ MemberAccessAST *asMemberAccess();
+ NameAST *asName();
+ NamedTypeSpecifierAST *asNamedTypeSpecifier();
+ NamespaceAST *asNamespace();
+ NamespaceAliasDefinitionAST *asNamespaceAliasDefinition();
+ NestedDeclaratorAST *asNestedDeclarator();
+ NestedExpressionAST *asNestedExpression();
+ NestedNameSpecifierAST *asNestedNameSpecifier();
+ NewDeclaratorAST *asNewDeclarator();
+ NewExpressionAST *asNewExpression();
+ NewInitializerAST *asNewInitializer();
+ NewTypeIdAST *asNewTypeId();
+ NumericLiteralAST *asNumericLiteral();
+ OperatorAST *asOperator();
+ OperatorFunctionIdAST *asOperatorFunctionId();
+ ParameterDeclarationAST *asParameterDeclaration();
+ ParameterDeclarationClauseAST *asParameterDeclarationClause();
+ PointerAST *asPointer();
+ PointerToMemberAST *asPointerToMember();
+ PostIncrDecrAST *asPostIncrDecr();
+ PostfixAST *asPostfix();
+ PostfixDeclaratorAST *asPostfixDeclarator();
+ PostfixExpressionAST *asPostfixExpression();
+ PtrOperatorAST *asPtrOperator();
+ QualifiedNameAST *asQualifiedName();
+ ReferenceAST *asReference();
+ ReturnStatementAST *asReturnStatement();
+ SimpleDeclarationAST *asSimpleDeclaration();
+ SimpleNameAST *asSimpleName();
+ SimpleSpecifierAST *asSimpleSpecifier();
+ SizeofExpressionAST *asSizeofExpression();
+ SpecifierAST *asSpecifier();
+ StatementAST *asStatement();
+ StringLiteralAST *asStringLiteral();
+ SwitchStatementAST *asSwitchStatement();
+ TemplateArgumentListAST *asTemplateArgumentList();
+ TemplateDeclarationAST *asTemplateDeclaration();
+ TemplateIdAST *asTemplateId();
+ TemplateTypeParameterAST *asTemplateTypeParameter();
+ ThisExpressionAST *asThisExpression();
+ ThrowExpressionAST *asThrowExpression();
+ TranslationUnitAST *asTranslationUnit();
+ TryBlockStatementAST *asTryBlockStatement();
+ TypeConstructorCallAST *asTypeConstructorCall();
+ TypeIdAST *asTypeId();
+ TypeidExpressionAST *asTypeidExpression();
+ TypenameCallExpressionAST *asTypenameCallExpression();
+ TypenameTypeParameterAST *asTypenameTypeParameter();
+ TypeofSpecifierAST *asTypeofSpecifier();
+ UnaryExpressionAST *asUnaryExpression();
+ UsingAST *asUsing();
+ UsingDirectiveAST *asUsingDirective();
+ WhileStatementAST *asWhileStatement();
+
+ virtual AST *clone(MemoryPool *pool) const = 0;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor) = 0;
+};
+
+class CPLUSPLUS_EXPORT SpecifierAST: public AST
+{
+public:
+ SpecifierAST *next;
+
+public:
+ virtual SpecifierAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT SimpleSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned specifier_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual SimpleSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT AttributeSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned attribute_token;
+ unsigned first_lparen_token;
+ unsigned second_lparen_token;
+ AttributeAST *attributes;
+ unsigned first_rparen_token;
+ unsigned second_rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual AttributeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT AttributeAST: public AST
+{
+public:
+ unsigned identifier_token;
+ unsigned lparen_token;
+ unsigned tag_token;
+ ExpressionListAST *expression_list;
+ unsigned rparen_token;
+ AttributeAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual AttributeAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypeofSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned typeof_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypeofSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT StatementAST: public AST
+{
+public:
+ StatementAST *next;
+
+public:
+ virtual StatementAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT ExpressionAST: public AST
+{
+public:
+ virtual ExpressionAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT DeclarationAST: public AST
+{
+public:
+ DeclarationAST *next;
+
+public:
+ virtual DeclarationAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT CoreDeclaratorAST: public AST
+{
+public:
+ virtual CoreDeclaratorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT PostfixDeclaratorAST: public AST
+{
+public:
+ PostfixDeclaratorAST *next;
+
+public:
+ virtual PostfixDeclaratorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT DeclaratorAST: public AST
+{
+public:
+ PtrOperatorAST *ptr_operators;
+ CoreDeclaratorAST *core_declarator;
+ PostfixDeclaratorAST *postfix_declarators;
+ SpecifierAST *attributes;
+ ExpressionAST *initializer;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ExpressionListAST: public ExpressionAST
+{
+public:
+ ExpressionAST *expression;
+ ExpressionListAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ExpressionListAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT SimpleDeclarationAST: public DeclarationAST
+{
+public:
+ SpecifierAST *decl_specifier_seq;
+ DeclaratorListAST *declarators;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual SimpleDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT EmptyDeclarationAST: public DeclarationAST
+{
+public:
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual EmptyDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT AccessDeclarationAST: public DeclarationAST
+{
+public:
+ unsigned access_specifier_token;
+ unsigned slots_token;
+ unsigned colon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual AccessDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST
+{
+public:
+ unsigned asm_token;
+ SpecifierAST *cv_qualifier_seq;
+ unsigned lparen_token;
+ unsigned rparen_token;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual AsmDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT BaseSpecifierAST: public AST
+{
+public:
+ unsigned token_virtual;
+ unsigned token_access_specifier;
+ NameAST *name;
+ BaseSpecifierAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual BaseSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CompoundLiteralAST: public ExpressionAST
+{
+public:
+ unsigned lparen_token;
+ ExpressionAST *type_id;
+ unsigned rparen_token;
+ ExpressionAST *initializer;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CompoundLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT QtMethodAST: public ExpressionAST
+{
+public:
+ unsigned method_token;
+ unsigned lparen_token;
+ DeclaratorAST *declarator;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual QtMethodAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST
+{
+public:
+ ExpressionAST *left_expression;
+ unsigned binary_op_token;
+ ExpressionAST *right_expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual BinaryExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CastExpressionAST: public ExpressionAST
+{
+public:
+ unsigned lparen_token;
+ ExpressionAST *type_id;
+ unsigned rparen_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CastExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ClassSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned classkey_token;
+ SpecifierAST *attributes;
+ NameAST *name;
+ unsigned colon_token;
+ BaseSpecifierAST *base_clause;
+ unsigned lbrace_token;
+ DeclarationAST *member_specifiers;
+ unsigned rbrace_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ClassSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CaseStatementAST: public StatementAST
+{
+public:
+ unsigned case_token;
+ ExpressionAST *expression;
+ unsigned colon_token;
+ StatementAST *statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CaseStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CompoundStatementAST: public StatementAST
+{
+public:
+ unsigned lbrace_token;
+ StatementAST *statements;
+ unsigned rbrace_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CompoundStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ConditionAST: public ExpressionAST
+{
+public:
+ SpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ConditionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ConditionalExpressionAST: public ExpressionAST
+{
+public:
+ ExpressionAST *condition;
+ unsigned question_token;
+ ExpressionAST *left_expression;
+ unsigned colon_token;
+ ExpressionAST *right_expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ConditionalExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CppCastExpressionAST: public ExpressionAST
+{
+public:
+ unsigned cast_token;
+ unsigned less_token;
+ ExpressionAST *type_id;
+ unsigned greater_token;
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CppCastExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CtorInitializerAST: public AST
+{
+public:
+ unsigned colon_token;
+ MemInitializerAST *member_initializers;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CtorInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DeclarationStatementAST: public StatementAST
+{
+public:
+ DeclarationAST *declaration;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DeclarationStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DeclaratorIdAST: public CoreDeclaratorAST
+{
+public:
+ NameAST *name;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DeclaratorIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NestedDeclaratorAST: public CoreDeclaratorAST
+{
+public:
+ unsigned lparen_token;
+ DeclaratorAST *declarator;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NestedDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT FunctionDeclaratorAST: public PostfixDeclaratorAST
+{
+public:
+ unsigned lparen_token;
+ ParameterDeclarationClauseAST *parameters;
+ unsigned rparen_token;
+ SpecifierAST *cv_qualifier_seq;
+ ExceptionSpecificationAST *exception_specification;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual FunctionDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ArrayDeclaratorAST: public PostfixDeclaratorAST
+{
+public:
+ unsigned lbracket_token;
+ ExpressionAST *expression;
+ unsigned rbracket_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ArrayDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DeclaratorListAST: public AST
+{
+public:
+ DeclaratorAST *declarator;
+ DeclaratorListAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DeclaratorListAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DeleteExpressionAST: public ExpressionAST
+{
+public:
+ unsigned scope_token;
+ unsigned delete_token;
+ unsigned lbracket_token;
+ unsigned rbracket_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DeleteExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DoStatementAST: public StatementAST
+{
+public:
+ unsigned do_token;
+ StatementAST *statement;
+ unsigned while_token;
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DoStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NamedTypeSpecifierAST: public SpecifierAST
+{
+public:
+ NameAST *name;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NamedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ElaboratedTypeSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned classkey_token;
+ NameAST *name;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ElaboratedTypeSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT EnumSpecifierAST: public SpecifierAST
+{
+public:
+ unsigned enum_token;
+ NameAST *name;
+ unsigned lbrace_token;
+ EnumeratorAST *enumerators;
+ unsigned rbrace_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual EnumSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT EnumeratorAST: public AST
+{
+public:
+ unsigned identifier_token;
+ unsigned equal_token;
+ ExpressionAST *expression;
+ EnumeratorAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual EnumeratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ExceptionDeclarationAST: public DeclarationAST
+{
+public:
+ SpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ unsigned dot_dot_dot_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ExceptionDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ExceptionSpecificationAST: public AST
+{
+public:
+ unsigned throw_token;
+ unsigned lparen_token;
+ unsigned dot_dot_dot_token;
+ ExpressionListAST *type_ids;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ExceptionSpecificationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ExpressionOrDeclarationStatementAST: public StatementAST
+{
+public:
+ StatementAST *expression;
+ StatementAST *declaration;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ExpressionOrDeclarationStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ExpressionStatementAST: public StatementAST
+{
+public:
+ ExpressionAST *expression;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ExpressionStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT FunctionDefinitionAST: public DeclarationAST
+{
+public:
+ SpecifierAST *decl_specifier_seq;
+ DeclaratorAST *declarator;
+ CtorInitializerAST *ctor_initializer;
+ StatementAST *function_body;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual FunctionDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST
+{
+public:
+ unsigned for_token;
+ unsigned lparen_token;
+ StatementAST *initializer;
+ ExpressionAST *condition;
+ unsigned semicolon_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+ StatementAST *statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ForStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT IfStatementAST: public StatementAST
+{
+public:
+ unsigned if_token;
+ unsigned lparen_token;
+ ExpressionAST *condition;
+ unsigned rparen_token;
+ StatementAST *statement;
+ unsigned else_token;
+ StatementAST *else_statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual IfStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ArrayInitializerAST: public ExpressionAST
+{
+public:
+ unsigned lbrace_token;
+ ExpressionListAST *expression_list;
+ unsigned rbrace_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ArrayInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT LabeledStatementAST: public StatementAST
+{
+public:
+ unsigned label_token;
+ unsigned colon_token;
+ StatementAST *statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual LabeledStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT LinkageBodyAST: public DeclarationAST
+{
+public:
+ unsigned lbrace_token;
+ DeclarationAST *declarations;
+ unsigned rbrace_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual LinkageBodyAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT LinkageSpecificationAST: public DeclarationAST
+{
+public:
+ unsigned extern_token;
+ unsigned extern_type;
+ DeclarationAST *declaration;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual LinkageSpecificationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT MemInitializerAST: public AST
+{
+public:
+ NameAST *name;
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+ MemInitializerAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual MemInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NameAST: public ExpressionAST
+{
+public:
+ virtual NameAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT NestedNameSpecifierAST: public AST
+{
+public:
+ NameAST *class_or_namespace_name;
+ unsigned scope_token;
+ NestedNameSpecifierAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NestedNameSpecifierAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT QualifiedNameAST: public NameAST
+{
+public:
+ unsigned global_scope_token;
+ NestedNameSpecifierAST *nested_name_specifier;
+ NameAST *unqualified_name;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual QualifiedNameAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT OperatorFunctionIdAST: public NameAST
+{
+public:
+ unsigned operator_token;
+ OperatorAST *op;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual OperatorFunctionIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ConversionFunctionIdAST: public NameAST
+{
+public:
+ unsigned operator_token;
+ SpecifierAST *type_specifier;
+ PtrOperatorAST *ptr_operators;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ConversionFunctionIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST
+{
+public:
+ unsigned identifier_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual SimpleNameAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT DestructorNameAST: public NameAST
+{
+public:
+ unsigned tilde_token;
+ unsigned identifier_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual DestructorNameAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TemplateIdAST: public NameAST
+{
+public:
+ unsigned identifier_token;
+ unsigned less_token;
+ TemplateArgumentListAST *template_arguments;
+ unsigned greater_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TemplateIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NamespaceAST: public DeclarationAST
+{
+public:
+ unsigned namespace_token;
+ unsigned identifier_token;
+ SpecifierAST *attributes;
+ DeclarationAST *linkage_body;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NamespaceAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NamespaceAliasDefinitionAST: public DeclarationAST
+{
+public:
+ unsigned namespace_token;
+ unsigned namespace_name;
+ unsigned equal_token;
+ NameAST *name;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NamespaceAliasDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NewDeclaratorAST: public AST
+{
+public:
+ PtrOperatorAST *ptr_operators;
+ NewDeclaratorAST *declarator;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NewDeclaratorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NewExpressionAST: public ExpressionAST
+{
+public:
+ unsigned scope_token;
+ unsigned new_token;
+ ExpressionAST *expression;
+ ExpressionAST *type_id;
+ NewTypeIdAST *new_type_id;
+ NewInitializerAST *new_initializer;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NewExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NewInitializerAST: public AST
+{
+public:
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NewInitializerAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NewTypeIdAST: public AST
+{
+public:
+ SpecifierAST *type_specifier;
+ NewInitializerAST *new_initializer;
+ NewDeclaratorAST *new_declarator;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NewTypeIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT OperatorAST: public AST
+{
+public:
+ unsigned op_token;
+ unsigned open_token;
+ unsigned close_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual OperatorAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ParameterDeclarationAST: public DeclarationAST
+{
+public:
+ SpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ unsigned equal_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ParameterDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ParameterDeclarationClauseAST: public AST
+{
+public:
+ DeclarationAST *parameter_declarations;
+ unsigned dot_dot_dot_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ParameterDeclarationClauseAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT PostfixAST: public AST
+{
+public:
+ PostfixAST *next;
+
+public:
+ virtual PostfixAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT CallAST: public PostfixAST
+{
+public:
+ unsigned lparen_token;
+ ExpressionListAST *expression_list;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CallAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ArrayAccessAST: public PostfixAST
+{
+public:
+ unsigned lbracket_token;
+ ExpressionAST *expression;
+ unsigned rbracket_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ArrayAccessAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT PostIncrDecrAST: public PostfixAST
+{
+public:
+ unsigned incr_decr_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual PostIncrDecrAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT MemberAccessAST: public PostfixAST
+{
+public:
+ unsigned access_token;
+ unsigned template_token;
+ NameAST *member_name;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual MemberAccessAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypeidExpressionAST: public ExpressionAST
+{
+public:
+ unsigned typeid_token;
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypeidExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypenameCallExpressionAST: public ExpressionAST
+{
+public:
+ unsigned typename_token;
+ NameAST *name;
+ unsigned lparen_token;
+ ExpressionListAST *expression_list;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypenameCallExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypeConstructorCallAST: public ExpressionAST
+{
+public:
+ SpecifierAST *type_specifier;
+ unsigned lparen_token;
+ ExpressionListAST *expression_list;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypeConstructorCallAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT PostfixExpressionAST: public ExpressionAST
+{
+public:
+ ExpressionAST *base_expression;
+ PostfixAST *postfix_expressions;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual PostfixExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT PtrOperatorAST: public AST
+{
+public:
+ PtrOperatorAST *next;
+
+public:
+ virtual PtrOperatorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT PointerToMemberAST: public PtrOperatorAST
+{
+public:
+ unsigned global_scope_token;
+ NestedNameSpecifierAST *nested_name_specifier;
+ unsigned star_token;
+ SpecifierAST *cv_qualifier_seq;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual PointerToMemberAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT PointerAST: public PtrOperatorAST
+{
+public:
+ unsigned star_token;
+ SpecifierAST *cv_qualifier_seq;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual PointerAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ReferenceAST: public PtrOperatorAST
+{
+public:
+ unsigned amp_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ReferenceAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT BreakStatementAST: public StatementAST
+{
+public:
+ unsigned break_token;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual BreakStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ContinueStatementAST: public StatementAST
+{
+public:
+ unsigned continue_token;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ContinueStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT GotoStatementAST: public StatementAST
+{
+public:
+ unsigned goto_token;
+ unsigned identifier_token;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual GotoStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ReturnStatementAST: public StatementAST
+{
+public:
+ unsigned return_token;
+ ExpressionAST *expression;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ReturnStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT SizeofExpressionAST: public ExpressionAST
+{
+public:
+ unsigned sizeof_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual SizeofExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NumericLiteralAST: public ExpressionAST
+{
+public:
+ unsigned token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NumericLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT BoolLiteralAST: public ExpressionAST
+{
+public:
+ unsigned token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual BoolLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ThisExpressionAST: public ExpressionAST
+{
+public:
+ unsigned this_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ThisExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT NestedExpressionAST: public ExpressionAST
+{
+public:
+ unsigned lparen_token;
+ ExpressionAST *expression;
+ unsigned rparen_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual NestedExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT StringLiteralAST: public ExpressionAST
+{
+public:
+ unsigned token;
+ StringLiteralAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual StringLiteralAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT SwitchStatementAST: public StatementAST
+{
+public:
+ unsigned switch_token;
+ unsigned lparen_token;
+ ExpressionAST *condition;
+ unsigned rparen_token;
+ StatementAST *statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual SwitchStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TemplateArgumentListAST: public AST
+{
+public:
+ ExpressionAST *template_argument;
+ TemplateArgumentListAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TemplateArgumentListAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TemplateDeclarationAST: public DeclarationAST
+{
+public:
+ unsigned export_token;
+ unsigned template_token;
+ unsigned less_token;
+ DeclarationAST *template_parameters;
+ unsigned greater_token;
+ DeclarationAST *declaration;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TemplateDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ThrowExpressionAST: public ExpressionAST
+{
+public:
+ unsigned throw_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ThrowExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TranslationUnitAST: public AST
+{
+public:
+ DeclarationAST *declarations;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TranslationUnitAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TryBlockStatementAST: public StatementAST
+{
+public:
+ unsigned try_token;
+ StatementAST *statement;
+ CatchClauseAST *catch_clause_seq;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TryBlockStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT CatchClauseAST: public StatementAST
+{
+public:
+ unsigned catch_token;
+ unsigned lparen_token;
+ ExceptionDeclarationAST *exception_declaration;
+ unsigned rparen_token;
+ StatementAST *statement;
+ CatchClauseAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual CatchClauseAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypeIdAST: public ExpressionAST
+{
+public:
+ SpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypeIdAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TypenameTypeParameterAST: public DeclarationAST
+{
+public:
+ unsigned classkey_token;
+ NameAST *name;
+ unsigned equal_token;
+ ExpressionAST *type_id;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TypenameTypeParameterAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT TemplateTypeParameterAST: public DeclarationAST
+{
+public:
+ unsigned template_token;
+ unsigned less_token;
+ DeclarationAST *template_parameters;
+ unsigned greater_token;
+ unsigned class_token;
+ NameAST *name;
+ unsigned equal_token;
+ ExpressionAST *type_id;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual TemplateTypeParameterAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT UnaryExpressionAST: public ExpressionAST
+{
+public:
+ unsigned unary_op_token;
+ ExpressionAST *expression;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual UnaryExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT UsingAST: public DeclarationAST
+{
+public:
+ unsigned using_token;
+ unsigned typename_token;
+ NameAST *name;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual UsingAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT UsingDirectiveAST: public DeclarationAST
+{
+public:
+ unsigned using_token;
+ unsigned namespace_token;
+ NameAST *name;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual UsingDirectiveAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT WhileStatementAST: public StatementAST
+{
+public:
+ unsigned while_token;
+ unsigned lparen_token;
+ ExpressionAST *condition;
+ unsigned rparen_token;
+ StatementAST *statement;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual WhileStatementAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+
+// ObjC++
+class CPLUSPLUS_EXPORT IdentifierListAST: public AST
+{
+public:
+ unsigned identifier_token;
+ IdentifierListAST *next;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual IdentifierListAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCClassDeclarationAST: public DeclarationAST
+{
+public:
+ SpecifierAST *attributes;
+ unsigned class_token;
+ IdentifierListAST *identifier_list;
+ unsigned semicolon_token;
+
+public:
+ virtual unsigned firstToken() const;
+ virtual unsigned lastToken() const;
+
+ virtual ObjCClassDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+ virtual void accept0(ASTVisitor *visitor);
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_AST_H
diff --git a/src/shared/cplusplus/ASTVisitor.cpp b/src/shared/cplusplus/ASTVisitor.cpp
new file mode 100644
index 0000000000..7b9ca1ed7f
--- /dev/null
+++ b/src/shared/cplusplus/ASTVisitor.cpp
@@ -0,0 +1,105 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "ASTVisitor.h"
+#include "AST.h"
+#include "TranslationUnit.h"
+#include "Control.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+ASTVisitor::ASTVisitor(Control *control)
+ : _control(control)
+{ }
+
+ASTVisitor::~ASTVisitor()
+{ }
+
+void ASTVisitor::accept(AST *ast)
+{ AST::accept(ast, this); }
+
+Control *ASTVisitor::control() const
+{ return _control; }
+
+TranslationUnit *ASTVisitor::translationUnit() const
+{ return _control->translationUnit(); }
+
+int ASTVisitor::tokenKind(unsigned index) const
+{ return translationUnit()->tokenKind(index); }
+
+const char *ASTVisitor::spell(unsigned index) const
+{
+ if (! index)
+ return 0;
+
+ return translationUnit()->tokenAt(index).spell();
+}
+
+Identifier *ASTVisitor::identifier(unsigned index) const
+{ return translationUnit()->identifier(index); }
+
+Literal *ASTVisitor::literal(unsigned index) const
+{ return translationUnit()->literal(index); }
+
+NumericLiteral *ASTVisitor::numericLiteral(unsigned index) const
+{ return translationUnit()->numericLiteral(index); }
+
+StringLiteral *ASTVisitor::stringLiteral(unsigned index) const
+{ return translationUnit()->stringLiteral(index); }
+
+void ASTVisitor::getTokenPosition(unsigned index,
+ unsigned *line,
+ unsigned *column,
+ StringLiteral **fileName) const
+{ translationUnit()->getTokenPosition(index, line, column, fileName); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
new file mode 100644
index 0000000000..f8d2d6790e
--- /dev/null
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -0,0 +1,200 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_ASTVISITOR_H
+#define CPLUSPLUS_ASTVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT ASTVisitor
+{
+ ASTVisitor(const ASTVisitor &other);
+ void operator =(const ASTVisitor &other);
+
+public:
+ ASTVisitor(Control *control);
+ virtual ~ASTVisitor();
+
+ Control *control() const;
+ TranslationUnit *translationUnit() const;
+
+ int tokenKind(unsigned index) const;
+ const char *spell(unsigned index) const;
+ Identifier *identifier(unsigned index) const;
+ Literal *literal(unsigned index) const;
+ NumericLiteral *numericLiteral(unsigned index) const;
+ StringLiteral *stringLiteral(unsigned index) const;
+
+ void getTokenPosition(unsigned index,
+ unsigned *line,
+ unsigned *column = 0,
+ StringLiteral **fileName = 0) const;
+
+ void accept(AST *ast);
+
+ virtual bool preVisit(AST *) { return true; }
+ virtual void postVisit(AST *) {}
+
+ virtual bool visit(AccessDeclarationAST *) { return true; }
+ virtual bool visit(ArrayAccessAST *) { return true; }
+ virtual bool visit(ArrayDeclaratorAST *) { return true; }
+ virtual bool visit(ArrayInitializerAST *) { return true; }
+ virtual bool visit(AsmDefinitionAST *) { return true; }
+ virtual bool visit(AttributeSpecifierAST *) { return true; }
+ virtual bool visit(AttributeAST *) { return true; }
+ virtual bool visit(BaseSpecifierAST *) { return true; }
+ virtual bool visit(BinaryExpressionAST *) { return true; }
+ virtual bool visit(BoolLiteralAST *) { return true; }
+ virtual bool visit(BreakStatementAST *) { return true; }
+ virtual bool visit(CallAST *) { return true; }
+ virtual bool visit(CaseStatementAST *) { return true; }
+ virtual bool visit(CastExpressionAST *) { return true; }
+ virtual bool visit(CatchClauseAST *) { return true; }
+ virtual bool visit(ClassSpecifierAST *) { return true; }
+ virtual bool visit(CompoundLiteralAST *) { return true; }
+ virtual bool visit(CompoundStatementAST *) { return true; }
+ virtual bool visit(ConditionAST *) { return true; }
+ virtual bool visit(ConditionalExpressionAST *) { return true; }
+ virtual bool visit(ContinueStatementAST *) { return true; }
+ virtual bool visit(ConversionFunctionIdAST *) { return true; }
+ virtual bool visit(CppCastExpressionAST *) { return true; }
+ virtual bool visit(CtorInitializerAST *) { return true; }
+ virtual bool visit(DeclaratorAST *) { return true; }
+ virtual bool visit(DeclarationStatementAST *) { return true; }
+ virtual bool visit(DeclaratorIdAST *) { return true; }
+ virtual bool visit(DeclaratorListAST *) { return true; }
+ virtual bool visit(DeleteExpressionAST *) { return true; }
+ virtual bool visit(DestructorNameAST *) { return true; }
+ virtual bool visit(DoStatementAST *) { return true; }
+ virtual bool visit(ElaboratedTypeSpecifierAST *) { return true; }
+ virtual bool visit(EmptyDeclarationAST *) { return true; }
+ virtual bool visit(EnumSpecifierAST *) { return true; }
+ virtual bool visit(EnumeratorAST *) { return true; }
+ virtual bool visit(ExceptionDeclarationAST *) { return true; }
+ virtual bool visit(ExceptionSpecificationAST *) { return true; }
+ virtual bool visit(ExpressionListAST *) { return true; }
+ virtual bool visit(ExpressionOrDeclarationStatementAST *) { return true; }
+ virtual bool visit(ExpressionStatementAST *) { return true; }
+ virtual bool visit(ForStatementAST *) { return true; }
+ virtual bool visit(FunctionDeclaratorAST *) { return true; }
+ virtual bool visit(FunctionDefinitionAST *) { return true; }
+ virtual bool visit(GotoStatementAST *) { return true; }
+ virtual bool visit(IfStatementAST *) { return true; }
+ virtual bool visit(LabeledStatementAST *) { return true; }
+ virtual bool visit(LinkageBodyAST *) { return true; }
+ virtual bool visit(LinkageSpecificationAST *) { return true; }
+ virtual bool visit(MemInitializerAST *) { return true; }
+ virtual bool visit(MemberAccessAST *) { return true; }
+ virtual bool visit(NamedTypeSpecifierAST *) { return true; }
+ virtual bool visit(NamespaceAST *) { return true; }
+ virtual bool visit(NamespaceAliasDefinitionAST *) { return true; }
+ virtual bool visit(NestedDeclaratorAST *) { return true; }
+ virtual bool visit(NestedExpressionAST *) { return true; }
+ virtual bool visit(NestedNameSpecifierAST *) { return true; }
+ virtual bool visit(NewDeclaratorAST *) { return true; }
+ virtual bool visit(NewExpressionAST *) { return true; }
+ virtual bool visit(NewInitializerAST *) { return true; }
+ virtual bool visit(NewTypeIdAST *) { return true; }
+ virtual bool visit(NumericLiteralAST *) { return true; }
+ virtual bool visit(OperatorAST *) { return true; }
+ virtual bool visit(OperatorFunctionIdAST *) { return true; }
+ virtual bool visit(ParameterDeclarationAST *) { return true; }
+ virtual bool visit(ParameterDeclarationClauseAST *) { return true; }
+ virtual bool visit(PointerAST *) { return true; }
+ virtual bool visit(PointerToMemberAST *) { return true; }
+ virtual bool visit(PostIncrDecrAST *) { return true; }
+ virtual bool visit(PostfixExpressionAST *) { return true; }
+ virtual bool visit(QualifiedNameAST *) { return true; }
+ virtual bool visit(ReferenceAST *) { return true; }
+ virtual bool visit(ReturnStatementAST *) { return true; }
+ virtual bool visit(SimpleDeclarationAST *) { return true; }
+ virtual bool visit(SimpleNameAST *) { return true; }
+ virtual bool visit(SimpleSpecifierAST *) { return true; }
+ virtual bool visit(SizeofExpressionAST *) { return true; }
+ virtual bool visit(StringLiteralAST *) { return true; }
+ virtual bool visit(SwitchStatementAST *) { return true; }
+ virtual bool visit(TemplateArgumentListAST *) { return true; }
+ virtual bool visit(TemplateDeclarationAST *) { return true; }
+ virtual bool visit(TemplateIdAST *) { return true; }
+ virtual bool visit(TemplateTypeParameterAST *) { return true; }
+ virtual bool visit(ThisExpressionAST *) { return true; }
+ virtual bool visit(ThrowExpressionAST *) { return true; }
+ virtual bool visit(TranslationUnitAST *) { return true; }
+ virtual bool visit(TryBlockStatementAST *) { return true; }
+ virtual bool visit(TypeConstructorCallAST *) { return true; }
+ virtual bool visit(TypeIdAST *) { return true; }
+ virtual bool visit(TypeidExpressionAST *) { return true; }
+ virtual bool visit(TypeofSpecifierAST *) { return true; }
+ virtual bool visit(TypenameCallExpressionAST *) { return true; }
+ virtual bool visit(TypenameTypeParameterAST *) { return true; }
+ virtual bool visit(UnaryExpressionAST *) { return true; }
+ virtual bool visit(UsingAST *) { return true; }
+ virtual bool visit(UsingDirectiveAST *) { return true; }
+ virtual bool visit(WhileStatementAST *) { return true; }
+ virtual bool visit(QtMethodAST *) { return true; }
+
+ // ObjC++
+ virtual bool visit(IdentifierListAST *) { return true; }
+ virtual bool visit(ObjCClassDeclarationAST *) { return true; }
+
+private:
+ Control *_control;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_ASTVISITOR_H
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
new file mode 100644
index 0000000000..b4f5283a74
--- /dev/null
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_ASTFWD_H
+#define CPLUSPLUS_ASTFWD_H
+
+#include <CPlusPlusForwardDeclarations.h>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class AST;
+class ASTVisitor;
+
+class AccessDeclarationAST;
+class ArrayAccessAST;
+class ArrayDeclaratorAST;
+class ArrayInitializerAST;
+class AsmDefinitionAST;
+class AttributeAST;
+class AttributeSpecifierAST;
+class BaseSpecifierAST;
+class BinaryExpressionAST;
+class BoolLiteralAST;
+class BreakStatementAST;
+class CallAST;
+class CaseStatementAST;
+class CastExpressionAST;
+class CatchClauseAST;
+class ClassSpecifierAST;
+class CompoundLiteralAST;
+class CompoundStatementAST;
+class ConditionAST;
+class ConditionalExpressionAST;
+class ContinueStatementAST;
+class ConversionFunctionIdAST;
+class CoreDeclaratorAST;
+class CppCastExpressionAST;
+class CtorInitializerAST;
+class DeclarationAST;
+class DeclarationStatementAST;
+class DeclaratorAST;
+class DeclaratorIdAST;
+class DeclaratorListAST;
+class DeleteExpressionAST;
+class DestructorNameAST;
+class DoStatementAST;
+class ElaboratedTypeSpecifierAST;
+class EmptyDeclarationAST;
+class EnumSpecifierAST;
+class EnumeratorAST;
+class ExceptionDeclarationAST;
+class ExceptionSpecificationAST;
+class ExpressionAST;
+class ExpressionListAST;
+class ExpressionOrDeclarationStatementAST;
+class ExpressionStatementAST;
+class ForStatementAST;
+class FunctionDeclaratorAST;
+class FunctionDefinitionAST;
+class GotoStatementAST;
+class IfStatementAST;
+class LabeledStatementAST;
+class LinkageBodyAST;
+class LinkageSpecificationAST;
+class MemInitializerAST;
+class MemberAccessAST;
+class NameAST;
+class NamedTypeSpecifierAST;
+class NamespaceAST;
+class NamespaceAliasDefinitionAST;
+class NestedDeclaratorAST;
+class NestedExpressionAST;
+class NestedNameSpecifierAST;
+class NewDeclaratorAST;
+class NewExpressionAST;
+class NewInitializerAST;
+class NewTypeIdAST;
+class NumericLiteralAST;
+class OperatorAST;
+class OperatorFunctionIdAST;
+class ParameterDeclarationAST;
+class ParameterDeclarationClauseAST;
+class PointerAST;
+class PointerToMemberAST;
+class PostIncrDecrAST;
+class PostfixAST;
+class PostfixDeclaratorAST;
+class PostfixExpressionAST;
+class PtrOperatorAST;
+class QualifiedNameAST;
+class ReferenceAST;
+class ReturnStatementAST;
+class SimpleDeclarationAST;
+class SimpleNameAST;
+class SimpleSpecifierAST;
+class SizeofExpressionAST;
+class SpecifierAST;
+class StatementAST;
+class StringLiteralAST;
+class SwitchStatementAST;
+class TemplateArgumentListAST;
+class TemplateDeclarationAST;
+class TemplateIdAST;
+class TemplateTypeParameterAST;
+class ThisExpressionAST;
+class ThrowExpressionAST;
+class TranslationUnitAST;
+class TryBlockStatementAST;
+class TypeConstructorCallAST;
+class TypeIdAST;
+class TypeidExpressionAST;
+class TypenameCallExpressionAST;
+class TypenameTypeParameterAST;
+class TypeofSpecifierAST;
+class UnaryExpressionAST;
+class UsingAST;
+class UsingDirectiveAST;
+class WhileStatementAST;
+class QtMethodAST;
+
+// ObjC++
+class IdentifierListAST;
+class ObjCClassDeclarationAST;
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_ASTFWD_H
diff --git a/src/shared/cplusplus/Array.cpp b/src/shared/cplusplus/Array.cpp
new file mode 100644
index 0000000000..7159008fd4
--- /dev/null
+++ b/src/shared/cplusplus/Array.cpp
@@ -0,0 +1,34 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "Array.h"
diff --git a/src/shared/cplusplus/Array.h b/src/shared/cplusplus/Array.h
new file mode 100644
index 0000000000..c639affc89
--- /dev/null
+++ b/src/shared/cplusplus/Array.h
@@ -0,0 +1,135 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_ARRAY_H
+#define CPLUSPLUS_ARRAY_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <new>
+#include <cstdlib>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+template <typename _Tp, int SEGMENT_SHIFT = 4>
+class Array
+{
+ Array(const Array &other);
+ void operator =(const Array &other);
+
+public:
+ Array()
+ : _segments(0),
+ _allocatedSegments(0),
+ _segmentCount(-1),
+ _allocatedElements(0),
+ _count(-1)
+ { }
+
+ ~Array()
+ {
+ if (_segments) {
+ for (int index = 0; index <= _segmentCount; ++index) {
+ delete[] (_segments[index] + (index << SEGMENT_SHIFT));
+ }
+ free(_segments);
+ }
+ }
+
+ inline unsigned size() const
+ { return _count + 1; }
+
+ inline unsigned count() const
+ { return _count + 1; }
+
+ inline const _Tp &at(unsigned index) const
+ { return _segments[index >> SEGMENT_SHIFT][index]; }
+
+ inline const _Tp &operator[](unsigned index) const
+ { return _segments[index >> SEGMENT_SHIFT][index]; }
+
+ inline _Tp &operator[](unsigned index)
+ { return _segments[index >> SEGMENT_SHIFT][index]; }
+
+ void push_back(const _Tp &value)
+ {
+ if (++_count == _allocatedElements) {
+ if (++_segmentCount == _allocatedSegments) {
+ _allocatedSegments += 4;
+ _segments = (_Tp **) realloc(_segments, _allocatedSegments * sizeof(_Tp *));
+ }
+
+ _Tp *segment = new _Tp[SEGMENT_SIZE];
+ _segments[_segmentCount] = segment - (_segmentCount << SEGMENT_SHIFT);
+ _allocatedElements += SEGMENT_SIZE;
+ }
+
+ _segments[_count >> SEGMENT_SHIFT][_count] = value;
+ }
+
+private:
+ enum {
+ SEGMENT_SIZE = 1 << SEGMENT_SHIFT
+ };
+
+ _Tp **_segments;
+ int _allocatedSegments;
+ int _segmentCount;
+
+ int _allocatedElements;
+ int _count;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_ARRAY_H
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
new file mode 100644
index 0000000000..31b01bfd81
--- /dev/null
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -0,0 +1,140 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+
+#ifdef HAVE_QT
+# include <QtCore/qglobal.h>
+# define CPLUSPLUS_BEGIN_HEADER
+# define CPLUSPLUS_END_HEADER
+# if defined(CPLUSPLUS_BUILD_LIB)
+# define CPLUSPLUS_EXPORT Q_DECL_EXPORT
+# else
+# define CPLUSPLUS_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define CPLUSPLUS_BEGIN_HEADER
+# define CPLUSPLUS_END_HEADER
+# define CPLUSPLUS_EXPORT
+#endif
+
+#ifdef CPLUSPLUS_WITH_NAMESPACE
+# define CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
+# define CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPLus
+# define CPLUSPLUS_USE_NAMESPACE using namespace CPlusPlus;
+#else
+# define CPLUSPLUS_BEGIN_NAMESPACE
+# define CPLUSPLUS_END_NAMESPACE
+# define CPLUSPLUS_USE_NAMESPACE ;
+#endif
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class TranslationUnit;
+class Semantic;
+class Control;
+class MemoryPool;
+class DiagnosticClient;
+
+class Identifier;
+class Literal;
+class StringLiteral;
+class NumericLiteral;
+
+class Scope;
+
+// names
+class NameVisitor;
+class Name;
+class NameId;
+class TemplateNameId;
+class DestructorNameId;
+class OperatorNameId;
+class ConversionNameId;
+class QualifiedNameId;
+
+// types
+class FullySpecifiedType;
+class TypeVisitor;
+class Type;
+class VoidType;
+class IntegerType;
+class FloatType;
+class PointerToMemberType;
+class PointerType;
+class ReferenceType;
+class ArrayType;
+class NamedType;
+
+// symbols
+class SymbolVisitor;
+class Symbol;
+class ScopedSymbol;
+class UsingNamespaceDirective;
+class UsingDeclaration;
+class Declaration;
+class Argument;
+class Function;
+class Namespace;
+class BaseClass;
+class Block;
+class Class;
+class Enum;
+
+class Use;
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
new file mode 100644
index 0000000000..610d57626f
--- /dev/null
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -0,0 +1,374 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckDeclaration.h"
+#include "Semantic.h"
+#include "AST.h"
+#include "TranslationUnit.h"
+#include "Scope.h"
+#include "Names.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Control.h"
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckDeclaration::CheckDeclaration(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _declaration(0),
+ _scope(0),
+ _templateParameters(0),
+ _checkAnonymousArguments(false)
+{ }
+
+CheckDeclaration::~CheckDeclaration()
+{ }
+
+void CheckDeclaration::check(DeclarationAST *declaration,
+ Scope *scope, Scope *templateParameters)
+{
+ Scope *previousScope = switchScope(scope);
+ Scope *previousTemplateParameters = switchTemplateParameters(templateParameters);
+ DeclarationAST *previousDeclaration = switchDeclaration(declaration);
+ accept(declaration);
+ (void) switchDeclaration(previousDeclaration);
+ (void) switchTemplateParameters(previousTemplateParameters);
+ (void) switchScope(previousScope);
+}
+
+DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration)
+{
+ DeclarationAST *previousDeclaration = _declaration;
+ _declaration = declaration;
+ return previousDeclaration;
+}
+
+Scope *CheckDeclaration::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+Scope *CheckDeclaration::switchTemplateParameters(Scope *templateParameters)
+{
+ Scope *previousTemplateParameters = _templateParameters;
+ _templateParameters = templateParameters;
+ return previousTemplateParameters;
+}
+
+void CheckDeclaration::checkFunctionArguments(Function *fun)
+{
+ if (! _checkAnonymousArguments)
+ return;
+
+ if (_scope->isClassScope() && fun->isPublic()) {
+ for (unsigned argc = 0; argc < fun->argumentCount(); ++argc) {
+ Argument *arg = fun->argumentAt(argc)->asArgument();
+ assert(arg != 0);
+
+ if (! arg->name()) {
+ translationUnit()->warning(arg->sourceLocation(),
+ "anonymous argument");
+ }
+ }
+ }
+}
+
+bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
+{
+ FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope);
+ FullySpecifiedType qualTy = ty.qualifiedType();
+
+ if (_templateParameters) {
+ if (Class *klass = ty->asClass()) {
+ klass->setTemplateParameters(_templateParameters);
+ }
+ }
+
+ for (DeclaratorListAST *it = ast->declarators; it; it = it->next) {
+ Name *name = 0;
+ FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy,
+ _scope, &name);
+
+ if (Function *fun = declTy->asFunction()) {
+ fun->setScope(_scope);
+ fun->setName(name);
+ fun->setMethodKey(semantic()->currentMethodKey());
+ fun->setVisibility(semantic()->currentVisibility());
+ } else if (semantic()->currentMethodKey() != Function::NormalMethod) {
+ translationUnit()->warning(ast->firstToken(),
+ "expected a function declaration");
+ }
+
+ unsigned location = 0;
+ if (it->declarator)
+ location = it->declarator->firstToken();
+ else
+ location = ast->firstToken();
+
+ Declaration *symbol = control()->newDeclaration(location, name);
+ symbol->setType(control()->integerType(IntegerType::Int));
+ symbol->setType(declTy);
+
+ if (_templateParameters && it == ast->declarators && ! ty->asClass())
+ symbol->setTemplateParameters(_templateParameters);
+
+ symbol->setVisibility(semantic()->currentVisibility());
+
+ if (ty.isFriend())
+ symbol->setStorage(Symbol::Friend);
+ else if (ty.isRegister())
+ symbol->setStorage(Symbol::Register);
+ else if (ty.isStatic())
+ symbol->setStorage(Symbol::Static);
+ else if (ty.isExtern())
+ symbol->setStorage(Symbol::Extern);
+ else if (ty.isMutable())
+ symbol->setStorage(Symbol::Mutable);
+ else if (ty.isTypedef())
+ symbol->setStorage(Symbol::Typedef);
+
+ _scope->enterSymbol(symbol);
+ }
+ return false;
+}
+
+bool CheckDeclaration::visit(EmptyDeclarationAST *)
+{
+ return false;
+}
+
+bool CheckDeclaration::visit(AccessDeclarationAST *ast)
+{
+ int accessSpecifier = tokenKind(ast->access_specifier_token);
+ int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier);
+ semantic()->switchVisibility(visibility);
+ if (ast->slots_token)
+ semantic()->switchMethodKey(Function::SlotMethod);
+ else if (accessSpecifier == T_SIGNALS)
+ semantic()->switchMethodKey(Function::SignalMethod);
+ else
+ semantic()->switchMethodKey(Function::NormalMethod);
+ return false;
+}
+
+bool CheckDeclaration::visit(AsmDefinitionAST *)
+{
+ return false;
+}
+
+bool CheckDeclaration::visit(ExceptionDeclarationAST *)
+{
+ return false;
+}
+
+bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
+{
+ FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope);
+ FullySpecifiedType qualTy = ty.qualifiedType();
+ Name *name = 0;
+ FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy,
+ _scope, &name);
+ Function *fun = funTy->asFunction();
+ if (! fun) {
+ translationUnit()->error(ast->firstToken(),
+ "expected a function prototype");
+ return false;
+ }
+
+ fun->setName(name);
+ fun->setTemplateParameters(_templateParameters);
+ fun->setVisibility(semantic()->currentVisibility());
+ fun->setMethodKey(semantic()->currentMethodKey());
+
+ checkFunctionArguments(fun);
+
+ _scope->enterSymbol(fun);
+
+ if (ast->ctor_initializer) {
+ bool looksLikeCtor = false;
+ if (ty.isValid() || ! fun->identity())
+ looksLikeCtor = false;
+ else if (fun->identity()->isNameId() || fun->identity()->isTemplateNameId())
+ looksLikeCtor = true;
+
+ if (! looksLikeCtor) {
+ translationUnit()->error(ast->ctor_initializer->firstToken(),
+ "only constructors take base initializers");
+ }
+ }
+
+ const int previousVisibility = semantic()->switchVisibility(Symbol::Public);
+ const int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod);
+
+ semantic()->check(ast->function_body, fun->members());
+
+ semantic()->switchMethodKey(previousMethodKey);
+ semantic()->switchVisibility(previousVisibility);
+
+ if (ast->next && ast->next->asEmptyDeclaration()) {
+ translationUnit()->warning(ast->next->firstToken(),
+ "unnecessary semicolon after function block");
+ }
+
+ return false;
+}
+
+bool CheckDeclaration::visit(LinkageBodyAST *ast)
+{
+ for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) {
+ semantic()->check(decl, _scope);
+ }
+ return false;
+}
+
+bool CheckDeclaration::visit(LinkageSpecificationAST *ast)
+{
+ for (DeclarationAST *decl = ast->declaration; decl; decl = decl->next) {
+ semantic()->check(decl, _scope);
+ }
+ return false;
+}
+
+bool CheckDeclaration::visit(NamespaceAST *ast)
+{
+ Identifier *id = identifier(ast->identifier_token);
+ Name *namespaceName = control()->nameId(id);
+ Namespace *ns = control()->newNamespace(ast->firstToken(), namespaceName);
+ _scope->enterSymbol(ns);
+ semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later.
+
+ if (ast->next && ast->next->asEmptyDeclaration()) {
+ translationUnit()->warning(ast->next->firstToken(),
+ "unnecessary semicolon after namespace");
+ }
+
+ return false;
+}
+
+bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *)
+{
+ return false;
+}
+
+bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
+{
+ Name *argName = 0;
+ FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope);
+ FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(),
+ _scope, &argName);
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ Argument *arg = control()->newArgument(ast->firstToken(), argName);
+ if (ast->expression)
+ arg->setInitializer(true);
+ arg->setType(argTy);
+ _scope->enterSymbol(arg);
+ return false;
+}
+
+bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
+{
+/*
+ Template *templ = control()->newTemplate(ast->firstToken());
+
+ for (DeclarationAST *param = ast->template_parameters; param;
+ param = param->next) {
+ semantic()->check(param, templ->members());
+ }
+*/
+
+ Scope *previousScope = switchScope(new Scope(_scope->owner()));
+ for (DeclarationAST *param = ast->template_parameters; param;
+ param = param->next) {
+ semantic()->check(param, _scope);
+ }
+
+ Scope *templateParameters = switchScope(previousScope);
+ semantic()->check(ast->declaration, _scope, templateParameters);
+ return false;
+}
+
+bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type
+ _scope->enterSymbol(arg);
+ return false;
+}
+
+bool CheckDeclaration::visit(TemplateTypeParameterAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type
+ _scope->enterSymbol(arg);
+ return false;
+}
+
+bool CheckDeclaration::visit(UsingAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ UsingDeclaration *u = control()->newUsingDeclaration(ast->firstToken(), name);
+ _scope->enterSymbol(u);
+ return false;
+}
+
+bool CheckDeclaration::visit(UsingDirectiveAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name);
+ _scope->enterSymbol(u);
+ return false;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h
new file mode 100644
index 0000000000..6e82678fa0
--- /dev/null
+++ b/src/shared/cplusplus/CheckDeclaration.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKDECLARATION_H
+#define CPLUSPLUS_CHECKDECLARATION_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckDeclaration: public SemanticCheck
+{
+public:
+ CheckDeclaration(Semantic *semantic);
+ virtual ~CheckDeclaration();
+
+ void check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters);
+
+protected:
+ DeclarationAST *switchDeclaration(DeclarationAST *declaration);
+ Scope *switchScope(Scope *scope);
+ Scope *switchTemplateParameters(Scope *templateParameters);
+
+ void checkFunctionArguments(Function *fun);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(SimpleDeclarationAST *ast);
+ virtual bool visit(EmptyDeclarationAST *ast);
+ virtual bool visit(AccessDeclarationAST *ast);
+ virtual bool visit(AsmDefinitionAST *ast);
+ virtual bool visit(ExceptionDeclarationAST *ast);
+ virtual bool visit(FunctionDefinitionAST *ast);
+ virtual bool visit(LinkageBodyAST *ast);
+ virtual bool visit(LinkageSpecificationAST *ast);
+ virtual bool visit(NamespaceAST *ast);
+ virtual bool visit(NamespaceAliasDefinitionAST *ast);
+ virtual bool visit(ParameterDeclarationAST *ast);
+ virtual bool visit(TemplateDeclarationAST *ast);
+ virtual bool visit(TypenameTypeParameterAST *ast);
+ virtual bool visit(TemplateTypeParameterAST *ast);
+ virtual bool visit(UsingAST *ast);
+ virtual bool visit(UsingDirectiveAST *ast);
+
+private:
+ DeclarationAST *_declaration;
+ Scope *_scope;
+ Scope *_templateParameters;
+ bool _checkAnonymousArguments: 1;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKDECLARATION_H
diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp
new file mode 100644
index 0000000000..13120fec58
--- /dev/null
+++ b/src/shared/cplusplus/CheckDeclarator.cpp
@@ -0,0 +1,258 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckDeclarator.h"
+#include "Semantic.h"
+#include "AST.h"
+#include "Control.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckDeclarator::CheckDeclarator(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _declarator(0),
+ _scope(0),
+ _name(0)
+{ }
+
+CheckDeclarator::~CheckDeclarator()
+{ }
+
+FullySpecifiedType CheckDeclarator::check(DeclaratorAST *declarator,
+ FullySpecifiedType type,
+ Scope *scope,
+ Name **name)
+{
+ FullySpecifiedType previousType = switchFullySpecifiedType(type);
+ Scope *previousScope = switchScope(scope);
+ DeclaratorAST *previousDeclarator = switchDeclarator(declarator);
+ Name **previousName = switchName(name);
+ accept(declarator);
+ (void) switchName(previousName);
+ (void) switchDeclarator(previousDeclarator);
+ (void) switchScope(previousScope);
+ return switchFullySpecifiedType(previousType);
+}
+
+FullySpecifiedType CheckDeclarator::check(PtrOperatorAST *ptrOperators,
+ FullySpecifiedType type,
+ Scope *scope)
+{
+ FullySpecifiedType previousType = switchFullySpecifiedType(type);
+ Scope *previousScope = switchScope(scope);
+ accept(ptrOperators);
+ (void) switchScope(previousScope);
+ return switchFullySpecifiedType(previousType);
+}
+
+DeclaratorAST *CheckDeclarator::switchDeclarator(DeclaratorAST *declarator)
+{
+ DeclaratorAST *previousDeclarator = _declarator;
+ _declarator = declarator;
+ return previousDeclarator;
+}
+
+FullySpecifiedType CheckDeclarator::switchFullySpecifiedType(FullySpecifiedType type)
+{
+ FullySpecifiedType previousType = _fullySpecifiedType;
+ _fullySpecifiedType = type;
+ return previousType;
+}
+
+Scope *CheckDeclarator::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+Name **CheckDeclarator::switchName(Name **name)
+{
+ Name **previousName = _name;
+ _name = name;
+ return previousName;
+}
+
+bool CheckDeclarator::visit(DeclaratorAST *ast)
+{
+ accept(ast->ptr_operators);
+ accept(ast->postfix_declarators);
+ accept(ast->core_declarator);
+
+ // ### check the initializer
+ // FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope);
+
+ if (ast->initializer && _fullySpecifiedType->isFunction()) {
+ _fullySpecifiedType->asFunction()->setPureVirtual(true);
+ }
+ return false;
+}
+
+bool CheckDeclarator::visit(DeclaratorIdAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ if (_name)
+ *_name = name;
+ return false;
+}
+
+bool CheckDeclarator::visit(NestedDeclaratorAST *ast)
+{
+ accept(ast->declarator);
+ return false;
+}
+
+bool CheckDeclarator::visit(FunctionDeclaratorAST *ast)
+{
+ Function *fun = control()->newFunction(ast->firstToken());
+ fun->setReturnType(_fullySpecifiedType);
+
+ if (ast->parameters) {
+ DeclarationAST *parameter_declarations = ast->parameters->parameter_declarations;
+ for (DeclarationAST *decl = parameter_declarations; decl; decl = decl->next) {
+ semantic()->check(decl, fun->arguments());
+ }
+
+ if (ast->parameters->dot_dot_dot_token)
+ fun->setVariadic(true);
+ }
+
+ // check the arguments
+ bool hasDefaultArguments = false;
+ for (unsigned i = 0; i < fun->argumentCount(); ++i) {
+ Argument *arg = fun->argumentAt(i)->asArgument();
+ if (hasDefaultArguments && ! arg->hasInitializer()) {
+ translationUnit()->error(ast->firstToken(),
+ "default argument missing for parameter at position %d", i + 1);
+ } else if (! hasDefaultArguments) {
+ hasDefaultArguments = arg->hasInitializer();
+ }
+ }
+
+ FullySpecifiedType funTy(fun);
+ _fullySpecifiedType = funTy;
+
+ for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+ SimpleSpecifierAST *cv = static_cast<SimpleSpecifierAST *>(it);
+ int k = tokenKind(cv->specifier_token);
+ if (k == T_CONST)
+ fun->setConst(true);
+ else if (k == T_VOLATILE)
+ fun->setVolatile(true);
+ }
+
+ accept(ast->next);
+ return false;
+}
+
+bool CheckDeclarator::visit(ArrayDeclaratorAST *ast)
+{
+ ArrayType *ty = control()->arrayType(_fullySpecifiedType); // ### set the dimension
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ FullySpecifiedType arrTy(ty);
+ _fullySpecifiedType = ty;
+ accept(ast->next);
+ return false;
+}
+
+bool CheckDeclarator::visit(PointerToMemberAST *ast)
+{
+ Name *memberName = semantic()->check(ast->nested_name_specifier, _scope);
+ PointerToMemberType *ptrTy = control()->pointerToMemberType(memberName, _fullySpecifiedType);
+ FullySpecifiedType ty(ptrTy);
+ _fullySpecifiedType = ty;
+ applyCvQualifiers(ast->cv_qualifier_seq);
+ accept(ast->next);
+ return false;
+}
+
+bool CheckDeclarator::visit(PointerAST *ast)
+{
+ PointerType *ptrTy = control()->pointerType(_fullySpecifiedType);
+ FullySpecifiedType ty(ptrTy);
+ _fullySpecifiedType = ty;
+ applyCvQualifiers(ast->cv_qualifier_seq);
+ accept(ast->next);
+ return false;
+}
+
+bool CheckDeclarator::visit(ReferenceAST *ast)
+{
+ ReferenceType *refTy = control()->referenceType(_fullySpecifiedType);
+ FullySpecifiedType ty(refTy);
+ _fullySpecifiedType = ty;
+ accept(ast->next);
+ return false;
+}
+
+void CheckDeclarator::applyCvQualifiers(SpecifierAST *cv)
+{
+ for (; cv; cv = cv->next) {
+ SimpleSpecifierAST *spec = static_cast<SimpleSpecifierAST *>(cv);
+ switch (translationUnit()->tokenKind(spec->specifier_token)) {
+ case T_VOLATILE:
+ _fullySpecifiedType.setVolatile(true);
+ break;
+ case T_CONST:
+ _fullySpecifiedType.setConst(true);
+ break;
+ default:
+ break;
+ } // switch
+ }
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckDeclarator.h b/src/shared/cplusplus/CheckDeclarator.h
new file mode 100644
index 0000000000..b1de623b00
--- /dev/null
+++ b/src/shared/cplusplus/CheckDeclarator.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKDECLARATOR_H
+#define CPLUSPLUS_CHECKDECLARATOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+#include "FullySpecifiedType.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckDeclarator: public SemanticCheck
+{
+public:
+ CheckDeclarator(Semantic *semantic);
+ virtual ~CheckDeclarator();
+
+ FullySpecifiedType check(DeclaratorAST *declarator,
+ FullySpecifiedType type,
+ Scope *scope,
+ Name **name);
+
+ FullySpecifiedType check(PtrOperatorAST *ptrOperators,
+ FullySpecifiedType type,
+ Scope *scope);
+
+protected:
+ DeclaratorAST *switchDeclarator(DeclaratorAST *declarator);
+ FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type);
+ Scope *switchScope(Scope *scope);
+ Name **switchName(Name **name);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(DeclaratorAST *ast);
+ // ptr operators
+ virtual bool visit(PointerToMemberAST *ast);
+ virtual bool visit(PointerAST *ast);
+ virtual bool visit(ReferenceAST *ast);
+ // core declarators
+ virtual bool visit(DeclaratorIdAST *ast);
+ virtual bool visit(NestedDeclaratorAST *ast);
+ // postfix declarators
+ virtual bool visit(FunctionDeclaratorAST *ast);
+ virtual bool visit(ArrayDeclaratorAST *ast);
+
+ void applyCvQualifiers(SpecifierAST *cv);
+
+private:
+ DeclaratorAST *_declarator;
+ Scope *_scope;
+ Name **_name;
+ FullySpecifiedType _fullySpecifiedType;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKDECLARATOR_H
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
new file mode 100644
index 0000000000..e546a99a53
--- /dev/null
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -0,0 +1,369 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckExpression.h"
+#include "Semantic.h"
+#include "TranslationUnit.h"
+#include "AST.h"
+#include "Scope.h"
+#include "Literals.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Control.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckExpression::CheckExpression(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _expression(0),
+ _scope(0),
+ _checkOldStyleCasts(false)
+{ }
+
+CheckExpression::~CheckExpression()
+{ }
+
+FullySpecifiedType CheckExpression::check(ExpressionAST *expression, Scope *scope)
+{
+ FullySpecifiedType previousType = switchFullySpecifiedType(FullySpecifiedType());
+ Scope *previousScope = switchScope(scope);
+ ExpressionAST *previousExpression = switchExpression(expression);
+ accept(expression);
+ (void) switchExpression(previousExpression);
+ (void) switchScope(previousScope);
+ return switchFullySpecifiedType(previousType);
+}
+
+ExpressionAST *CheckExpression::switchExpression(ExpressionAST *expression)
+{
+ ExpressionAST *previousExpression = _expression;
+ _expression = expression;
+ return previousExpression;
+}
+
+FullySpecifiedType CheckExpression::switchFullySpecifiedType(FullySpecifiedType type)
+{
+ FullySpecifiedType previousType = _fullySpecifiedType;
+ _fullySpecifiedType = type;
+ return previousType;
+}
+
+Scope *CheckExpression::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+bool CheckExpression::visit(ExpressionListAST *ast)
+{
+ for (ExpressionListAST *it = ast; it; it = it->next) {
+ FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+ }
+ return false;
+}
+
+bool CheckExpression::visit(BinaryExpressionAST *ast)
+{
+ FullySpecifiedType leftExprTy = semantic()->check(ast->left_expression, _scope);
+ FullySpecifiedType rightExprTy = semantic()->check(ast->right_expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(CastExpressionAST *ast)
+{
+ FullySpecifiedType castTy = semantic()->check(ast->type_id, _scope);
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ if (_checkOldStyleCasts && ! castTy->isVoidType())
+ translationUnit()->warning(ast->firstToken(),
+ "ugly old style cast");
+ return false;
+}
+
+bool CheckExpression::visit(ConditionAST *ast)
+{
+ FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope);
+ Name *name = 0;
+ FullySpecifiedType declTy = semantic()->check(ast->declarator, typeSpecTy.qualifiedType(),
+ _scope, &name);
+ Declaration *decl = control()->newDeclaration(ast->declarator->firstToken(), name);
+ decl->setType(declTy);
+ _scope->enterSymbol(decl);
+ return false;
+}
+
+bool CheckExpression::visit(ConditionalExpressionAST *ast)
+{
+ FullySpecifiedType condTy = semantic()->check(ast->condition, _scope);
+ FullySpecifiedType leftExprTy = semantic()->check(ast->left_expression, _scope);
+ FullySpecifiedType rightExprTy = semantic()->check(ast->right_expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(CppCastExpressionAST *ast)
+{
+ FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope);
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(DeleteExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(ArrayInitializerAST *ast)
+{
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+ }
+ return false;
+}
+
+bool CheckExpression::visit(QualifiedNameAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(OperatorFunctionIdAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(ConversionFunctionIdAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(SimpleNameAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(DestructorNameAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(TemplateIdAST *ast)
+{
+ Name *name = semantic()->check(ast, _scope);
+ _scope->addUse(ast->firstToken(), name);
+ return false;
+}
+
+bool CheckExpression::visit(NewExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope);
+ // ### process new-typeid
+ // ### process new-initializer
+ return false;
+}
+
+bool CheckExpression::visit(TypeidExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(TypenameCallExpressionAST *ast)
+{
+ if (Name *name = semantic()->check(ast->name, _scope)) {
+ _scope->addUse(ast->name->firstToken(), name);
+ }
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+ }
+ return false;
+}
+
+bool CheckExpression::visit(TypeConstructorCallAST *ast)
+{
+ FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope);
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+ }
+ return false;
+}
+
+bool CheckExpression::visit(PostfixExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->base_expression, _scope);
+ for (PostfixAST *fx = ast->postfix_expressions; fx; fx = fx->next) {
+ accept(fx); // ### not exactly.
+ }
+ return false;
+}
+
+bool CheckExpression::visit(SizeofExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(NumericLiteralAST *)
+{
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Int));
+ return false;
+}
+
+bool CheckExpression::visit(BoolLiteralAST *)
+{
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Bool));
+ return false;
+}
+
+bool CheckExpression::visit(StringLiteralAST *)
+{
+ IntegerType *charTy = control()->integerType(IntegerType::Char);
+ _fullySpecifiedType.setType(control()->pointerType(charTy));
+ return false;
+}
+
+bool CheckExpression::visit(ThisExpressionAST *)
+{
+ return false;
+}
+
+bool CheckExpression::visit(NestedExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(ThrowExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(TypeIdAST *ast)
+{
+ FullySpecifiedType typeSpecTy = semantic()->check(ast->type_specifier, _scope);
+ FullySpecifiedType declTy = semantic()->check(ast->declarator, typeSpecTy.qualifiedType(),
+ _scope);
+ _fullySpecifiedType = declTy;
+ return false;
+}
+
+bool CheckExpression::visit(UnaryExpressionAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(QtMethodAST *ast)
+{
+ Name *name = 0;
+ Scope dummy;
+ FullySpecifiedType methTy = semantic()->check(ast->declarator, FullySpecifiedType(),
+ &dummy, &name);
+ Function *fty = methTy->asFunction();
+ if (! fty)
+ translationUnit()->warning(ast->firstToken(), "expected a function declarator");
+ else {
+ for (unsigned i = 0; i < fty->argumentCount(); ++i) {
+ Symbol *arg = fty->argumentAt(i);
+ if (arg->name())
+ translationUnit()->warning(arg->sourceLocation(),
+ "argument should be anonymous");
+ }
+ }
+ return false;
+}
+
+bool CheckExpression::visit(CompoundLiteralAST *ast)
+{
+ /*FullySpecifiedType exprTy = */ semantic()->check(ast->type_id, _scope);
+ /*FullySpecifiedType initTy = */ semantic()->check(ast->initializer, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(CallAST *ast)
+{
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+ }
+ return false;
+}
+
+bool CheckExpression::visit(ArrayAccessAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckExpression::visit(PostIncrDecrAST *)
+{
+ return false;
+}
+
+bool CheckExpression::visit(MemberAccessAST *ast)
+{
+ if (Name *name = semantic()->check(ast->member_name, _scope))
+ _scope->addUse(ast->member_name->firstToken(), name);
+ return false;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h
new file mode 100644
index 0000000000..5b5ae884b7
--- /dev/null
+++ b/src/shared/cplusplus/CheckExpression.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKEXPRESSION_H
+#define CPLUSPLUS_CHECKEXPRESSION_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+#include "FullySpecifiedType.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckExpression: public SemanticCheck
+{
+public:
+ CheckExpression(Semantic *semantic);
+ virtual ~CheckExpression();
+
+ FullySpecifiedType check(ExpressionAST *expression, Scope *scope);
+
+protected:
+ ExpressionAST *switchExpression(ExpressionAST *expression);
+ FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type);
+ Scope *switchScope(Scope *scope);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(ExpressionListAST *ast);
+ virtual bool visit(BinaryExpressionAST *ast);
+ virtual bool visit(CastExpressionAST *ast);
+ virtual bool visit(ConditionAST *ast);
+ virtual bool visit(ConditionalExpressionAST *ast);
+ virtual bool visit(CppCastExpressionAST *ast);
+ virtual bool visit(DeleteExpressionAST *ast);
+ virtual bool visit(ArrayInitializerAST *ast);
+ virtual bool visit(NewExpressionAST *ast);
+ virtual bool visit(TypeidExpressionAST *ast);
+ virtual bool visit(TypenameCallExpressionAST *ast);
+ virtual bool visit(TypeConstructorCallAST *ast);
+ virtual bool visit(PostfixExpressionAST *ast);
+ virtual bool visit(SizeofExpressionAST *ast);
+ virtual bool visit(NumericLiteralAST *ast);
+ virtual bool visit(BoolLiteralAST *ast);
+ virtual bool visit(ThisExpressionAST *ast);
+ virtual bool visit(NestedExpressionAST *ast);
+ virtual bool visit(StringLiteralAST *ast);
+ virtual bool visit(ThrowExpressionAST *ast);
+ virtual bool visit(TypeIdAST *ast);
+ virtual bool visit(UnaryExpressionAST *ast);
+ virtual bool visit(QtMethodAST *ast);
+ virtual bool visit(CompoundLiteralAST *ast);
+
+ //names
+ virtual bool visit(QualifiedNameAST *ast);
+ virtual bool visit(OperatorFunctionIdAST *ast);
+ virtual bool visit(ConversionFunctionIdAST *ast);
+ virtual bool visit(SimpleNameAST *ast);
+ virtual bool visit(DestructorNameAST *ast);
+ virtual bool visit(TemplateIdAST *ast);
+
+ // postfix expressions
+ virtual bool visit(CallAST *ast);
+ virtual bool visit(ArrayAccessAST *ast);
+ virtual bool visit(PostIncrDecrAST *ast);
+ virtual bool visit(MemberAccessAST *ast);
+
+private:
+ ExpressionAST *_expression;
+ FullySpecifiedType _fullySpecifiedType;
+ Scope *_scope;
+ bool _checkOldStyleCasts: 1;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKEXPRESSION_H
diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp
new file mode 100644
index 0000000000..09b90f3cb8
--- /dev/null
+++ b/src/shared/cplusplus/CheckName.cpp
@@ -0,0 +1,348 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckName.h"
+#include "Semantic.h"
+#include "AST.h"
+#include "Control.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+#include "Names.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckName::CheckName(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _name(0),
+ _scope(0)
+{ }
+
+CheckName::~CheckName()
+{ }
+
+Name *CheckName::check(NameAST *name, Scope *scope)
+{
+ Name *previousName = switchName(0);
+ Scope *previousScope = switchScope(scope);
+ accept(name);
+ (void) switchScope(previousScope);
+ return switchName(previousName);
+}
+
+Name *CheckName::check(NestedNameSpecifierAST *nested_name_specifier, Scope *scope)
+{
+ Name *previousName = switchName(0);
+ Scope *previousScope = switchScope(scope);
+
+ std::vector<Name *> names;
+ for (NestedNameSpecifierAST *it = nested_name_specifier;
+ it; it = it->next) {
+ names.push_back(semantic()->check(it->class_or_namespace_name, _scope));
+ }
+ _name = control()->qualifiedNameId(&names[0], names.size());
+
+ (void) switchScope(previousScope);
+ return switchName(previousName);
+}
+
+Name *CheckName::switchName(Name *name)
+{
+ Name *previousName = _name;
+ _name = name;
+ return previousName;
+}
+
+Scope *CheckName::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+bool CheckName::visit(QualifiedNameAST *ast)
+{
+ std::vector<Name *> names;
+ for (NestedNameSpecifierAST *it = ast->nested_name_specifier;
+ it; it = it->next) {
+ names.push_back(semantic()->check(it->class_or_namespace_name, _scope));
+ }
+ names.push_back(semantic()->check(ast->unqualified_name, _scope));
+ _name = control()->qualifiedNameId(&names[0], names.size(),
+ ast->global_scope_token != 0);
+ return false;
+}
+
+bool CheckName::visit(OperatorFunctionIdAST *ast)
+{
+ assert(ast->op != 0);
+
+ OperatorNameId::Kind kind = OperatorNameId::InvalidOp;
+
+ switch (tokenKind(ast->op->op_token)) {
+ case T_NEW:
+ if (ast->op->open_token)
+ kind = OperatorNameId::NewArrayOp;
+ else
+ kind = OperatorNameId::NewOp;
+ break;
+
+ case T_DELETE:
+ if (ast->op->open_token)
+ kind = OperatorNameId::DeleteArrayOp;
+ else
+ kind = OperatorNameId::DeleteOp;
+ break;
+
+ case T_PLUS:
+ kind = OperatorNameId::PlusOp;
+ break;
+
+ case T_MINUS:
+ kind = OperatorNameId::MinusOp;
+ break;
+
+ case T_STAR:
+ kind = OperatorNameId::StarOp;
+ break;
+
+ case T_SLASH:
+ kind = OperatorNameId::SlashOp;
+ break;
+
+ case T_PERCENT:
+ kind = OperatorNameId::PercentOp;
+ break;
+
+ case T_CARET:
+ kind = OperatorNameId::CaretOp;
+ break;
+
+ case T_AMPER:
+ kind = OperatorNameId::AmpOp;
+ break;
+
+ case T_PIPE:
+ kind = OperatorNameId::PipeOp;
+ break;
+
+ case T_TILDE:
+ kind = OperatorNameId::TildeOp;
+ break;
+
+ case T_EXCLAIM:
+ kind = OperatorNameId::ExclaimOp;
+ break;
+
+ case T_EQUAL:
+ kind = OperatorNameId::EqualOp;
+ break;
+
+ case T_LESS:
+ kind = OperatorNameId::LessOp;
+ break;
+
+ case T_GREATER:
+ kind = OperatorNameId::GreaterOp;
+ break;
+
+ case T_PLUS_EQUAL:
+ kind = OperatorNameId::PlusEqualOp;
+ break;
+
+ case T_MINUS_EQUAL:
+ kind = OperatorNameId::MinusEqualOp;
+ break;
+
+ case T_STAR_EQUAL:
+ kind = OperatorNameId::StarEqualOp;
+ break;
+
+ case T_SLASH_EQUAL:
+ kind = OperatorNameId::SlashEqualOp;
+ break;
+
+ case T_PERCENT_EQUAL:
+ kind = OperatorNameId::PercentEqualOp;
+ break;
+
+ case T_CARET_EQUAL:
+ kind = OperatorNameId::CaretEqualOp;
+ break;
+
+ case T_AMPER_EQUAL:
+ kind = OperatorNameId::AmpEqualOp;
+ break;
+
+ case T_PIPE_EQUAL:
+ kind = OperatorNameId::PipeEqualOp;
+ break;
+
+ case T_LESS_LESS:
+ kind = OperatorNameId::LessLessOp;
+ break;
+
+ case T_GREATER_GREATER:
+ kind = OperatorNameId::GreaterGreaterOp;
+ break;
+
+ case T_LESS_LESS_EQUAL:
+ kind = OperatorNameId::LessLessEqualOp;
+ break;
+
+ case T_GREATER_GREATER_EQUAL:
+ kind = OperatorNameId::GreaterGreaterEqualOp;
+ break;
+
+ case T_EQUAL_EQUAL:
+ kind = OperatorNameId::EqualEqualOp;
+ break;
+
+ case T_EXCLAIM_EQUAL:
+ kind = OperatorNameId::ExclaimEqualOp;
+ break;
+
+ case T_LESS_EQUAL:
+ kind = OperatorNameId::LessEqualOp;
+ break;
+
+ case T_GREATER_EQUAL:
+ kind = OperatorNameId::GreaterEqualOp;
+ break;
+
+ case T_AMPER_AMPER:
+ kind = OperatorNameId::AmpAmpOp;
+ break;
+
+ case T_PIPE_PIPE:
+ kind = OperatorNameId::PipePipeOp;
+ break;
+
+ case T_PLUS_PLUS:
+ kind = OperatorNameId::PlusPlusOp;
+ break;
+
+ case T_MINUS_MINUS:
+ kind = OperatorNameId::MinusMinusOp;
+ break;
+
+ case T_COMMA:
+ kind = OperatorNameId::CommaOp;
+ break;
+
+ case T_ARROW_STAR:
+ kind = OperatorNameId::ArrowStarOp;
+ break;
+
+ case T_ARROW:
+ kind = OperatorNameId::ArrowOp;
+ break;
+
+ case T_LPAREN:
+ kind = OperatorNameId::FunctionCallOp;
+ break;
+
+ case T_LBRACKET:
+ kind = OperatorNameId::ArrayAccessOp;
+ break;
+
+ default:
+ kind = OperatorNameId::InvalidOp;
+ } // switch
+
+ _name = control()->operatorNameId(kind);
+ return false;
+}
+
+bool CheckName::visit(ConversionFunctionIdAST *ast)
+{
+ FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope);
+ ty = semantic()->check(ast->ptr_operators, ty, _scope);
+ _name = control()->conversionNameId(ty);
+ return false;
+}
+
+bool CheckName::visit(SimpleNameAST *ast)
+{
+ Identifier *id = identifier(ast->identifier_token);
+ _name = control()->nameId(id);
+ return false;
+}
+
+bool CheckName::visit(DestructorNameAST *ast)
+{
+ Identifier *id = identifier(ast->identifier_token);
+ _name = control()->destructorNameId(id);
+ return false;
+}
+
+bool CheckName::visit(TemplateIdAST *ast)
+{
+ Identifier *id = identifier(ast->identifier_token);
+ std::vector<FullySpecifiedType> templateArguments;
+ for (TemplateArgumentListAST *it = ast->template_arguments; it;
+ it = it->next) {
+ ExpressionAST *arg = it->template_argument;
+ FullySpecifiedType exprTy = semantic()->check(arg, _scope);
+ templateArguments.push_back(exprTy);
+ }
+ if (templateArguments.empty())
+ _name = control()->templateNameId(id);
+ else
+ _name = control()->templateNameId(id, &templateArguments[0],
+ templateArguments.size());
+ return false;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckName.h b/src/shared/cplusplus/CheckName.h
new file mode 100644
index 0000000000..4b0631b002
--- /dev/null
+++ b/src/shared/cplusplus/CheckName.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKNAME_H
+#define CPLUSPLUS_CHECKNAME_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckName: public SemanticCheck
+{
+public:
+ CheckName(Semantic *semantic);
+ virtual ~CheckName();
+
+ Name *check(NameAST *name, Scope *scope);
+ Name *check(NestedNameSpecifierAST *name, Scope *scope);
+
+protected:
+ Name *switchName(Name *name);
+ Scope *switchScope(Scope *scope);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(QualifiedNameAST *ast);
+ virtual bool visit(OperatorFunctionIdAST *ast);
+ virtual bool visit(ConversionFunctionIdAST *ast);
+ virtual bool visit(SimpleNameAST *ast);
+ virtual bool visit(DestructorNameAST *ast);
+ virtual bool visit(TemplateIdAST *ast);
+
+private:
+ Name *_name;
+ Scope *_scope;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKNAME_H
diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp
new file mode 100644
index 0000000000..eeb59eebcc
--- /dev/null
+++ b/src/shared/cplusplus/CheckSpecifier.cpp
@@ -0,0 +1,392 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckSpecifier.h"
+#include "Semantic.h"
+#include "AST.h"
+#include "Token.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+#include "Names.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Control.h"
+#include "Scope.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckSpecifier::CheckSpecifier(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _specifier(0),
+ _scope(0)
+{ }
+
+CheckSpecifier::~CheckSpecifier()
+{ }
+
+FullySpecifiedType CheckSpecifier::check(SpecifierAST *specifier, Scope *scope)
+{
+ FullySpecifiedType previousType = switchFullySpecifiedType(FullySpecifiedType());
+ Scope *previousScope = switchScope(scope);
+ SpecifierAST *previousSpecifier = switchSpecifier(specifier);
+ accept(specifier);
+ (void) switchSpecifier(previousSpecifier);
+ (void) switchScope(previousScope);
+ return switchFullySpecifiedType(previousType);
+}
+
+SpecifierAST *CheckSpecifier::switchSpecifier(SpecifierAST *specifier)
+{
+ SpecifierAST *previousSpecifier = _specifier;
+ _specifier = specifier;
+ return previousSpecifier;
+}
+
+FullySpecifiedType CheckSpecifier::switchFullySpecifiedType(FullySpecifiedType type)
+{
+ FullySpecifiedType previousType = _fullySpecifiedType;
+ _fullySpecifiedType = type;
+ return previousType;
+}
+
+Scope *CheckSpecifier::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+bool CheckSpecifier::visit(SimpleSpecifierAST *ast)
+{
+ switch (tokenKind(ast->specifier_token)) {
+ case T_CONST:
+ if (_fullySpecifiedType.isConst())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setConst(true);
+ break;
+
+ case T_VOLATILE:
+ if (_fullySpecifiedType.isVolatile())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setVolatile(true);
+ break;
+
+ case T_FRIEND:
+ if (_fullySpecifiedType.isFriend())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setFriend(true);
+ break;
+
+ case T_REGISTER:
+ if (_fullySpecifiedType.isRegister())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setRegister(true);
+ break;
+
+ case T_STATIC:
+ if (_fullySpecifiedType.isStatic())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setStatic(true);
+ break;
+
+ case T_EXTERN:
+ if (_fullySpecifiedType.isExtern())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setExtern(true);
+ break;
+
+ case T_MUTABLE:
+ if (_fullySpecifiedType.isMutable())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setMutable(true);
+ break;
+
+ case T_TYPEDEF:
+ if (_fullySpecifiedType.isTypedef())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setTypedef(true);
+ break;
+
+ case T_INLINE:
+ if (_fullySpecifiedType.isInline())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setInline(true);
+ break;
+
+ case T_VIRTUAL:
+ if (_fullySpecifiedType.isVirtual())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setVirtual(true);
+ break;
+
+ case T_EXPLICIT:
+ if (_fullySpecifiedType.isExplicit())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setExplicit(true);
+ break;
+
+ case T_SIGNED:
+ if (_fullySpecifiedType.isSigned())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setSigned(true);
+ break;
+
+ case T_UNSIGNED:
+ if (_fullySpecifiedType.isUnsigned())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate `%s'", spell(ast->specifier_token));
+ _fullySpecifiedType.setUnsigned(true);
+ break;
+
+ case T_CHAR:
+ if (_fullySpecifiedType.type())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Char));
+ break;
+
+ case T_WCHAR_T:
+ if (_fullySpecifiedType.type())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::WideChar));
+ break;
+
+ case T_BOOL:
+ if (_fullySpecifiedType.type())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Bool));
+ break;
+
+ case T_SHORT:
+ if (Type *tp = _fullySpecifiedType.type()) {
+ IntegerType *intType = control()->integerType(IntegerType::Int);
+ if (tp != intType)
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ }
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Short));
+ break;
+
+ case T_INT:
+ if (Type *tp = _fullySpecifiedType.type()) {
+ IntegerType *shortType = control()->integerType(IntegerType::Short);
+ IntegerType *longType = control()->integerType(IntegerType::Long);
+ IntegerType *longLongType = control()->integerType(IntegerType::LongLong);
+ if (tp == shortType || tp == longType || tp == longLongType)
+ break;
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ }
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Int));
+ break;
+
+ case T_LONG:
+ if (Type *tp = _fullySpecifiedType.type()) {
+ IntegerType *intType = control()->integerType(IntegerType::Int);
+ IntegerType *longType = control()->integerType(IntegerType::Long);
+ FloatType *doubleType = control()->floatType(FloatType::Double);
+ if (tp == longType) {
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::LongLong));
+ break;
+ } else if (tp == doubleType) {
+ _fullySpecifiedType.setType(control()->floatType(FloatType::LongDouble));
+ break;
+ } else if (tp != intType) {
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ }
+ }
+ _fullySpecifiedType.setType(control()->integerType(IntegerType::Long));
+ break;
+
+ case T_FLOAT:
+ if (_fullySpecifiedType.type())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ _fullySpecifiedType.setType(control()->floatType(FloatType::Float));
+ break;
+
+ case T_DOUBLE:
+ if (Type *tp = _fullySpecifiedType.type()) {
+ IntegerType *longType = control()->integerType(IntegerType::Long);
+ if (tp == longType) {
+ _fullySpecifiedType.setType(control()->floatType(FloatType::LongDouble));
+ break;
+ }
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ }
+ _fullySpecifiedType.setType(control()->floatType(FloatType::Double));
+ break;
+
+ case T_VOID:
+ if (_fullySpecifiedType.type())
+ translationUnit()->error(ast->specifier_token,
+ "duplicate data type in declaration");
+ _fullySpecifiedType.setType(control()->voidType());
+ break;
+
+ default:
+ break;
+ } // switch
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(ClassSpecifierAST *ast)
+{
+ Name *className = semantic()->check(ast->name, _scope);
+ Class *klass = control()->newClass(ast->firstToken(), className);
+ unsigned classKey = tokenKind(ast->classkey_token);
+ if (classKey == T_CLASS)
+ klass->setClassKey(Class::ClassKey);
+ else if (classKey == T_STRUCT)
+ klass->setClassKey(Class::StructKey);
+ else if (classKey == T_UNION)
+ klass->setClassKey(Class::UnionKey);
+ klass->setVisibility(semantic()->currentVisibility());
+ _scope->enterSymbol(klass);
+ _fullySpecifiedType.setType(klass);
+
+ for (BaseSpecifierAST *base = ast->base_clause; base; base = base->next) {
+ Name *baseClassName = semantic()->check(base->name, _scope);
+ BaseClass *baseClass = control()->newBaseClass(ast->firstToken(), baseClassName);
+ if (base->token_virtual)
+ baseClass->setVirtual(true);
+ if (base->token_access_specifier) {
+ int accessSpecifier = tokenKind(base->token_access_specifier);
+ int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier);
+ baseClass->setVisibility(visibility);
+ }
+ klass->addBaseClass(baseClass);
+ }
+
+ int visibility = semantic()->visibilityForClassKey(classKey);
+ int previousVisibility = semantic()->switchVisibility(visibility);
+ int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod);
+
+ for (DeclarationAST *member = ast->member_specifiers;
+ member; member = member->next) {
+ semantic()->check(member, klass->members());
+ }
+
+ (void) semantic()->switchMethodKey(previousMethodKey);
+ (void) semantic()->switchVisibility(previousVisibility);
+
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(NamedTypeSpecifierAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ _fullySpecifiedType.setType(control()->namedType(name));
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(ElaboratedTypeSpecifierAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ _fullySpecifiedType.setType(control()->namedType(name));
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(EnumSpecifierAST *ast)
+{
+ Name *name = semantic()->check(ast->name, _scope);
+ Enum *e = control()->newEnum(ast->firstToken(), name);
+ e->setVisibility(semantic()->currentVisibility());
+ _scope->enterSymbol(e);
+ _fullySpecifiedType.setType(e);
+ for (EnumeratorAST *enumerator = ast->enumerators; enumerator;
+ enumerator = enumerator->next) {
+ Identifier *id = identifier(enumerator->identifier_token);
+ if (! id)
+ continue;
+ NameId *enumeratorName = control()->nameId(id);
+ Declaration *decl = control()->newDeclaration(enumerator->firstToken(),
+ enumeratorName);
+ e->addMember(decl);
+ }
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(TypeofSpecifierAST *ast)
+{
+ semantic()->check(ast->expression, _scope);
+ accept(ast->next);
+ return false;
+}
+
+bool CheckSpecifier::visit(AttributeSpecifierAST *)
+{
+ return false;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckSpecifier.h b/src/shared/cplusplus/CheckSpecifier.h
new file mode 100644
index 0000000000..3e6ddc57ba
--- /dev/null
+++ b/src/shared/cplusplus/CheckSpecifier.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKSPECIFIER_H
+#define CPLUSPLUS_CHECKSPECIFIER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+#include "FullySpecifiedType.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckSpecifier: public SemanticCheck
+{
+public:
+ CheckSpecifier(Semantic *semantic);
+ virtual ~CheckSpecifier();
+
+ FullySpecifiedType check(SpecifierAST *specifier, Scope *scope);
+
+protected:
+ SpecifierAST *switchSpecifier(SpecifierAST *specifier);
+ FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type);
+ Scope *switchScope(Scope *scope);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(SimpleSpecifierAST *ast);
+ virtual bool visit(ClassSpecifierAST *ast);
+ virtual bool visit(NamedTypeSpecifierAST *ast);
+ virtual bool visit(ElaboratedTypeSpecifierAST *ast);
+ virtual bool visit(EnumSpecifierAST *ast);
+ virtual bool visit(TypeofSpecifierAST *ast);
+ virtual bool visit(AttributeSpecifierAST *ast);
+
+private:
+ SpecifierAST *_specifier;
+ FullySpecifiedType _fullySpecifiedType;
+ Scope *_scope;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKSPECIFIER_H
diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp
new file mode 100644
index 0000000000..67902ff252
--- /dev/null
+++ b/src/shared/cplusplus/CheckStatement.cpp
@@ -0,0 +1,239 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CheckStatement.h"
+#include "Semantic.h"
+#include "AST.h"
+#include "TranslationUnit.h"
+#include "Scope.h"
+#include "CoreTypes.h"
+#include "Control.h"
+#include "Symbols.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+CheckStatement::CheckStatement(Semantic *semantic)
+ : SemanticCheck(semantic),
+ _statement(0),
+ _scope(0)
+{ }
+
+CheckStatement::~CheckStatement()
+{ }
+
+void CheckStatement::check(StatementAST *statement, Scope *scope)
+{
+ Scope *previousScope = switchScope(scope);
+ StatementAST *previousStatement = switchStatement(statement);
+ accept(statement);
+ (void) switchStatement(previousStatement);
+ (void) switchScope(previousScope);
+}
+
+StatementAST *CheckStatement::switchStatement(StatementAST *statement)
+{
+ StatementAST *previousStatement = _statement;
+ _statement = statement;
+ return previousStatement;
+}
+
+Scope *CheckStatement::switchScope(Scope *scope)
+{
+ Scope *previousScope = _scope;
+ _scope = scope;
+ return previousScope;
+}
+
+bool CheckStatement::visit(CaseStatementAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ semantic()->check(ast->statement, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(CompoundStatementAST *ast)
+{
+ Block *block = control()->newBlock(ast->lbrace_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ for (StatementAST *it = ast->statements; it; it = it->next) {
+ semantic()->check(it, _scope);
+ }
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool CheckStatement::visit(DeclarationStatementAST *ast)
+{
+ semantic()->check(ast->declaration, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(DoStatementAST *ast)
+{
+ semantic()->check(ast->statement, _scope);
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(ExpressionOrDeclarationStatementAST *ast)
+{
+// translationUnit()->warning(ast->firstToken(),
+// "ambiguous expression or declaration statement");
+ if (ast->declaration)
+ semantic()->check(ast->declaration, _scope);
+ else
+ semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(ExpressionStatementAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(ForStatementAST *ast)
+{
+ Block *block = control()->newBlock(ast->for_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ semantic()->check(ast->initializer, _scope);
+ FullySpecifiedType condTy = semantic()->check(ast->condition, _scope);
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ semantic()->check(ast->statement, _scope);
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool CheckStatement::visit(IfStatementAST *ast)
+{
+ Block *block = control()->newBlock(ast->if_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ FullySpecifiedType exprTy = semantic()->check(ast->condition, _scope);
+ semantic()->check(ast->statement, _scope);
+ semantic()->check(ast->else_statement, _scope);
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool CheckStatement::visit(LabeledStatementAST *ast)
+{
+ semantic()->check(ast->statement, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(BreakStatementAST *)
+{
+ return false;
+}
+
+bool CheckStatement::visit(ContinueStatementAST *)
+{
+ return false;
+}
+
+bool CheckStatement::visit(GotoStatementAST *)
+{
+ return false;
+}
+
+bool CheckStatement::visit(ReturnStatementAST *ast)
+{
+ FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
+ return false;
+}
+
+bool CheckStatement::visit(SwitchStatementAST *ast)
+{
+ Block *block = control()->newBlock(ast->switch_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ FullySpecifiedType condTy = semantic()->check(ast->condition, _scope);
+ semantic()->check(ast->statement, _scope);
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool CheckStatement::visit(TryBlockStatementAST *ast)
+{
+ semantic()->check(ast->statement, _scope);
+ for (CatchClauseAST *c = ast->catch_clause_seq; c; c = c->next) {
+ semantic()->check(c, _scope);
+ }
+ return false;
+}
+
+bool CheckStatement::visit(CatchClauseAST *ast)
+{
+ Block *block = control()->newBlock(ast->catch_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ semantic()->check(ast->exception_declaration, _scope);
+ semantic()->check(ast->statement, _scope);
+ (void) switchScope(previousScope);
+ return false;
+}
+
+bool CheckStatement::visit(WhileStatementAST *ast)
+{
+ Block *block = control()->newBlock(ast->while_token);
+ _scope->enterSymbol(block);
+ Scope *previousScope = switchScope(block->members());
+ FullySpecifiedType condTy = semantic()->check(ast->condition, _scope);
+ semantic()->check(ast->statement, _scope);
+ (void) switchScope(previousScope);
+ return false;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h
new file mode 100644
index 0000000000..856f64be8f
--- /dev/null
+++ b/src/shared/cplusplus/CheckStatement.h
@@ -0,0 +1,102 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CHECKSTATEMENT_H
+#define CPLUSPLUS_CHECKSTATEMENT_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "SemanticCheck.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck
+{
+public:
+ CheckStatement(Semantic *semantic);
+ virtual ~CheckStatement();
+
+ void check(StatementAST *statement, Scope *scope);
+
+protected:
+ StatementAST *switchStatement(StatementAST *statement);
+ Scope *switchScope(Scope *scope);
+
+ using ASTVisitor::visit;
+
+ virtual bool visit(CaseStatementAST *ast);
+ virtual bool visit(CompoundStatementAST *ast);
+ virtual bool visit(DeclarationStatementAST *ast);
+ virtual bool visit(DoStatementAST *ast);
+ virtual bool visit(ExpressionOrDeclarationStatementAST *ast);
+ virtual bool visit(ExpressionStatementAST *ast);
+ virtual bool visit(ForStatementAST *ast);
+ virtual bool visit(IfStatementAST *ast);
+ virtual bool visit(LabeledStatementAST *ast);
+ virtual bool visit(BreakStatementAST *ast);
+ virtual bool visit(ContinueStatementAST *ast);
+ virtual bool visit(GotoStatementAST *ast);
+ virtual bool visit(ReturnStatementAST *ast);
+ virtual bool visit(SwitchStatementAST *ast);
+ virtual bool visit(TryBlockStatementAST *ast);
+ virtual bool visit(CatchClauseAST *ast);
+ virtual bool visit(WhileStatementAST *ast);
+
+private:
+ StatementAST *_statement;
+ Scope *_scope;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CHECKSTATEMENT_H
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
new file mode 100644
index 0000000000..e44d84a1ae
--- /dev/null
+++ b/src/shared/cplusplus/Control.cpp
@@ -0,0 +1,636 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Control.h"
+#include "MemoryPool.h"
+#include "Literals.h"
+#include "LiteralTable.h"
+#include "TranslationUnit.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+#include "Names.h"
+#include "Array.h"
+#include <map> // ### replace me with LiteralTable
+#include <string>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+template <typename _Iterator>
+static void delete_map_entries(_Iterator first, _Iterator last)
+{
+ for (; first != last; ++first)
+ delete first->second;
+}
+
+template <typename _Map>
+static void delete_map_entries(const _Map &m)
+{ delete_map_entries(m.begin(), m.end()); }
+
+template <typename _Iterator>
+static void delete_array_entries(_Iterator first, _Iterator last)
+{
+ for (; first != last; ++first)
+ delete *first;
+}
+
+template <typename _Array>
+static void delete_array_entries(const _Array &a)
+{ delete_array_entries(a.begin(), a.end()); }
+
+class Control::Data
+{
+public:
+ Data(Control *control)
+ : control(control),
+ translationUnit(0),
+ diagnosticClient(0)
+ { }
+
+ ~Data()
+ {
+ // names
+ delete_map_entries(nameIds);
+ delete_map_entries(destructorNameIds);
+ delete_map_entries(operatorNameIds);
+ delete_map_entries(conversionNameIds);
+ delete_map_entries(qualifiedNameIds);
+ delete_map_entries(templateNameIds);
+
+ // types
+ delete_map_entries(integerTypes);
+ delete_map_entries(floatTypes);
+ delete_map_entries(pointerToMemberTypes);
+ delete_map_entries(pointerTypes);
+ delete_map_entries(referenceTypes);
+ delete_map_entries(arrayTypes);
+ delete_map_entries(namedTypes);
+
+ // symbols
+ delete_array_entries(declarations);
+ delete_array_entries(arguments);
+ delete_array_entries(functions);
+ delete_array_entries(baseClasses);
+ delete_array_entries(blocks);
+ delete_array_entries(classes);
+ delete_array_entries(namespaces);
+ delete_array_entries(usingNamespaceDirectives);
+ delete_array_entries(enums);
+ delete_array_entries(usingDeclarations);
+ }
+
+ NameId *findOrInsertNameId(Identifier *id)
+ {
+ if (! id)
+ return 0;
+ std::map<Identifier *, NameId *>::iterator it = nameIds.lower_bound(id);
+ if (it == nameIds.end() || it->first != id)
+ it = nameIds.insert(it, std::make_pair(id, new NameId(id)));
+ return it->second;
+ }
+
+ TemplateNameId *findOrInsertTemplateNameId(Identifier *id,
+ const std::vector<FullySpecifiedType> &templateArguments)
+ {
+ if (! id)
+ return 0;
+ const TemplateNameIdKey key(id, templateArguments);
+ std::map<TemplateNameIdKey, TemplateNameId *>::iterator it =
+ templateNameIds.lower_bound(key);
+ if (it == templateNameIds.end() || it->first != key) {
+ const FullySpecifiedType *args = 0;
+ if (templateArguments.size())
+ args = &templateArguments[0];
+ TemplateNameId *templ = new TemplateNameId(id, args,
+ templateArguments.size());
+ it = templateNameIds.insert(it, std::make_pair(key, templ));
+ }
+ return it->second;
+ }
+
+ DestructorNameId *findOrInsertDestructorNameId(Identifier *id)
+ {
+ if (! id)
+ return 0;
+ std::map<Identifier *, DestructorNameId *>::iterator it = destructorNameIds.lower_bound(id);
+ if (it == destructorNameIds.end() || it->first != id)
+ it = destructorNameIds.insert(it, std::make_pair(id, new DestructorNameId(id)));
+ return it->second;
+ }
+
+ OperatorNameId *findOrInsertOperatorNameId(int kind)
+ {
+ const int key(kind);
+ std::map<int, OperatorNameId *>::iterator it = operatorNameIds.lower_bound(key);
+ if (it == operatorNameIds.end() || it->first != key)
+ it = operatorNameIds.insert(it, std::make_pair(key, new OperatorNameId(kind)));
+ return it->second;
+ }
+
+ ConversionNameId *findOrInsertConversionNameId(FullySpecifiedType type)
+ {
+ std::map<FullySpecifiedType, ConversionNameId *>::iterator it =
+ conversionNameIds.lower_bound(type);
+ if (it == conversionNameIds.end() || it->first != type)
+ it = conversionNameIds.insert(it, std::make_pair(type, new ConversionNameId(type)));
+ return it->second;
+ }
+
+ QualifiedNameId *findOrInsertQualifiedNameId(const std::vector<Name *> &names, bool isGlobal)
+ {
+ const QualifiedNameIdKey key(names, isGlobal);
+ std::map<QualifiedNameIdKey, QualifiedNameId *>::iterator it =
+ qualifiedNameIds.lower_bound(key);
+ if (it == qualifiedNameIds.end() || it->first != key) {
+ QualifiedNameId *name = new QualifiedNameId(&names[0], names.size(), isGlobal);
+ it = qualifiedNameIds.insert(it, std::make_pair(key, name));
+ }
+ return it->second;
+ }
+
+ IntegerType *findOrInsertIntegerType(int kind)
+ {
+ const int key = int(kind);
+ std::map<int, IntegerType *>::iterator it = integerTypes.lower_bound(key);
+ if (it == integerTypes.end() || it->first != key)
+ it = integerTypes.insert(it, std::make_pair(key, new IntegerType(kind)));
+ return it->second;
+ }
+
+ FloatType *findOrInsertFloatType(int kind)
+ {
+ const int key = int(kind);
+ std::map<int, FloatType *>::iterator it = floatTypes.lower_bound(key);
+ if (it == floatTypes.end() || it->first != key)
+ it = floatTypes.insert(it, std::make_pair(key, new FloatType(kind)));
+ return it->second;
+ }
+
+ PointerToMemberType *findOrInsertPointerToMemberType(Name *memberName, FullySpecifiedType elementType)
+ {
+ const PointerToMemberTypeKey key(memberName, elementType);
+ std::map<PointerToMemberTypeKey, PointerToMemberType *>::iterator it =
+ pointerToMemberTypes.lower_bound(key);
+ if (it == pointerToMemberTypes.end() || it->first != key)
+ it = pointerToMemberTypes.insert(it, std::make_pair(key, new PointerToMemberType(memberName, elementType)));
+ return it->second;
+ }
+
+ PointerType *findOrInsertPointerType(FullySpecifiedType elementType)
+ {
+ std::map<FullySpecifiedType, PointerType *>::iterator it =
+ pointerTypes.lower_bound(elementType);
+ if (it == pointerTypes.end() || it->first != elementType)
+ it = pointerTypes.insert(it, std::make_pair(elementType, new PointerType(elementType)));
+ return it->second;
+ }
+
+ ReferenceType *findOrInsertReferenceType(FullySpecifiedType elementType)
+ {
+ std::map<FullySpecifiedType, ReferenceType *>::iterator it =
+ referenceTypes.lower_bound(elementType);
+ if (it == referenceTypes.end() || it->first != elementType)
+ it = referenceTypes.insert(it, std::make_pair(elementType, new ReferenceType(elementType)));
+ return it->second;
+ }
+
+ ArrayType *findOrInsertArrayType(FullySpecifiedType elementType, size_t size)
+ {
+ const ArrayKey key(elementType, size);
+ std::map<ArrayKey, ArrayType *>::iterator it =
+ arrayTypes.lower_bound(key);
+ if (it == arrayTypes.end() || it->first != key)
+ it = arrayTypes.insert(it, std::make_pair(key, new ArrayType(elementType, size)));
+ return it->second;
+ }
+
+ NamedType *findOrInsertNamedType(Name *name)
+ {
+ std::map<Name *, NamedType *>::iterator it = namedTypes.lower_bound(name);
+ if (it == namedTypes.end() || it->first != name)
+ it = namedTypes.insert(it, std::make_pair(name, new NamedType(name)));
+ return it->second;
+ }
+
+ Declaration *newDeclaration(unsigned sourceLocation, Name *name)
+ {
+ Declaration *declaration = new Declaration(translationUnit,
+ sourceLocation, name);
+ declarations.push_back(declaration);
+ return declaration;
+ }
+
+ Argument *newArgument(unsigned sourceLocation, Name *name)
+ {
+ Argument *argument = new Argument(translationUnit,
+ sourceLocation, name);
+ arguments.push_back(argument);
+ return argument;
+ }
+
+ Function *newFunction(unsigned sourceLocation, Name *name)
+ {
+ Function *function = new Function(translationUnit,
+ sourceLocation, name);
+ functions.push_back(function);
+ return function;
+ }
+
+ BaseClass *newBaseClass(unsigned sourceLocation, Name *name)
+ {
+ BaseClass *baseClass = new BaseClass(translationUnit,
+ sourceLocation, name);
+ baseClasses.push_back(baseClass);
+ return baseClass;
+ }
+
+ Block *newBlock(unsigned sourceLocation)
+ {
+ Block *block = new Block(translationUnit, sourceLocation);
+ blocks.push_back(block);
+ return block;
+ }
+
+ Class *newClass(unsigned sourceLocation, Name *name)
+ {
+ Class *klass = new Class(translationUnit,
+ sourceLocation, name);
+ classes.push_back(klass);
+ return klass;
+ }
+
+ Namespace *newNamespace(unsigned sourceLocation, Name *name)
+ {
+ Namespace *ns = new Namespace(translationUnit,
+ sourceLocation, name);
+ namespaces.push_back(ns);
+ return ns;
+ }
+
+ UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, Name *name)
+ {
+ UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit,
+ sourceLocation, name);
+ usingNamespaceDirectives.push_back(u);
+ return u;
+ }
+
+ Enum *newEnum(unsigned sourceLocation, Name *name)
+ {
+ Enum *e = new Enum(translationUnit,
+ sourceLocation, name);
+ enums.push_back(e);
+ return e;
+ }
+
+ UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name)
+ {
+ UsingDeclaration *u = new UsingDeclaration(translationUnit,
+ sourceLocation, name);
+ usingDeclarations.push_back(u);
+ return u;
+ }
+
+ struct TemplateNameIdKey {
+ Identifier *id;
+ std::vector<FullySpecifiedType> templateArguments;
+
+ TemplateNameIdKey(Identifier *id, const std::vector<FullySpecifiedType> &templateArguments)
+ : id(id), templateArguments(templateArguments)
+ { }
+
+ bool operator == (const TemplateNameIdKey &other) const
+ { return id == other.id && templateArguments == other.templateArguments; }
+
+ bool operator != (const TemplateNameIdKey &other) const
+ { return ! operator==(other); }
+
+ bool operator < (const TemplateNameIdKey &other) const
+ {
+ if (id == other.id)
+ return std::lexicographical_compare(templateArguments.begin(),
+ templateArguments.end(),
+ other.templateArguments.begin(),
+ other.templateArguments.end());
+ return id < other.id;
+ }
+ };
+
+ struct QualifiedNameIdKey {
+ std::vector<Name *> names;
+ bool isGlobal;
+
+ QualifiedNameIdKey(const std::vector<Name *> &names, bool isGlobal) :
+ names(names), isGlobal(isGlobal)
+ { }
+
+ bool operator == (const QualifiedNameIdKey &other) const
+ { return isGlobal == other.isGlobal && names == other.names; }
+
+ bool operator != (const QualifiedNameIdKey &other) const
+ { return ! operator==(other); }
+
+ bool operator < (const QualifiedNameIdKey &other) const
+ {
+ if (isGlobal == other.isGlobal)
+ return std::lexicographical_compare(names.begin(), names.end(),
+ other.names.begin(), other.names.end());
+ return isGlobal < other.isGlobal;
+ }
+ };
+
+ struct ArrayKey {
+ FullySpecifiedType type;
+ size_t size;
+
+ ArrayKey() :
+ size(0)
+ { }
+
+ ArrayKey(FullySpecifiedType type, size_t size) :
+ type(type), size(size)
+ { }
+
+ bool operator == (const ArrayKey &other) const
+ { return type == other.type && size == other.size; }
+
+ bool operator != (const ArrayKey &other) const
+ { return ! operator==(other); }
+
+ bool operator < (const ArrayKey &other) const
+ {
+ if (type == other.type)
+ return size < other.size;
+ return type < other.type;
+ }
+ };
+
+ struct PointerToMemberTypeKey {
+ Name *memberName;
+ FullySpecifiedType type;
+
+ PointerToMemberTypeKey()
+ : memberName(0)
+ { }
+
+ PointerToMemberTypeKey(Name *memberName, FullySpecifiedType type)
+ : memberName(memberName), type(type)
+ { }
+
+ bool operator == (const PointerToMemberTypeKey &other) const
+ { return memberName == other.memberName && type == other.type; }
+
+ bool operator != (const PointerToMemberTypeKey &other) const
+ { return ! operator==(other); }
+
+ bool operator < (const PointerToMemberTypeKey &other) const
+ {
+ if (memberName == other.memberName)
+ return type < other.type;
+ return memberName < other.memberName;
+ }
+ };
+
+ Control *control;
+ TranslationUnit *translationUnit;
+ DiagnosticClient *diagnosticClient;
+ LiteralTable<Identifier> identifiers;
+ LiteralTable<StringLiteral> stringLiterals;
+ LiteralTable<NumericLiteral> numericLiterals;
+ LiteralTable<StringLiteral> fileNames;
+
+ // ### replace std::map with lookup tables. ASAP!
+
+ // names
+ std::map<Identifier *, NameId *> nameIds;
+ std::map<Identifier *, DestructorNameId *> destructorNameIds;
+ std::map<int, OperatorNameId *> operatorNameIds;
+ std::map<FullySpecifiedType, ConversionNameId *> conversionNameIds;
+ std::map<TemplateNameIdKey, TemplateNameId *> templateNameIds;
+ std::map<QualifiedNameIdKey, QualifiedNameId *> qualifiedNameIds;
+
+ // types
+ VoidType voidType;
+ std::map<int, IntegerType *> integerTypes;
+ std::map<int, FloatType *> floatTypes;
+ std::map<PointerToMemberTypeKey, PointerToMemberType *> pointerToMemberTypes;
+ std::map<FullySpecifiedType, PointerType *> pointerTypes;
+ std::map<FullySpecifiedType, ReferenceType *> referenceTypes;
+ std::map<ArrayKey, ArrayType *> arrayTypes;
+ std::map<Name *, NamedType *> namedTypes;
+
+ // symbols
+ std::vector<Declaration *> declarations;
+ std::vector<Argument *> arguments;
+ std::vector<Function *> functions;
+ std::vector<BaseClass *> baseClasses;
+ std::vector<Block *> blocks;
+ std::vector<Class *> classes;
+ std::vector<Namespace *> namespaces;
+ std::vector<UsingNamespaceDirective *> usingNamespaceDirectives;
+ std::vector<Enum *> enums;
+ std::vector<UsingDeclaration *> usingDeclarations;
+};
+
+Control::Control()
+{ d = new Data(this); }
+
+Control::~Control()
+{ delete d; }
+
+TranslationUnit *Control::translationUnit() const
+{ return d->translationUnit; }
+
+TranslationUnit *Control::switchTranslationUnit(TranslationUnit *unit)
+{
+ TranslationUnit *previousTranslationUnit = d->translationUnit;
+ d->translationUnit = unit;
+ return previousTranslationUnit;
+}
+
+DiagnosticClient *Control::diagnosticClient() const
+{ return d->diagnosticClient; }
+
+void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
+{ d->diagnosticClient = diagnosticClient; }
+
+Identifier *Control::findOrInsertIdentifier(const char *chars, unsigned size)
+{ return d->identifiers.findOrInsertLiteral(chars, size); }
+
+Identifier *Control::findOrInsertIdentifier(const char *chars)
+{
+ unsigned length = std::char_traits<char>::length(chars);
+ return findOrInsertIdentifier(chars, length);
+}
+
+Control::IdentifierIterator Control::firstIdentifier() const
+{ return d->identifiers.begin(); }
+
+Control::IdentifierIterator Control::lastIdentifier() const
+{ return d->identifiers.end(); }
+
+StringLiteral *Control::findOrInsertStringLiteral(const char *chars, unsigned size)
+{ return d->stringLiterals.findOrInsertLiteral(chars, size); }
+
+StringLiteral *Control::findOrInsertStringLiteral(const char *chars)
+{
+ unsigned length = std::char_traits<char>::length(chars);
+ return findOrInsertStringLiteral(chars, length);
+}
+
+NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars, unsigned size)
+{ return d->numericLiterals.findOrInsertLiteral(chars, size); }
+
+NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars)
+{
+ unsigned length = std::char_traits<char>::length(chars);
+ return findOrInsertNumericLiteral(chars, length);
+}
+
+unsigned Control::fileNameCount() const
+{ return d->fileNames.size(); }
+
+StringLiteral *Control::fileNameAt(unsigned index) const
+{ return d->fileNames.at(index); }
+
+StringLiteral *Control::findOrInsertFileName(const char *chars, unsigned size)
+{ return d->fileNames.findOrInsertLiteral(chars, size); }
+
+StringLiteral *Control::findOrInsertFileName(const char *chars)
+{
+ unsigned length = std::char_traits<char>::length(chars);
+ return findOrInsertFileName(chars, length);
+}
+
+NameId *Control::nameId(Identifier *id)
+{ return d->findOrInsertNameId(id); }
+
+TemplateNameId *Control::templateNameId(Identifier *id,
+ FullySpecifiedType *const args,
+ unsigned argv)
+{
+ std::vector<FullySpecifiedType> templateArguments(args, args + argv);
+ return d->findOrInsertTemplateNameId(id, templateArguments);
+}
+
+DestructorNameId *Control::destructorNameId(Identifier *id)
+{ return d->findOrInsertDestructorNameId(id); }
+
+OperatorNameId *Control::operatorNameId(int kind)
+{ return d->findOrInsertOperatorNameId(kind); }
+
+ConversionNameId *Control::conversionNameId(FullySpecifiedType type)
+{ return d->findOrInsertConversionNameId(type); }
+
+QualifiedNameId *Control::qualifiedNameId(Name *const *names,
+ unsigned nameCount,
+ bool isGlobal)
+{
+ std::vector<Name *> classOrNamespaceNames(names, names + nameCount);
+ return d->findOrInsertQualifiedNameId(classOrNamespaceNames, isGlobal);
+}
+
+VoidType *Control::voidType()
+{ return &d->voidType; }
+
+IntegerType *Control::integerType(int kind)
+{ return d->findOrInsertIntegerType(kind); }
+
+FloatType *Control::floatType(int kind)
+{ return d->findOrInsertFloatType(kind); }
+
+PointerToMemberType *Control::pointerToMemberType(Name *memberName, FullySpecifiedType elementType)
+{ return d->findOrInsertPointerToMemberType(memberName, elementType); }
+
+PointerType *Control::pointerType(FullySpecifiedType elementType)
+{ return d->findOrInsertPointerType(elementType); }
+
+ReferenceType *Control::referenceType(FullySpecifiedType elementType)
+{ return d->findOrInsertReferenceType(elementType); }
+
+ArrayType *Control::arrayType(FullySpecifiedType elementType, size_t size)
+{ return d->findOrInsertArrayType(elementType, size); }
+
+NamedType *Control::namedType(Name *name)
+{ return d->findOrInsertNamedType(name); }
+
+Argument *Control::newArgument(unsigned sourceLocation, Name *name)
+{ return d->newArgument(sourceLocation, name); }
+
+Function *Control::newFunction(unsigned sourceLocation, Name *name)
+{ return d->newFunction(sourceLocation, name); }
+
+Namespace *Control::newNamespace(unsigned sourceLocation, Name *name)
+{ return d->newNamespace(sourceLocation, name); }
+
+BaseClass *Control::newBaseClass(unsigned sourceLocation, Name *name)
+{ return d->newBaseClass(sourceLocation, name); }
+
+Class *Control::newClass(unsigned sourceLocation, Name *name)
+{ return d->newClass(sourceLocation, name); }
+
+Enum *Control::newEnum(unsigned sourceLocation, Name *name)
+{ return d->newEnum(sourceLocation, name); }
+
+Block *Control::newBlock(unsigned sourceLocation)
+{ return d->newBlock(sourceLocation); }
+
+Declaration *Control::newDeclaration(unsigned sourceLocation, Name *name)
+{ return d->newDeclaration(sourceLocation, name); }
+
+UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLocation,
+ Name *name)
+{ return d->newUsingNamespaceDirective(sourceLocation, name); }
+
+UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name)
+{ return d->newUsingDeclaration(sourceLocation, name); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
new file mode 100644
index 0000000000..98c1bacdd2
--- /dev/null
+++ b/src/shared/cplusplus/Control.h
@@ -0,0 +1,180 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CONTROL_H
+#define CPLUSPLUS_CONTROL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstddef>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Control
+{
+public:
+ Control();
+ ~Control();
+
+ TranslationUnit *translationUnit() const;
+ TranslationUnit *switchTranslationUnit(TranslationUnit *unit);
+
+ DiagnosticClient *diagnosticClient() const;
+ void setDiagnosticClient(DiagnosticClient *diagnosticClient);
+
+ /// Returns the canonical name id.
+ NameId *nameId(Identifier *id);
+
+ /// Returns the canonical template name id.
+ TemplateNameId *templateNameId(Identifier *id,
+ FullySpecifiedType *const args = 0,
+ unsigned argc = 0);
+
+ /// Returns the canonical destructor name id.
+ DestructorNameId *destructorNameId(Identifier *id);
+
+ /// Returns the canonical operator name id.
+ OperatorNameId *operatorNameId(int operatorId);
+
+ /// Returns the canonical conversion name id.
+ ConversionNameId *conversionNameId(FullySpecifiedType type);
+
+ /// Returns the canonical qualified name id.
+ QualifiedNameId *qualifiedNameId(Name *const *names,
+ unsigned nameCount,
+ bool isGlobal = false);
+
+ /// Returns a Type object of type VoidType.
+ VoidType *voidType();
+
+ /// Returns a Type object of type IntegerType.
+ IntegerType *integerType(int integerId);
+
+ /// Returns a Type object of type FloatType.
+ FloatType *floatType(int floatId);
+
+ /// Returns a Type object of type PointertoMemberType.
+ PointerToMemberType *pointerToMemberType(Name *memberName,
+ FullySpecifiedType elementType);
+
+ /// Returns a Type object of type PointerType.
+ PointerType *pointerType(FullySpecifiedType elementType);
+
+ /// Returns a Type object of type ReferenceType.
+ ReferenceType *referenceType(FullySpecifiedType elementType);
+
+ /// Retruns a Type object of type ArrayType.
+ ArrayType *arrayType(FullySpecifiedType elementType, size_t size = 0);
+
+ /// Returns a Type object of type NamedType.
+ NamedType *namedType(Name *name);
+
+ /// Creates a new Declaration symbol.
+ Declaration *newDeclaration(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Argument symbol.
+ Argument *newArgument(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Function symbol.
+ Function *newFunction(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Namespace symbol.
+ Namespace *newNamespace(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new BaseClass symbol.
+ BaseClass *newBaseClass(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Class symbol.
+ Class *newClass(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Enum symbol.
+ Enum *newEnum(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new Block symbol.
+ Block *newBlock(unsigned sourceLocation);
+
+ /// Creates a new UsingNamespaceDirective symbol.
+ UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, Name *name = 0);
+
+ /// Creates a new UsingDeclaration symbol.
+ UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name = 0);
+
+ Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
+ Identifier *findOrInsertIdentifier(const char *chars);
+
+ typedef const Identifier *const *IdentifierIterator;
+
+ IdentifierIterator firstIdentifier() const;
+ IdentifierIterator lastIdentifier() const;
+
+ StringLiteral *findOrInsertStringLiteral(const char *chars, unsigned size);
+ StringLiteral *findOrInsertStringLiteral(const char *chars);
+
+ NumericLiteral *findOrInsertNumericLiteral(const char *chars, unsigned size);
+ NumericLiteral *findOrInsertNumericLiteral(const char *chars);
+
+ StringLiteral *findOrInsertFileName(const char *chars, unsigned size);
+ StringLiteral *findOrInsertFileName(const char *chars);
+
+ unsigned fileNameCount() const;
+ StringLiteral *fileNameAt(unsigned index) const;
+
+private:
+ class Data;
+ friend class Data;
+ Data *d;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CONTROL_H
diff --git a/src/shared/cplusplus/CoreTypes.cpp b/src/shared/cplusplus/CoreTypes.cpp
new file mode 100644
index 0000000000..cf5a3ca4fb
--- /dev/null
+++ b/src/shared/cplusplus/CoreTypes.cpp
@@ -0,0 +1,237 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "CoreTypes.h"
+#include "TypeVisitor.h"
+#include "Names.h"
+#include <algorithm>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+
+bool VoidType::isEqualTo(const Type *other) const
+{
+ const VoidType *o = other->asVoidType();
+ return o != 0;
+}
+
+void VoidType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+PointerToMemberType::PointerToMemberType(Name *memberName, FullySpecifiedType elementType)
+ : _memberName(memberName),
+ _elementType(elementType)
+{ }
+
+PointerToMemberType::~PointerToMemberType()
+{ }
+
+Name *PointerToMemberType::memberName() const
+{ return _memberName; }
+
+FullySpecifiedType PointerToMemberType::elementType() const
+{ return _elementType; }
+
+bool PointerToMemberType::isEqualTo(const Type *other) const
+{
+ const PointerToMemberType *o = other->asPointerToMemberType();
+ if (! o)
+ return false;
+ else if (! _memberName->isEqualTo(o->_memberName))
+ return false;
+ return _elementType.isEqualTo(o->_elementType);
+}
+
+void PointerToMemberType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+PointerType::PointerType(FullySpecifiedType elementType)
+ : _elementType(elementType)
+{ }
+
+PointerType::~PointerType()
+{ }
+
+bool PointerType::isEqualTo(const Type *other) const
+{
+ const PointerType *o = other->asPointerType();
+ if (! o)
+ return false;
+ return _elementType.isEqualTo(o->_elementType);
+}
+
+void PointerType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+FullySpecifiedType PointerType::elementType() const
+{ return _elementType; }
+
+ReferenceType::ReferenceType(FullySpecifiedType elementType)
+ : _elementType(elementType)
+{ }
+
+ReferenceType::~ReferenceType()
+{ }
+
+bool ReferenceType::isEqualTo(const Type *other) const
+{
+ const ReferenceType *o = other->asReferenceType();
+ if (! o)
+ return false;
+ return _elementType.isEqualTo(o->_elementType);
+}
+
+void ReferenceType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+FullySpecifiedType ReferenceType::elementType() const
+{ return _elementType; }
+
+IntegerType::IntegerType(int kind)
+ : _kind(kind)
+{ }
+
+IntegerType::~IntegerType()
+{ }
+
+bool IntegerType::isEqualTo(const Type *other) const
+{
+ const IntegerType *o = other->asIntegerType();
+ if (! o)
+ return false;
+ return _kind == o->_kind;
+}
+
+void IntegerType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+int IntegerType::kind() const
+{ return _kind; }
+
+FloatType::FloatType(int kind)
+ : _kind(kind)
+{ }
+
+FloatType::~FloatType()
+{ }
+
+void FloatType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+int FloatType::kind() const
+{ return _kind; }
+
+bool FloatType::isEqualTo(const Type *other) const
+{
+ const FloatType *o = other->asFloatType();
+ if (! o)
+ return false;
+ return _kind == o->_kind;
+}
+
+ArrayType::ArrayType(FullySpecifiedType elementType, size_t size)
+ : _elementType(elementType), _size(size)
+{ }
+
+ArrayType::~ArrayType()
+{ }
+
+bool ArrayType::isEqualTo(const Type *other) const
+{
+ const ArrayType *o = other->asArrayType();
+ if (! o)
+ return false;
+ else if (_size != o->_size)
+ return false;
+ return _elementType.isEqualTo(o->_elementType);
+}
+
+void ArrayType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+FullySpecifiedType ArrayType::elementType() const
+{ return _elementType; }
+
+size_t ArrayType::size() const
+{ return _size; }
+
+NamedType::NamedType(Name *name)
+ : _name(name)
+{ }
+
+NamedType::~NamedType()
+{ }
+
+Name *NamedType::name() const
+{ return _name; }
+
+bool NamedType::isEqualTo(const Type *other) const
+{
+ const NamedType *o = other->asNamedType();
+ if (! o)
+ return false;
+
+ Name *name = _name;
+ if (QualifiedNameId *q = name->asQualifiedNameId())
+ name = q->unqualifiedNameId();
+
+ Name *otherName = o->name();
+ if (QualifiedNameId *q = otherName->asQualifiedNameId())
+ otherName = q->unqualifiedNameId();
+
+ return name->isEqualTo(otherName);
+}
+
+void NamedType::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CoreTypes.h b/src/shared/cplusplus/CoreTypes.h
new file mode 100644
index 0000000000..c3c0461838
--- /dev/null
+++ b/src/shared/cplusplus/CoreTypes.h
@@ -0,0 +1,217 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_CORETYPES_H
+#define CPLUSPLUS_CORETYPES_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Type.h"
+#include "FullySpecifiedType.h"
+#include <cstddef>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT VoidType: public Type
+{
+public:
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT IntegerType: public Type
+{
+public:
+ enum Kind {
+ Char,
+ WideChar,
+ Bool,
+ Short,
+ Int,
+ Long,
+ LongLong
+ };
+
+public:
+ IntegerType(int kind);
+ virtual ~IntegerType();
+
+ int kind() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ int _kind;
+};
+
+class CPLUSPLUS_EXPORT FloatType: public Type
+{
+public:
+ enum Kind {
+ Float,
+ Double,
+ LongDouble
+ };
+
+public:
+ FloatType(int kind);
+ virtual ~FloatType();
+
+ int kind() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ int _kind;
+};
+
+class CPLUSPLUS_EXPORT PointerType: public Type
+{
+public:
+ PointerType(FullySpecifiedType elementType);
+ virtual ~PointerType();
+
+ FullySpecifiedType elementType() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ FullySpecifiedType _elementType;
+};
+
+class CPLUSPLUS_EXPORT PointerToMemberType: public Type
+{
+public:
+ PointerToMemberType(Name *memberName, FullySpecifiedType elementType);
+ virtual ~PointerToMemberType();
+
+ Name *memberName() const;
+ FullySpecifiedType elementType() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ Name *_memberName;
+ FullySpecifiedType _elementType;
+};
+
+class CPLUSPLUS_EXPORT ReferenceType: public Type
+{
+public:
+ ReferenceType(FullySpecifiedType elementType);
+ virtual ~ReferenceType();
+
+ FullySpecifiedType elementType() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ FullySpecifiedType _elementType;
+};
+
+class CPLUSPLUS_EXPORT ArrayType: public Type
+{
+public:
+ ArrayType(FullySpecifiedType elementType, size_t size);
+ virtual ~ArrayType();
+
+ FullySpecifiedType elementType() const;
+ size_t size() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ FullySpecifiedType _elementType;
+ size_t _size;
+};
+
+class CPLUSPLUS_EXPORT NamedType: public Type
+{
+public:
+ NamedType(Name *name);
+ virtual ~NamedType();
+
+ Name *name() const;
+
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ Name *_name;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_CORETYPES_H
diff --git a/src/shared/cplusplus/DiagnosticClient.cpp b/src/shared/cplusplus/DiagnosticClient.cpp
new file mode 100644
index 0000000000..12670adef9
--- /dev/null
+++ b/src/shared/cplusplus/DiagnosticClient.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "DiagnosticClient.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+DiagnosticClient::DiagnosticClient()
+{ }
+
+DiagnosticClient::~DiagnosticClient()
+{ }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/DiagnosticClient.h b/src/shared/cplusplus/DiagnosticClient.h
new file mode 100644
index 0000000000..6fa06887c6
--- /dev/null
+++ b/src/shared/cplusplus/DiagnosticClient.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_DIAGNOSTICCLIENT_H
+#define CPLUSPLUS_DIAGNOSTICCLIENT_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstdarg>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT DiagnosticClient
+{
+ DiagnosticClient(const DiagnosticClient &other);
+ void operator =(const DiagnosticClient &other);
+
+public:
+ enum Level {
+ Warning,
+ Error,
+ Fatal
+ };
+
+ DiagnosticClient();
+ virtual ~DiagnosticClient();
+
+ virtual void report(int level,
+ StringLiteral *fileName,
+ unsigned line, unsigned column,
+ const char *format, va_list ap) = 0;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_DIAGNOSTICCLIENT_H
diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp
new file mode 100644
index 0000000000..71dec2934b
--- /dev/null
+++ b/src/shared/cplusplus/FullySpecifiedType.cpp
@@ -0,0 +1,204 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "FullySpecifiedType.h"
+#include "Type.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+FullySpecifiedType::FullySpecifiedType(Type *type) :
+ _type(type), _flags(0)
+{ }
+
+FullySpecifiedType::~FullySpecifiedType()
+{ }
+
+bool FullySpecifiedType::isValid() const
+{ return _type != 0; }
+
+Type *FullySpecifiedType::type() const
+{ return _type; }
+
+void FullySpecifiedType::setType(Type *type)
+{ _type = type; }
+
+FullySpecifiedType FullySpecifiedType::qualifiedType() const
+{
+ FullySpecifiedType ty = *this;
+ ty.setFriend(false);
+ ty.setRegister(false);
+ ty.setStatic(false);
+ ty.setExtern(false);
+ ty.setMutable(false);
+ ty.setTypedef(false);
+ return ty;
+}
+
+bool FullySpecifiedType::isConst() const
+{ return _isConst; }
+
+void FullySpecifiedType::setConst(bool isConst)
+{ _isConst = isConst; }
+
+bool FullySpecifiedType::isVolatile() const
+{ return _isVolatile; }
+
+void FullySpecifiedType::setVolatile(bool isVolatile)
+{ _isVolatile = isVolatile; }
+
+bool FullySpecifiedType::isSigned() const
+{ return _isSigned; }
+
+void FullySpecifiedType::setSigned(bool isSigned)
+{ _isSigned = isSigned; }
+
+bool FullySpecifiedType::isUnsigned() const
+{ return _isUnsigned; }
+
+void FullySpecifiedType::setUnsigned(bool isUnsigned)
+{ _isUnsigned = isUnsigned; }
+
+bool FullySpecifiedType::isFriend() const
+{ return _isFriend; }
+
+void FullySpecifiedType::setFriend(bool isFriend)
+{ _isFriend = isFriend; }
+
+bool FullySpecifiedType::isRegister() const
+{ return _isRegister; }
+
+void FullySpecifiedType::setRegister(bool isRegister)
+{ _isRegister = isRegister; }
+
+bool FullySpecifiedType::isStatic() const
+{ return _isStatic; }
+
+void FullySpecifiedType::setStatic(bool isStatic)
+{ _isStatic = isStatic; }
+
+bool FullySpecifiedType::isExtern() const
+{ return _isExtern; }
+
+void FullySpecifiedType::setExtern(bool isExtern)
+{ _isExtern = isExtern; }
+
+bool FullySpecifiedType::isMutable() const
+{ return _isMutable; }
+
+void FullySpecifiedType::setMutable(bool isMutable)
+{ _isMutable = isMutable; }
+
+bool FullySpecifiedType::isTypedef() const
+{ return _isTypedef; }
+
+void FullySpecifiedType::setTypedef(bool isTypedef)
+{ _isTypedef = isTypedef; }
+
+bool FullySpecifiedType::isInline() const
+{ return _isInline; }
+
+void FullySpecifiedType::setInline(bool isInline)
+{ _isInline = isInline; }
+
+bool FullySpecifiedType::isVirtual() const
+{ return _isVirtual; }
+
+void FullySpecifiedType::setVirtual(bool isVirtual)
+{ _isVirtual = isVirtual; }
+
+bool FullySpecifiedType::isExplicit() const
+{ return _isExplicit; }
+
+void FullySpecifiedType::setExplicit(bool isExplicit)
+{ _isExplicit = isExplicit; }
+
+bool FullySpecifiedType::isEqualTo(const FullySpecifiedType &other) const
+{
+ if (_flags != other._flags)
+ return false;
+ if (_type == other._type)
+ return true;
+ else if (! _type)
+ return false;
+ else
+ return _type->isEqualTo(other._type);
+}
+
+Type &FullySpecifiedType::operator*()
+{ return *_type; }
+
+FullySpecifiedType::operator bool() const
+{ return _type != 0; }
+
+const Type &FullySpecifiedType::operator*() const
+{ return *_type; }
+
+Type *FullySpecifiedType::operator->()
+{ return _type; }
+
+const Type *FullySpecifiedType::operator->() const
+{ return _type; }
+
+bool FullySpecifiedType::operator == (const FullySpecifiedType &other) const
+{ return _type == other._type && _flags == other._flags; }
+
+bool FullySpecifiedType::operator != (const FullySpecifiedType &other) const
+{ return ! operator ==(other); }
+
+bool FullySpecifiedType::operator < (const FullySpecifiedType &other) const
+{
+ if (_type == other._type)
+ return _flags < other._flags;
+ return _type < other._type;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/FullySpecifiedType.h b/src/shared/cplusplus/FullySpecifiedType.h
new file mode 100644
index 0000000000..d156fff5ab
--- /dev/null
+++ b/src/shared/cplusplus/FullySpecifiedType.h
@@ -0,0 +1,158 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_FULLYSPECIFIEDTYPE_H
+#define CPLUSPLUS_FULLYSPECIFIEDTYPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT FullySpecifiedType
+{
+public:
+ FullySpecifiedType(Type *type = 0);
+ ~FullySpecifiedType();
+
+ bool isValid() const;
+ operator bool() const;
+
+ Type *type() const;
+ void setType(Type *type);
+
+ FullySpecifiedType qualifiedType() const;
+
+ bool isConst() const;
+ void setConst(bool isConst);
+
+ bool isVolatile() const;
+ void setVolatile(bool isVolatile);
+
+ bool isSigned() const;
+ void setSigned(bool isSigned);
+
+ bool isUnsigned() const;
+ void setUnsigned(bool isUnsigned);
+
+ bool isFriend() const;
+ void setFriend(bool isFriend);
+
+ bool isRegister() const;
+ void setRegister(bool isRegister);
+
+ bool isStatic() const;
+ void setStatic(bool isStatic);
+
+ bool isExtern() const;
+ void setExtern(bool isExtern);
+
+ bool isMutable() const;
+ void setMutable(bool isMutable);
+
+ bool isTypedef() const;
+ void setTypedef(bool isTypedef);
+
+ bool isInline() const;
+ void setInline(bool isInline);
+
+ bool isVirtual() const;
+ void setVirtual(bool isVirtual);
+
+ bool isExplicit() const;
+ void setExplicit(bool isExplicit);
+
+ bool isEqualTo(const FullySpecifiedType &other) const;
+
+ Type &operator*();
+ const Type &operator*() const;
+
+ Type *operator->();
+ const Type *operator->() const;
+
+ bool operator == (const FullySpecifiedType &other) const;
+ bool operator != (const FullySpecifiedType &other) const;
+ bool operator < (const FullySpecifiedType &other) const;
+
+private:
+ Type *_type;
+ union {
+ unsigned _flags;
+ struct {
+ // cv qualifiers
+ unsigned _isConst: 1;
+ unsigned _isVolatile: 1;
+
+ // sign
+ unsigned _isSigned: 1;
+ unsigned _isUnsigned: 1;
+
+ // storage class specifiers
+ unsigned _isFriend: 1;
+ unsigned _isRegister: 1;
+ unsigned _isStatic: 1;
+ unsigned _isExtern: 1;
+ unsigned _isMutable: 1;
+ unsigned _isTypedef: 1;
+
+ // function specifiers
+ unsigned _isInline: 1;
+ unsigned _isVirtual: 1;
+ unsigned _isExplicit: 1;
+ };
+ };
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H
diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp
new file mode 100644
index 0000000000..180feb341d
--- /dev/null
+++ b/src/shared/cplusplus/Keywords.cpp
@@ -0,0 +1,1348 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Lexer.h"
+#include "Token.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+static inline int classify2(const char *s, bool) {
+ if (s[0] == 'd') {
+ if (s[1] == 'o') {
+ return T_DO;
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'f') {
+ return T_IF;
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify3(const char *s, bool) {
+ if (s[0] == 'a') {
+ if (s[1] == 's') {
+ if (s[2] == 'm') {
+ return T_ASM;
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'o') {
+ if (s[2] == 'r') {
+ return T_FOR;
+ }
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 't') {
+ return T_INT;
+ }
+ }
+ }
+ else if (s[0] == 'n') {
+ if (s[1] == 'e') {
+ if (s[2] == 'w') {
+ return T_NEW;
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'r') {
+ if (s[2] == 'y') {
+ return T_TRY;
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify4(const char *s, bool q) {
+ if (s[0] == 'a') {
+ if (s[1] == 'u') {
+ if (s[2] == 't') {
+ if (s[3] == 'o') {
+ return T_AUTO;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'b') {
+ if (s[1] == 'o') {
+ if (s[2] == 'o') {
+ if (s[3] == 'l') {
+ return T_BOOL;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'a') {
+ if (s[2] == 's') {
+ if (s[3] == 'e') {
+ return T_CASE;
+ }
+ }
+ }
+ else if (s[1] == 'h') {
+ if (s[2] == 'a') {
+ if (s[3] == 'r') {
+ return T_CHAR;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'e') {
+ if (s[1] == 'l') {
+ if (s[2] == 's') {
+ if (s[3] == 'e') {
+ return T_ELSE;
+ }
+ }
+ }
+ else if (s[1] == 'n') {
+ if (s[2] == 'u') {
+ if (s[3] == 'm') {
+ return T_ENUM;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'g') {
+ if (s[1] == 'o') {
+ if (s[2] == 't') {
+ if (s[3] == 'o') {
+ return T_GOTO;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'l') {
+ if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 'g') {
+ return T_LONG;
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'h') {
+ if (s[2] == 'i') {
+ if (s[3] == 's') {
+ return T_THIS;
+ }
+ }
+ }
+ else if (s[1] == 'r') {
+ if (s[2] == 'u') {
+ if (s[3] == 'e') {
+ return T_TRUE;
+ }
+ }
+ }
+ }
+ else if (s[0] == 'v') {
+ if (s[1] == 'o') {
+ if (s[2] == 'i') {
+ if (s[3] == 'd') {
+ return T_VOID;
+ }
+ }
+ }
+ }
+ else if (q && s[0] == 'S') {
+ if (s[1] == 'L') {
+ if (s[2] == 'O') {
+ if (s[3] == 'T') {
+ return T_SLOT;
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify5(const char *s, bool q) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'a') {
+ if (s[3] == 's') {
+ if (s[4] == 'm') {
+ return T___ASM;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'b') {
+ if (s[1] == 'r') {
+ if (s[2] == 'e') {
+ if (s[3] == 'a') {
+ if (s[4] == 'k') {
+ return T_BREAK;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'a') {
+ if (s[2] == 't') {
+ if (s[3] == 'c') {
+ if (s[4] == 'h') {
+ return T_CATCH;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'l') {
+ if (s[2] == 'a') {
+ if (s[3] == 's') {
+ if (s[4] == 's') {
+ return T_CLASS;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 's') {
+ if (s[4] == 't') {
+ return T_CONST;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'a') {
+ if (s[2] == 'l') {
+ if (s[3] == 's') {
+ if (s[4] == 'e') {
+ return T_FALSE;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'l') {
+ if (s[2] == 'o') {
+ if (s[3] == 'a') {
+ if (s[4] == 't') {
+ return T_FLOAT;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'h') {
+ if (s[2] == 'o') {
+ if (s[3] == 'r') {
+ if (s[4] == 't') {
+ return T_SHORT;
+ }
+ }
+ }
+ }
+ else if (q) {
+ if (s[1] == 'l') {
+ if (s[2] == 'o') {
+ if (s[3] == 't') {
+ if (s[4] == 's') {
+ return T_SLOTS;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'h') {
+ if (s[2] == 'r') {
+ if (s[3] == 'o') {
+ if (s[4] == 'w') {
+ return T_THROW;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 'n') {
+ if (s[2] == 'i') {
+ if (s[3] == 'o') {
+ if (s[4] == 'n') {
+ return T_UNION;
+ }
+ }
+ }
+ }
+ else if (s[1] == 's') {
+ if (s[2] == 'i') {
+ if (s[3] == 'n') {
+ if (s[4] == 'g') {
+ return T_USING;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'w') {
+ if (s[1] == 'h') {
+ if (s[2] == 'i') {
+ if (s[3] == 'l') {
+ if (s[4] == 'e') {
+ return T_WHILE;
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify6(const char *s, bool q) {
+ if (s[0] == 'd') {
+ if (s[1] == 'e') {
+ if (s[2] == 'l') {
+ if (s[3] == 'e') {
+ if (s[4] == 't') {
+ if (s[5] == 'e') {
+ return T_DELETE;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'o') {
+ if (s[2] == 'u') {
+ if (s[3] == 'b') {
+ if (s[4] == 'l') {
+ if (s[5] == 'e') {
+ return T_DOUBLE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'e') {
+ if (s[1] == 'x') {
+ if (s[2] == 'p') {
+ if (s[3] == 'o') {
+ if (s[4] == 'r') {
+ if (s[5] == 't') {
+ return T_EXPORT;
+ }
+ }
+ }
+ }
+ else if (s[2] == 't') {
+ if (s[3] == 'e') {
+ if (s[4] == 'r') {
+ if (s[5] == 'n') {
+ return T_EXTERN;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'r') {
+ if (s[2] == 'i') {
+ if (s[3] == 'e') {
+ if (s[4] == 'n') {
+ if (s[5] == 'd') {
+ return T_FRIEND;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 'l') {
+ if (s[3] == 'i') {
+ if (s[4] == 'n') {
+ if (s[5] == 'e') {
+ return T_INLINE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'u') {
+ if (s[2] == 'b') {
+ if (s[3] == 'l') {
+ if (s[4] == 'i') {
+ if (s[5] == 'c') {
+ return T_PUBLIC;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'r') {
+ if (s[1] == 'e') {
+ if (s[2] == 't') {
+ if (s[3] == 'u') {
+ if (s[4] == 'r') {
+ if (s[5] == 'n') {
+ return T_RETURN;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'i') {
+ if (s[2] == 'g') {
+ if (s[3] == 'n') {
+ if (s[4] == 'e') {
+ if (s[5] == 'd') {
+ return T_SIGNED;
+ }
+ }
+ }
+ }
+ else if (s[2] == 'z') {
+ if (s[3] == 'e') {
+ if (s[4] == 'o') {
+ if (s[5] == 'f') {
+ return T_SIZEOF;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 't') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == 'i') {
+ if (s[5] == 'c') {
+ return T_STATIC;
+ }
+ }
+ }
+ }
+ else if (s[2] == 'r') {
+ if (s[3] == 'u') {
+ if (s[4] == 'c') {
+ if (s[5] == 't') {
+ return T_STRUCT;
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'w') {
+ if (s[2] == 'i') {
+ if (s[3] == 't') {
+ if (s[4] == 'c') {
+ if (s[5] == 'h') {
+ return T_SWITCH;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'y') {
+ if (s[2] == 'p') {
+ if (s[3] == 'e') {
+ if (s[4] == 'i') {
+ if (s[5] == 'd') {
+ return T_TYPEID;
+ }
+ }
+ else if (s[4] == 'o') {
+ if (s[5] == 'f') {
+ return T_TYPEOF;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (q && s[0] == 'S') {
+ if (s[1] == 'I') {
+ if (s[2] == 'G') {
+ if (s[3] == 'N') {
+ if (s[4] == 'A') {
+ if (s[5] == 'L') {
+ return T_SIGNAL;
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify7(const char *s, bool q) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'a') {
+ if (s[3] == 's') {
+ if (s[4] == 'm') {
+ if (s[5] == '_') {
+ if (s[6] == '_') {
+ return T___ASM__;
+ }
+ }
+ }
+ }
+ }
+ else if (s[2] == 'c') {
+ if (s[3] == 'o') {
+ if (s[4] == 'n') {
+ if (s[5] == 's') {
+ if (s[6] == 't') {
+ return T___CONST;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'd') {
+ if (s[1] == 'e') {
+ if (s[2] == 'f') {
+ if (s[3] == 'a') {
+ if (s[4] == 'u') {
+ if (s[5] == 'l') {
+ if (s[6] == 't') {
+ return T_DEFAULT;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'm') {
+ if (s[1] == 'u') {
+ if (s[2] == 't') {
+ if (s[3] == 'a') {
+ if (s[4] == 'b') {
+ if (s[5] == 'l') {
+ if (s[6] == 'e') {
+ return T_MUTABLE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'r') {
+ if (s[2] == 'i') {
+ if (s[3] == 'v') {
+ if (s[4] == 'a') {
+ if (s[5] == 't') {
+ if (s[6] == 'e') {
+ return T_PRIVATE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (q && s[0] == 's') {
+ if (s[1] == 'i') {
+ if (s[2] == 'g') {
+ if (s[3] == 'n') {
+ if (s[4] == 'a') {
+ if (s[5] == 'l') {
+ if (s[6] == 's') {
+ return T_SIGNALS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'y') {
+ if (s[2] == 'p') {
+ if (s[3] == 'e') {
+ if (s[4] == 'd') {
+ if (s[5] == 'e') {
+ if (s[6] == 'f') {
+ return T_TYPEDEF;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'v') {
+ if (s[1] == 'i') {
+ if (s[2] == 'r') {
+ if (s[3] == 't') {
+ if (s[4] == 'u') {
+ if (s[5] == 'a') {
+ if (s[6] == 'l') {
+ return T_VIRTUAL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'w') {
+ if (s[1] == 'c') {
+ if (s[2] == 'h') {
+ if (s[3] == 'a') {
+ if (s[4] == 'r') {
+ if (s[5] == '_') {
+ if (s[6] == 't') {
+ return T_WCHAR_T;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (q && s[0] == 'Q') {
+ if (s[1] == '_') {
+ if (s[2] == 'S') {
+ if (s[3] == 'L') {
+ if (s[4] == 'O') {
+ if (s[5] == 'T') {
+ if (s[6] == 'S') {
+ return T_SLOTS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify8(const char *s, bool) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'i') {
+ if (s[3] == 'n') {
+ if (s[4] == 'l') {
+ if (s[5] == 'i') {
+ if (s[6] == 'n') {
+ if (s[7] == 'e') {
+ return T___INLINE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[2] == 't') {
+ if (s[3] == 'y') {
+ if (s[4] == 'p') {
+ if (s[5] == 'e') {
+ if (s[6] == 'o') {
+ if (s[7] == 'f') {
+ return T___TYPEOF;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 't') {
+ if (s[4] == 'i') {
+ if (s[5] == 'n') {
+ if (s[6] == 'u') {
+ if (s[7] == 'e') {
+ return T_CONTINUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'e') {
+ if (s[1] == 'x') {
+ if (s[2] == 'p') {
+ if (s[3] == 'l') {
+ if (s[4] == 'i') {
+ if (s[5] == 'c') {
+ if (s[6] == 'i') {
+ if (s[7] == 't') {
+ return T_EXPLICIT;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'o') {
+ if (s[1] == 'p') {
+ if (s[2] == 'e') {
+ if (s[3] == 'r') {
+ if (s[4] == 'a') {
+ if (s[5] == 't') {
+ if (s[6] == 'o') {
+ if (s[7] == 'r') {
+ return T_OPERATOR;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'r') {
+ if (s[1] == 'e') {
+ if (s[2] == 'g') {
+ if (s[3] == 'i') {
+ if (s[4] == 's') {
+ if (s[5] == 't') {
+ if (s[6] == 'e') {
+ if (s[7] == 'r') {
+ return T_REGISTER;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'e') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ if (s[5] == 'a') {
+ if (s[6] == 't') {
+ if (s[7] == 'e') {
+ return T_TEMPLATE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'y') {
+ if (s[2] == 'p') {
+ if (s[3] == 'e') {
+ if (s[4] == 'n') {
+ if (s[5] == 'a') {
+ if (s[6] == 'm') {
+ if (s[7] == 'e') {
+ return T_TYPENAME;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'u') {
+ if (s[1] == 'n') {
+ if (s[2] == 's') {
+ if (s[3] == 'i') {
+ if (s[4] == 'g') {
+ if (s[5] == 'n') {
+ if (s[6] == 'e') {
+ if (s[7] == 'd') {
+ return T_UNSIGNED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'v') {
+ if (s[1] == 'o') {
+ if (s[2] == 'l') {
+ if (s[3] == 'a') {
+ if (s[4] == 't') {
+ if (s[5] == 'i') {
+ if (s[6] == 'l') {
+ if (s[7] == 'e') {
+ return T_VOLATILE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify9(const char *s, bool q) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'c') {
+ if (s[3] == 'o') {
+ if (s[4] == 'n') {
+ if (s[5] == 's') {
+ if (s[6] == 't') {
+ if (s[7] == '_') {
+ if (s[8] == '_') {
+ return T___CONST__;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'n') {
+ if (s[1] == 'a') {
+ if (s[2] == 'm') {
+ if (s[3] == 'e') {
+ if (s[4] == 's') {
+ if (s[5] == 'p') {
+ if (s[6] == 'a') {
+ if (s[7] == 'c') {
+ if (s[8] == 'e') {
+ return T_NAMESPACE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'r') {
+ if (s[2] == 'o') {
+ if (s[3] == 't') {
+ if (s[4] == 'e') {
+ if (s[5] == 'c') {
+ if (s[6] == 't') {
+ if (s[7] == 'e') {
+ if (s[8] == 'd') {
+ return T_PROTECTED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (q && s[0] == 'Q') {
+ if (s[1] == '_') {
+ if (s[2] == 'S') {
+ if (s[3] == 'I') {
+ if (s[4] == 'G') {
+ if (s[5] == 'N') {
+ if (s[6] == 'A') {
+ if (s[7] == 'L') {
+ if (s[8] == 'S') {
+ return T_SIGNALS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify10(const char *s, bool) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'i') {
+ if (s[3] == 'n') {
+ if (s[4] == 'l') {
+ if (s[5] == 'i') {
+ if (s[6] == 'n') {
+ if (s[7] == 'e') {
+ if (s[8] == '_') {
+ if (s[9] == '_') {
+ return T___INLINE__;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[2] == 't') {
+ if (s[3] == 'y') {
+ if (s[4] == 'p') {
+ if (s[5] == 'e') {
+ if (s[6] == 'o') {
+ if (s[7] == 'f') {
+ if (s[8] == '_') {
+ if (s[9] == '_') {
+ return T___TYPEOF__;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[2] == 'v') {
+ if (s[3] == 'o') {
+ if (s[4] == 'l') {
+ if (s[5] == 'a') {
+ if (s[6] == 't') {
+ if (s[7] == 'i') {
+ if (s[8] == 'l') {
+ if (s[9] == 'e') {
+ return T___VOLATILE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'o') {
+ if (s[2] == 'n') {
+ if (s[3] == 's') {
+ if (s[4] == 't') {
+ if (s[5] == '_') {
+ if (s[6] == 'c') {
+ if (s[7] == 'a') {
+ if (s[8] == 's') {
+ if (s[9] == 't') {
+ return T_CONST_CAST;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify11(const char *s, bool) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == 't') {
+ if (s[5] == 'r') {
+ if (s[6] == 'i') {
+ if (s[7] == 'b') {
+ if (s[8] == 'u') {
+ if (s[9] == 't') {
+ if (s[10] == 'e') {
+ return T___ATTRIBUTE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 't') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == 'i') {
+ if (s[5] == 'c') {
+ if (s[6] == '_') {
+ if (s[7] == 'c') {
+ if (s[8] == 'a') {
+ if (s[9] == 's') {
+ if (s[10] == 't') {
+ return T_STATIC_CAST;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify12(const char *s, bool) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'v') {
+ if (s[3] == 'o') {
+ if (s[4] == 'l') {
+ if (s[5] == 'a') {
+ if (s[6] == 't') {
+ if (s[7] == 'i') {
+ if (s[8] == 'l') {
+ if (s[9] == 'e') {
+ if (s[10] == '_') {
+ if (s[11] == '_') {
+ return T___VOLATILE__;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'd') {
+ if (s[1] == 'y') {
+ if (s[2] == 'n') {
+ if (s[3] == 'a') {
+ if (s[4] == 'm') {
+ if (s[5] == 'i') {
+ if (s[6] == 'c') {
+ if (s[7] == '_') {
+ if (s[8] == 'c') {
+ if (s[9] == 'a') {
+ if (s[10] == 's') {
+ if (s[11] == 't') {
+ return T_DYNAMIC_CAST;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify13(const char *s, bool) {
+ if (s[0] == '_') {
+ if (s[1] == '_') {
+ if (s[2] == 'a') {
+ if (s[3] == 't') {
+ if (s[4] == 't') {
+ if (s[5] == 'r') {
+ if (s[6] == 'i') {
+ if (s[7] == 'b') {
+ if (s[8] == 'u') {
+ if (s[9] == 't') {
+ if (s[10] == 'e') {
+ if (s[11] == '_') {
+ if (s[12] == '_') {
+ return T___ATTRIBUTE__;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classify16(const char *s, bool) {
+ if (s[0] == 'r') {
+ if (s[1] == 'e') {
+ if (s[2] == 'i') {
+ if (s[3] == 'n') {
+ if (s[4] == 't') {
+ if (s[5] == 'e') {
+ if (s[6] == 'r') {
+ if (s[7] == 'p') {
+ if (s[8] == 'r') {
+ if (s[9] == 'e') {
+ if (s[10] == 't') {
+ if (s[11] == '_') {
+ if (s[12] == 'c') {
+ if (s[13] == 'a') {
+ if (s[14] == 's') {
+ if (s[15] == 't') {
+ return T_REINTERPRET_CAST;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+int Lexer::classify(const char *s, int n, bool q) {
+ switch (n) {
+ case 2: return classify2(s, q);
+ case 3: return classify3(s, q);
+ case 4: return classify4(s, q);
+ case 5: return classify5(s, q);
+ case 6: return classify6(s, q);
+ case 7: return classify7(s, q);
+ case 8: return classify8(s, q);
+ case 9: return classify9(s, q);
+ case 10: return classify10(s, q);
+ case 11: return classify11(s, q);
+ case 12: return classify12(s, q);
+ case 13: return classify13(s, q);
+ case 16: return classify16(s, q);
+ default: return T_IDENTIFIER;
+ } // switch
+}
+
+static inline int classifyOperator2(const char *s) {
+ if (s[0] == 'o') {
+ if (s[1] == 'r') {
+ return T_OR;
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classifyOperator3(const char *s) {
+ if (s[0] == 'a') {
+ if (s[1] == 'n') {
+ if (s[2] == 'd') {
+ return T_AND;
+ }
+ }
+ }
+ else if (s[0] == 'n') {
+ if (s[1] == 'o') {
+ if (s[2] == 't') {
+ return T_NOT;
+ }
+ }
+ }
+ else if (s[0] == 'x') {
+ if (s[1] == 'o') {
+ if (s[2] == 'r') {
+ return T_XOR;
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classifyOperator5(const char *s) {
+ if (s[0] == 'b') {
+ if (s[1] == 'i') {
+ if (s[2] == 't') {
+ if (s[3] == 'o') {
+ if (s[4] == 'r') {
+ return T_BITOR;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'c') {
+ if (s[1] == 'o') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'l') {
+ return T_COMPL;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'o') {
+ if (s[1] == 'r') {
+ if (s[2] == '_') {
+ if (s[3] == 'e') {
+ if (s[4] == 'q') {
+ return T_OR_EQ;
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+static inline int classifyOperator6(const char *s) {
+ if (s[0] == 'a') {
+ if (s[1] == 'n') {
+ if (s[2] == 'd') {
+ if (s[3] == '_') {
+ if (s[4] == 'e') {
+ if (s[5] == 'q') {
+ return T_AND_EQ;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'b') {
+ if (s[1] == 'i') {
+ if (s[2] == 't') {
+ if (s[3] == 'a') {
+ if (s[4] == 'n') {
+ if (s[5] == 'd') {
+ return T_BITAND;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'n') {
+ if (s[1] == 'o') {
+ if (s[2] == 't') {
+ if (s[3] == '_') {
+ if (s[4] == 'e') {
+ if (s[5] == 'q') {
+ return T_NOT_EQ;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'x') {
+ if (s[1] == 'o') {
+ if (s[2] == 'r') {
+ if (s[3] == '_') {
+ if (s[4] == 'e') {
+ if (s[5] == 'q') {
+ return T_XOR_EQ;
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_IDENTIFIER;
+}
+
+int Lexer::classifyOperator(const char *s, int n) {
+ switch (n) {
+ case 2: return classifyOperator2(s);
+ case 3: return classifyOperator3(s);
+ case 5: return classifyOperator5(s);
+ case 6: return classifyOperator6(s);
+ default: return T_IDENTIFIER;
+ } // switch
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Keywords.kwgen b/src/shared/cplusplus/Keywords.kwgen
new file mode 100644
index 0000000000..f23b3b7cea
--- /dev/null
+++ b/src/shared/cplusplus/Keywords.kwgen
@@ -0,0 +1,86 @@
+
+#include "Lexer.h"
+#include "Token.h"
+
+%token-prefix=T_
+%toupper
+%no-enums
+%namespace=Lexer
+
+%%
+__asm
+__asm__
+__attribute
+__attribute__
+__const
+__const__
+__inline
+__inline__
+__typeof
+__typeof__
+__volatile
+__volatile__
+asm
+auto
+bool
+break
+case
+catch
+char
+class
+const
+const_cast
+continue
+default
+delete
+do
+double
+dynamic_cast
+else
+enum
+explicit
+export
+extern
+false
+float
+for
+friend
+goto
+if
+inline
+int
+long
+mutable
+namespace
+new
+operator
+private
+protected
+public
+register
+reinterpret_cast
+return
+short
+signed
+sizeof
+static
+static_cast
+struct
+switch
+template
+this
+throw
+true
+try
+typedef
+typeid
+typename
+typeof
+union
+unsigned
+using
+virtual
+void
+volatile
+wchar_t
+while
diff --git a/src/shared/cplusplus/Lexer.cpp b/src/shared/cplusplus/Lexer.cpp
new file mode 100644
index 0000000000..73c12524d7
--- /dev/null
+++ b/src/shared/cplusplus/Lexer.cpp
@@ -0,0 +1,680 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Lexer.h"
+#include "Control.h"
+#include "TranslationUnit.h"
+#include <cctype>
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+Lexer::Lexer(TranslationUnit *unit)
+ : _translationUnit(unit),
+ _state(Lexer::DefaultState),
+ _flags(0),
+ _currentLine(1)
+{
+ _scanKeywords = true;
+ setSource(_translationUnit->firstSourceChar(),
+ _translationUnit->lastSourceChar());
+}
+
+Lexer::Lexer(const char *firstChar, const char *lastChar)
+ : _translationUnit(0),
+ _state(Lexer::DefaultState),
+ _flags(0),
+ _currentLine(1)
+{
+ _scanKeywords = true;
+ setSource(firstChar, lastChar);
+}
+
+Lexer::~Lexer()
+{ }
+
+TranslationUnit *Lexer::translationUnit() const
+{ return _translationUnit; }
+
+Control *Lexer::control() const
+{
+ if (_translationUnit)
+ return _translationUnit->control();
+
+ return 0;
+}
+
+void Lexer::setSource(const char *firstChar, const char *lastChar)
+{
+ _firstChar = firstChar;
+ _lastChar = lastChar;
+ _currentChar = _firstChar - 1;
+ _tokenStart = _currentChar;
+ _yychar = '\n';
+}
+
+void Lexer::setStartWithNewline(bool enabled)
+{
+ if (enabled)
+ _yychar = '\n';
+ else
+ _yychar = ' ';
+}
+
+int Lexer::state() const
+{ return _state; }
+
+void Lexer::setState(int state)
+{ _state = state; }
+
+bool Lexer::qtMocRunEnabled() const
+{ return _qtMocRunEnabled; }
+
+void Lexer::setQtMocRunEnabled(bool onoff)
+{ _qtMocRunEnabled = onoff; }
+
+bool Lexer::objCEnabled() const
+{ return _objCEnabled; }
+
+void Lexer::setObjCEnabled(bool onoff)
+{ _objCEnabled = onoff; }
+
+bool Lexer::isIncremental() const
+{ return _isIncremental; }
+
+void Lexer::setIncremental(bool isIncremental)
+{ _isIncremental = isIncremental; }
+
+bool Lexer::scanCommentTokens() const
+{ return _scanCommentTokens; }
+
+void Lexer::setScanCommentTokens(bool onoff)
+{ _scanCommentTokens = onoff; }
+
+bool Lexer::scanKeywords() const
+{ return _scanKeywords; }
+
+void Lexer::setScanKeywords(bool onoff)
+{ _scanKeywords = onoff; }
+
+void Lexer::setScanAngleStringLiteralTokens(bool onoff)
+{ _scanAngleStringLiteralTokens = onoff; }
+
+void Lexer::pushLineStartOffset()
+{
+ ++_currentLine;
+
+ if (_translationUnit)
+ _translationUnit->pushLineOffset(_currentChar - _firstChar);
+}
+
+unsigned Lexer::tokenOffset() const
+{ return _tokenStart - _firstChar; }
+
+unsigned Lexer::tokenLength() const
+{ return _currentChar - _tokenStart; }
+
+const char *Lexer::tokenBegin() const
+{ return _tokenStart; }
+
+const char *Lexer::tokenEnd() const
+{ return _currentChar; }
+
+unsigned Lexer::currentLine() const
+{ return _currentLine; }
+
+void Lexer::scan(Token *tok)
+{
+ tok->reset();
+ scan_helper(tok);
+ tok->length = _currentChar - _tokenStart;
+}
+
+void Lexer::scan_helper(Token *tok)
+{
+ _Lagain:
+ while (_yychar && std::isspace(_yychar)) {
+ if (_yychar == '\n')
+ tok->newline = true;
+ else
+ tok->whitespace = true;
+ yyinp();
+ }
+
+ if (! _translationUnit)
+ tok->lineno = _currentLine;
+
+ _tokenStart = _currentChar;
+ tok->offset = _currentChar - _firstChar;
+
+ if (_state == MultiLineCommentState) {
+ if (! _yychar) {
+ tok->kind = T_EOF_SYMBOL;
+ return;
+ }
+
+ while (_yychar) {
+ if (_yychar != '*')
+ yyinp();
+ else {
+ yyinp();
+ if (_yychar == '/') {
+ yyinp();
+ _state = DefaultState;
+ break;
+ }
+ }
+ }
+
+ if (! _scanCommentTokens)
+ goto _Lagain;
+
+ tok->kind = T_COMMENT;
+ return; // done
+ }
+
+ if (! _yychar) {
+ tok->kind = T_EOF_SYMBOL;
+ return;
+ }
+
+ unsigned char ch = _yychar;
+ yyinp();
+
+ switch (ch) {
+ case '\\':
+ while (_yychar != '\n' && std::isspace(_yychar))
+ yyinp();
+ // ### assert(! _yychar || _yychar == '\n');
+ if (_yychar == '\n') {
+ tok->joined = true;
+ tok->newline = false;
+ yyinp();
+ }
+ goto _Lagain;
+
+ case '"': case '\'': {
+ const char quote = ch;
+
+ tok->kind = quote == '"'
+ ? T_STRING_LITERAL
+ : T_CHAR_LITERAL;
+
+ const char *yytext = _currentChar;
+
+ while (_yychar && _yychar != quote) {
+ if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == quote);
+
+ int yylen = _currentChar - yytext;
+
+ if (_yychar == quote)
+ yyinp();
+
+ if (control())
+ tok->string = control()->findOrInsertStringLiteral(yytext, yylen);
+ } break;
+
+ case '{':
+ tok->kind = T_LBRACE;
+ break;
+
+ case '}':
+ tok->kind = T_RBRACE;
+ break;
+
+ case '[':
+ tok->kind = T_LBRACKET;
+ break;
+
+ case ']':
+ tok->kind = T_RBRACKET;
+ break;
+
+ case '#':
+ if (_yychar == '#') {
+ tok->kind = T_POUND_POUND;
+ yyinp();
+ } else {
+ tok->kind = T_POUND;
+ }
+ break;
+
+ case '(':
+ tok->kind = T_LPAREN;
+ break;
+
+ case ')':
+ tok->kind = T_RPAREN;
+ break;
+
+ case ';':
+ tok->kind = T_SEMICOLON;
+ break;
+
+ case ':':
+ if (_yychar == ':') {
+ yyinp();
+ tok->kind = T_COLON_COLON;
+ } else {
+ tok->kind = T_COLON;
+ }
+ break;
+
+ case '.':
+ if (_yychar == '*') {
+ yyinp();
+ tok->kind = T_DOT_STAR;
+ } else if (_yychar == '.') {
+ yyinp();
+ // ### assert(_yychar);
+ if (_yychar == '.') {
+ yyinp();
+ tok->kind = T_DOT_DOT_DOT;
+ } else {
+ tok->kind = T_ERROR;
+ }
+ } else if (std::isdigit(_yychar)) {
+ const char *yytext = _currentChar - 2;
+ do {
+ if (_yychar == 'e' || _yychar == 'E') {
+ yyinp();
+ if (_yychar == '-' || _yychar == '+') {
+ yyinp();
+ // ### assert(std::isdigit(_yychar));
+ }
+ } else if (std::isalnum(_yychar) || _yychar == '.') {
+ yyinp();
+ } else {
+ break;
+ }
+ } while (_yychar);
+ int yylen = _currentChar - yytext;
+ tok->kind = T_INT_LITERAL;
+ if (control())
+ tok->number = control()->findOrInsertNumericLiteral(yytext, yylen);
+ } else {
+ tok->kind = T_DOT;
+ }
+ break;
+
+ case '?':
+ tok->kind = T_QUESTION;
+ break;
+
+ case '+':
+ if (_yychar == '+') {
+ yyinp();
+ tok->kind = T_PLUS_PLUS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_PLUS_EQUAL;
+ } else {
+ tok->kind = T_PLUS;
+ }
+ break;
+
+ case '-':
+ if (_yychar == '-') {
+ yyinp();
+ tok->kind = T_MINUS_MINUS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_MINUS_EQUAL;
+ } else if (_yychar == '>') {
+ yyinp();
+ if (_yychar == '*') {
+ yyinp();
+ tok->kind = T_ARROW_STAR;
+ } else {
+ tok->kind = T_ARROW;
+ }
+ } else {
+ tok->kind = T_MINUS;
+ }
+ break;
+
+ case '*':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_STAR_EQUAL;
+ } else {
+ tok->kind = T_STAR;
+ }
+ break;
+
+ case '/':
+ if (_yychar == '/') {
+ do {
+ yyinp();
+ } while (_yychar && _yychar != '\n');
+ if (! _scanCommentTokens)
+ goto _Lagain;
+ tok->kind = T_COMMENT;
+ } else if (_yychar == '*') {
+ yyinp();
+ while (_yychar) {
+ if (_yychar != '*') {
+ yyinp();
+ } else {
+ yyinp();
+ if (_yychar == '/')
+ break;
+ }
+ }
+
+ if (_yychar)
+ yyinp();
+ else
+ _state = MultiLineCommentState;
+
+ if (! _scanCommentTokens)
+ goto _Lagain;
+ tok->kind = T_COMMENT;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_SLASH_EQUAL;
+ } else {
+ tok->kind = T_SLASH;
+ }
+ break;
+
+ case '%':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_PERCENT_EQUAL;
+ } else {
+ tok->kind = T_PERCENT;
+ }
+ break;
+
+ case '^':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_CARET_EQUAL;
+ } else {
+ tok->kind = T_CARET;
+ }
+ break;
+
+ case '&':
+ if (_yychar == '&') {
+ yyinp();
+ tok->kind = T_AMPER_AMPER;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_AMPER_EQUAL;
+ } else {
+ tok->kind = T_AMPER;
+ }
+ break;
+
+ case '|':
+ if (_yychar == '|') {
+ yyinp();
+ tok->kind = T_PIPE_PIPE;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_PIPE_EQUAL;
+ } else {
+ tok->kind = T_PIPE;
+ }
+ break;
+
+ case '~':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_TILDE_EQUAL;
+ } else {
+ tok->kind = T_TILDE;
+ }
+ break;
+
+ case '!':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_EXCLAIM_EQUAL;
+ } else {
+ tok->kind = T_EXCLAIM;
+ }
+ break;
+
+ case '=':
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_EQUAL_EQUAL;
+ } else {
+ tok->kind = T_EQUAL;
+ }
+ break;
+
+ case '<':
+ if (_scanAngleStringLiteralTokens) {
+ const char *yytext = _currentChar;
+ while (_yychar && _yychar != '>')
+ yyinp();
+ int yylen = _currentChar - yytext;
+ // ### assert(_yychar == '>');
+ if (_yychar == '>')
+ yyinp();
+ if (control())
+ tok->string = control()->findOrInsertStringLiteral(yytext, yylen);
+ tok->kind = T_ANGLE_STRING_LITERAL;
+ } else if (_yychar == '<') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_LESS_LESS_EQUAL;
+ } else
+ tok->kind = T_LESS_LESS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_LESS_EQUAL;
+ } else {
+ tok->kind = T_LESS;
+ }
+ break;
+
+ case '>':
+ if (_yychar == '>') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_GREATER_GREATER_EQUAL;
+ } else
+ tok->kind = T_LESS_LESS;
+ tok->kind = T_GREATER_GREATER;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->kind = T_GREATER_EQUAL;
+ } else {
+ tok->kind = T_GREATER;
+ }
+ break;
+
+ case ',':
+ tok->kind = T_COMMA;
+ break;
+
+ default: {
+ if (_objCEnabled) {
+ if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') {
+ const char *yytext = _currentChar;
+
+ do {
+ yyinp();
+ if (! isalnum(_yychar))
+ break;
+ } while (_yychar);
+
+ const int yylen = _currentChar - yytext;
+ tok->kind = classifyObjCAtKeyword(yytext, yylen);
+ break;
+ } else if (ch == '@' && _yychar == '"') {
+ // objc @string literals
+ ch = _yychar;
+ yyinp();
+ tok->kind = T_AT_STRING_LITERAL;
+
+ const char *yytext = _currentChar;
+
+ while (_yychar && _yychar != '"') {
+ if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == '"');
+
+ int yylen = _currentChar - yytext;
+
+ if (_yychar == '"')
+ yyinp();
+
+ if (control())
+ tok->string = control()->findOrInsertStringLiteral(yytext, yylen);
+
+ break;
+ }
+ }
+
+ if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) {
+ // wide char/string literals
+ ch = _yychar;
+ yyinp();
+
+ const char quote = ch;
+
+ tok->kind = quote == '"'
+ ? T_WIDE_STRING_LITERAL
+ : T_WIDE_CHAR_LITERAL;
+
+ const char *yytext = _currentChar;
+
+ while (_yychar && _yychar != quote) {
+ if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == quote);
+
+ int yylen = _currentChar - yytext;
+
+ if (_yychar == quote)
+ yyinp();
+
+ if (control())
+ tok->string = control()->findOrInsertStringLiteral(yytext, yylen);
+ } else if (std::isalpha(ch) || ch == '_') {
+ const char *yytext = _currentChar - 1;
+ while (std::isalnum(_yychar) || _yychar == '_')
+ yyinp();
+ int yylen = _currentChar - yytext;
+ if (_scanKeywords)
+ tok->kind = classify(yytext, yylen, _qtMocRunEnabled);
+ else
+ tok->kind = T_IDENTIFIER;
+
+ if (tok->kind == T_IDENTIFIER) {
+ tok->kind = classifyOperator(yytext, yylen);
+
+ if (control())
+ tok->identifier = control()->findOrInsertIdentifier(yytext, yylen);
+ }
+ break;
+ } else if (std::isdigit(ch)) {
+ const char *yytext = _currentChar - 1;
+ while (_yychar) {
+ if (_yychar == 'e' || _yychar == 'E') {
+ yyinp();
+ if (_yychar == '-' || _yychar == '+') {
+ yyinp();
+ // ### assert(std::isdigit(_yychar));
+ }
+ } else if (std::isalnum(_yychar) || _yychar == '.') {
+ yyinp();
+ } else {
+ break;
+ }
+ }
+ int yylen = _currentChar - yytext;
+ tok->kind = T_INT_LITERAL;
+ if (control())
+ tok->number = control()->findOrInsertNumericLiteral(yytext, yylen);
+ break;
+ } else {
+ tok->kind = T_ERROR;
+ break;
+ }
+ } // default
+
+ } // switch
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Lexer.h b/src/shared/cplusplus/Lexer.h
new file mode 100644
index 0000000000..4cb62493db
--- /dev/null
+++ b/src/shared/cplusplus/Lexer.h
@@ -0,0 +1,159 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LEXER_H
+#define CPLUSPLUS_LEXER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Token.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Lexer
+{
+ Lexer(const Lexer &other);
+ void operator =(const Lexer &other);
+
+public:
+ enum State {
+ DefaultState,
+ MultiLineCommentState
+ };
+
+ Lexer(TranslationUnit *unit);
+ Lexer(const char *firstChar, const char *lastChar);
+ ~Lexer();
+
+ Control *control() const;
+ TranslationUnit *translationUnit() const;
+
+ bool qtMocRunEnabled() const;
+ void setQtMocRunEnabled(bool onoff);
+
+ bool objCEnabled() const;
+ void setObjCEnabled(bool onoff);
+
+ void scan(Token *tok);
+
+ inline void operator()(Token *tok)
+ { scan(tok); }
+
+ unsigned tokenOffset() const;
+ unsigned tokenLength() const;
+ const char *tokenBegin() const;
+ const char *tokenEnd() const;
+ unsigned currentLine() const;
+
+ bool scanCommentTokens() const;
+ void setScanCommentTokens(bool onoff);
+
+ bool scanKeywords() const;
+ void setScanKeywords(bool onoff);
+
+ bool scanAngleStringLiteralTokens() const;
+ void setScanAngleStringLiteralTokens(bool onoff);
+
+ void setStartWithNewline(bool enabled);
+
+ int state() const;
+ void setState(int state);
+
+ bool isIncremental() const;
+ void setIncremental(bool isIncremental);
+
+private:
+ void scan_helper(Token *tok);
+ void setSource(const char *firstChar, const char *lastChar);
+ static int classify(const char *string, int length, bool q);
+ static int classifyObjCAtKeyword(const char *s, int n);
+ static int classifyOperator(const char *string, int length);
+
+ inline void yyinp()
+ {
+ if (++_currentChar == _lastChar)
+ _yychar = 0;
+ else {
+ _yychar = *_currentChar;
+ if (_yychar == '\n')
+ pushLineStartOffset();
+ }
+ }
+
+ void pushLineStartOffset();
+
+private:
+ TranslationUnit *_translationUnit;
+ const char *_firstChar;
+ const char *_currentChar;
+ const char *_lastChar;
+ const char *_tokenStart;
+ unsigned char _yychar;
+ int _state;
+ union {
+ unsigned _flags;
+ struct {
+ unsigned _isIncremental: 1;
+ unsigned _scanCommentTokens: 1;
+ unsigned _scanKeywords: 1;
+ unsigned _scanAngleStringLiteralTokens: 1;
+ unsigned _qtMocRunEnabled: 1;
+ unsigned _objCEnabled: 1;
+ };
+ };
+ unsigned _currentLine;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_LEXER_H
diff --git a/src/shared/cplusplus/LiteralTable.cpp b/src/shared/cplusplus/LiteralTable.cpp
new file mode 100644
index 0000000000..21e3b2d8dd
--- /dev/null
+++ b/src/shared/cplusplus/LiteralTable.cpp
@@ -0,0 +1,34 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "LiteralTable.h"
diff --git a/src/shared/cplusplus/LiteralTable.h b/src/shared/cplusplus/LiteralTable.h
new file mode 100644
index 0000000000..35744fe360
--- /dev/null
+++ b/src/shared/cplusplus/LiteralTable.h
@@ -0,0 +1,181 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LITERALTABLE_H
+#define CPLUSPLUS_LITERALTABLE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstring>
+#include <cstdlib>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+template <typename _Literal>
+class LiteralTable
+{
+ LiteralTable(const LiteralTable &other);
+ void operator =(const LiteralTable &other);
+
+public:
+ typedef _Literal **iterator;
+
+public:
+ LiteralTable()
+ : _literals(0),
+ _allocatedLiterals(0),
+ _literalCount(-1),
+ _buckets(0),
+ _allocatedBuckets(0)
+ { }
+
+ ~LiteralTable()
+ {
+ if (_literals) {
+ _Literal **lastLiteral = _literals + _literalCount + 1;
+ for (_Literal **it = _literals; it != lastLiteral; ++it)
+ delete *it;
+ free(_literals);
+ }
+ if (_buckets)
+ free(_buckets);
+ }
+
+ bool empty() const
+ { return _literalCount == -1; }
+
+ unsigned size() const
+ { return _literalCount + 1; }
+
+ _Literal *at(unsigned index) const
+ { return _literals[index]; }
+
+ iterator begin() const
+ { return _literals; }
+
+ iterator end() const
+ { return _literals + _literalCount + 1; }
+
+ _Literal *findOrInsertLiteral(const char *chars, unsigned size)
+ {
+ if (_buckets) {
+ unsigned h = _Literal::hashCode(chars, size);
+ _Literal *literal = _buckets[h % _allocatedBuckets];
+ for (; literal; literal = static_cast<_Literal *>(literal->_next)) {
+ if (literal->size() == size && ! strncmp(literal->chars(), chars, size))
+ return literal;
+ }
+ }
+
+ _Literal *literal = new _Literal(chars, size);
+
+ if (++_literalCount == _allocatedLiterals) {
+ _allocatedLiterals <<= 1;
+
+ if (! _allocatedLiterals)
+ _allocatedLiterals = 256;
+
+ _literals = (_Literal **) realloc(_literals, sizeof(_Literal *) * _allocatedLiterals);
+ }
+
+ _literals[_literalCount] = literal;
+
+ if (! _buckets || _literalCount >= _allocatedBuckets * .6)
+ rehash();
+ else {
+ unsigned h = literal->hashCode() % _allocatedBuckets;
+ literal->_next = _buckets[h];
+ _buckets[h] = literal;
+ }
+
+ return literal;
+ }
+
+protected:
+ void rehash()
+ {
+ if (_buckets)
+ free(_buckets);
+
+ _allocatedBuckets <<= 1;
+
+ if (! _allocatedBuckets)
+ _allocatedBuckets = 256;
+
+ _buckets = (_Literal **) calloc(_allocatedBuckets, sizeof(_Literal *));
+
+ _Literal **lastLiteral = _literals + (_literalCount + 1);
+
+ for (_Literal **it = _literals; it != lastLiteral; ++it) {
+ _Literal *literal = *it;
+ unsigned h = literal->hashCode() % _allocatedBuckets;
+
+ literal->_next = _buckets[h];
+ _buckets[h] = literal;
+ }
+ }
+
+protected:
+ MemoryPool *_pool;
+
+ _Literal **_literals;
+ int _allocatedLiterals;
+ int _literalCount;
+
+ _Literal **_buckets;
+ int _allocatedBuckets;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_LITERALTABLE_H
diff --git a/src/shared/cplusplus/Literals.cpp b/src/shared/cplusplus/Literals.cpp
new file mode 100644
index 0000000000..f7ac69f568
--- /dev/null
+++ b/src/shared/cplusplus/Literals.cpp
@@ -0,0 +1,138 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Literals.h"
+#include <cstring>
+#include <algorithm>
+#include <iostream>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+////////////////////////////////////////////////////////////////////////////////
+Literal::Literal(const char *chars, unsigned size)
+ : _index(0), _next(0)
+{
+ _chars = new char[size + 1];
+
+ strncpy(_chars, chars, size);
+ _chars[size] = '\0';
+
+ _size = size;
+
+ _hashCode = hashCode(_chars, _size);
+}
+
+Literal::~Literal()
+{ delete[] _chars; }
+
+Literal::iterator Literal::begin() const
+{ return _chars; }
+
+Literal::iterator Literal::end() const
+{ return _chars + _size; }
+
+const char *Literal::chars() const
+{ return _chars; }
+
+char Literal::at(unsigned index) const
+{ return _chars[index]; }
+
+unsigned Literal::size() const
+{ return _size; }
+
+unsigned Literal::hashCode() const
+{ return _hashCode; }
+
+unsigned Literal::hashCode(const char *chars, unsigned size)
+{
+ unsigned h = 0;
+ for (unsigned i = 0; i < size; ++i)
+ h = (h >> 5) - h + chars[i];
+ return h;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+StringLiteral::StringLiteral(const char *chars, unsigned size)
+ : Literal(chars, size)
+{ }
+
+StringLiteral::~StringLiteral()
+{ }
+
+////////////////////////////////////////////////////////////////////////////////
+NumericLiteral::NumericLiteral(const char *chars, unsigned size)
+ : Literal(chars, size)
+{ }
+
+NumericLiteral::~NumericLiteral()
+{ }
+
+////////////////////////////////////////////////////////////////////////////////
+Identifier::Identifier(const char *chars, unsigned size)
+ : Literal(chars, size)
+{ }
+
+Identifier::~Identifier()
+{ }
+
+bool Identifier::isEqualTo(const Identifier *other) const
+{
+ if (this == other)
+ return true;
+ else if (hashCode() != other->hashCode())
+ return false;
+ else if (size() != other->size())
+ return false;
+ return ! strcmp(chars(), other->chars());
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Literals.h b/src/shared/cplusplus/Literals.h
new file mode 100644
index 0000000000..f55978b270
--- /dev/null
+++ b/src/shared/cplusplus/Literals.h
@@ -0,0 +1,122 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_LITERALS_H
+#define CPLUSPLUS_LITERALS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Token.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Literal
+{
+ Literal(const Literal &other);
+ void operator =(const Literal &other);
+
+public:
+ typedef const char *iterator;
+ typedef iterator const_iterator;
+
+public:
+ Literal(const char *chars, unsigned size);
+ virtual ~Literal();
+
+ iterator begin() const;
+ iterator end() const;
+
+ char at(unsigned index) const;
+ const char *chars() const;
+ unsigned size() const;
+
+ unsigned hashCode() const;
+ static unsigned hashCode(const char *chars, unsigned size);
+
+private:
+ char *_chars;
+ unsigned _size;
+ unsigned _hashCode;
+
+public:
+ // ### private
+ unsigned _index;
+ Literal *_next;
+};
+
+class CPLUSPLUS_EXPORT StringLiteral: public Literal
+{
+public:
+ StringLiteral(const char *chars, unsigned size);
+ virtual ~StringLiteral();
+};
+
+class CPLUSPLUS_EXPORT NumericLiteral: public Literal
+{
+public:
+ NumericLiteral(const char *chars, unsigned size);
+ virtual ~NumericLiteral();
+};
+
+class CPLUSPLUS_EXPORT Identifier: public Literal
+{
+public:
+ Identifier(const char *chars, unsigned size);
+ virtual ~Identifier();
+
+ bool isEqualTo(const Identifier *other) const;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_LITERALS_H
diff --git a/src/shared/cplusplus/MemoryPool.cpp b/src/shared/cplusplus/MemoryPool.cpp
new file mode 100644
index 0000000000..880c6bb884
--- /dev/null
+++ b/src/shared/cplusplus/MemoryPool.cpp
@@ -0,0 +1,130 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "MemoryPool.h"
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+MemoryPool::MemoryPool()
+ : _initializeAllocatedMemory(true),
+ _blocks(0),
+ _allocatedBlocks(0),
+ _blockCount(-1),
+ ptr(0),
+ end(0)
+{ }
+
+MemoryPool::~MemoryPool()
+{
+ if (_blockCount != -1) {
+ for (int i = 0; i < _blockCount + 1; ++i) {
+ free(_blocks[i]);
+ }
+ }
+
+ if (_blocks)
+ free(_blocks);
+}
+
+bool MemoryPool::initializeAllocatedMemory() const
+{ return _initializeAllocatedMemory; }
+
+void MemoryPool::setInitializeAllocatedMemory(bool initializeAllocatedMemory)
+{ _initializeAllocatedMemory = initializeAllocatedMemory; }
+
+void *MemoryPool::allocate_helper(size_t size)
+{
+ assert(size < BLOCK_SIZE);
+
+ if (++_blockCount == _allocatedBlocks) {
+ if (! _allocatedBlocks)
+ _allocatedBlocks = 8;
+ else
+ _allocatedBlocks *= 2;
+
+ _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks);
+ }
+
+ char *&block = _blocks[_blockCount];
+
+ if (_initializeAllocatedMemory)
+ block = (char *) calloc(1, BLOCK_SIZE);
+ else
+ block = (char *) malloc(BLOCK_SIZE);
+
+ ptr = block;
+ end = ptr + BLOCK_SIZE;
+
+ void *addr = ptr;
+ ptr += size;
+ return addr;
+}
+
+Managed::Managed()
+{ }
+
+Managed::~Managed()
+{ }
+
+void *Managed::operator new(size_t size, MemoryPool *pool)
+{ return pool->allocate(size); }
+
+void Managed::operator delete(void *)
+{ }
+
+void Managed::operator delete(void *, MemoryPool *)
+{ }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/MemoryPool.h b/src/shared/cplusplus/MemoryPool.h
new file mode 100644
index 0000000000..13c61c9d24
--- /dev/null
+++ b/src/shared/cplusplus/MemoryPool.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_MEMORYPOOL_H
+#define CPLUSPLUS_MEMORYPOOL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstddef>
+#include <new>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT MemoryPool
+{
+ MemoryPool(const MemoryPool &other);
+ void operator =(const MemoryPool &other);
+
+public:
+ MemoryPool();
+ ~MemoryPool();
+
+ bool initializeAllocatedMemory() const;
+ void setInitializeAllocatedMemory(bool initializeAllocatedMemory);
+
+ inline void *allocate(size_t size)
+ {
+ size = (size + 7) & ~7;
+ if (ptr && (ptr + size < end)) {
+ void *addr = ptr;
+ ptr += size;
+ return addr;
+ }
+ return allocate_helper(size);
+ }
+
+private:
+ void *allocate_helper(size_t size);
+
+private:
+ bool _initializeAllocatedMemory;
+ char **_blocks;
+ int _allocatedBlocks;
+ int _blockCount;
+ char *ptr, *end;
+
+ enum
+ {
+ BLOCK_SIZE = 8 * 1024,
+ DEFAULT_BLOCK_COUNT = 8
+ };
+};
+
+class CPLUSPLUS_EXPORT Managed
+{
+ Managed(const Managed &other);
+ void operator = (const Managed &other);
+
+public:
+ Managed();
+ virtual ~Managed();
+
+ void *operator new(size_t size, MemoryPool *pool);
+ void operator delete(void *);
+ void operator delete(void *, MemoryPool *);
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_MEMORYPOOL_H
diff --git a/src/shared/cplusplus/Name.cpp b/src/shared/cplusplus/Name.cpp
new file mode 100644
index 0000000000..89e875a93c
--- /dev/null
+++ b/src/shared/cplusplus/Name.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Name.h"
+#include "Names.h"
+#include "NameVisitor.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+Name::Name()
+{ }
+
+Name::~Name()
+{ }
+
+bool Name::isNameId() const
+{ return dynamic_cast<const NameId *>(this) != 0; }
+
+bool Name::isTemplateNameId() const
+{ return dynamic_cast<const TemplateNameId *>(this) != 0; }
+
+bool Name::isDestructorNameId() const
+{ return dynamic_cast<const DestructorNameId *>(this) != 0; }
+
+bool Name::isOperatorNameId() const
+{ return dynamic_cast<const OperatorNameId *>(this) != 0; }
+
+bool Name::isConversionNameId() const
+{ return dynamic_cast<const ConversionNameId *>(this) != 0; }
+
+bool Name::isQualifiedNameId() const
+{ return dynamic_cast<const QualifiedNameId *>(this) != 0; }
+
+const NameId *Name::asNameId() const
+{ return dynamic_cast<const NameId *>(this); }
+
+const TemplateNameId *Name::asTemplateNameId() const
+{ return dynamic_cast<const TemplateNameId *>(this); }
+
+const DestructorNameId *Name::asDestructorNameId() const
+{ return dynamic_cast<const DestructorNameId *>(this); }
+
+const OperatorNameId *Name::asOperatorNameId() const
+{ return dynamic_cast<const OperatorNameId *>(this); }
+
+const ConversionNameId *Name::asConversionNameId() const
+{ return dynamic_cast<const ConversionNameId *>(this); }
+
+const QualifiedNameId *Name::asQualifiedNameId() const
+{ return dynamic_cast<const QualifiedNameId *>(this); }
+
+NameId *Name::asNameId()
+{ return dynamic_cast<NameId *>(this); }
+
+TemplateNameId *Name::asTemplateNameId()
+{ return dynamic_cast<TemplateNameId *>(this); }
+
+DestructorNameId *Name::asDestructorNameId()
+{ return dynamic_cast<DestructorNameId *>(this); }
+
+OperatorNameId *Name::asOperatorNameId()
+{ return dynamic_cast<OperatorNameId *>(this); }
+
+ConversionNameId *Name::asConversionNameId()
+{ return dynamic_cast<ConversionNameId *>(this); }
+
+QualifiedNameId *Name::asQualifiedNameId()
+{ return dynamic_cast<QualifiedNameId *>(this); }
+
+void Name::accept(NameVisitor *visitor)
+{
+ if (visitor->preVisit(this))
+ accept0(visitor);
+ visitor->postVisit(this);
+}
+
+void Name::accept(Name *name, NameVisitor *visitor)
+{
+ if (! name)
+ return;
+ name->accept(visitor);
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Name.h b/src/shared/cplusplus/Name.h
new file mode 100644
index 0000000000..1f30a28516
--- /dev/null
+++ b/src/shared/cplusplus/Name.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAME_H
+#define CPLUSPLUS_NAME_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Name
+{
+ Name(const Name &other);
+ void operator =(const Name &other);
+
+public:
+ Name();
+ virtual ~Name();
+
+ bool isNameId() const;
+ bool isTemplateNameId() const;
+ bool isDestructorNameId() const;
+ bool isOperatorNameId() const;
+ bool isConversionNameId() const;
+ bool isQualifiedNameId() const;
+
+ const NameId *asNameId() const;
+ const TemplateNameId *asTemplateNameId() const;
+ const DestructorNameId *asDestructorNameId() const;
+ const OperatorNameId *asOperatorNameId() const;
+ const ConversionNameId *asConversionNameId() const;
+ const QualifiedNameId *asQualifiedNameId() const;
+
+ NameId *asNameId();
+ TemplateNameId *asTemplateNameId();
+ DestructorNameId *asDestructorNameId();
+ OperatorNameId *asOperatorNameId();
+ ConversionNameId *asConversionNameId();
+ QualifiedNameId *asQualifiedNameId();
+
+ virtual bool isEqualTo(const Name *other) const = 0;
+
+ void accept(NameVisitor *visitor);
+ static void accept(Name *name, NameVisitor *visitor);
+
+protected:
+ virtual void accept0(NameVisitor *visitor) = 0;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_NAME_H
diff --git a/src/shared/cplusplus/NameVisitor.cpp b/src/shared/cplusplus/NameVisitor.cpp
new file mode 100644
index 0000000000..d4f1af6575
--- /dev/null
+++ b/src/shared/cplusplus/NameVisitor.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "NameVisitor.h"
+#include "Names.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+NameVisitor::NameVisitor()
+{ }
+
+NameVisitor::~NameVisitor()
+{ }
+
+void NameVisitor::accept(Name *name)
+{ Name::accept(name, this); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/NameVisitor.h b/src/shared/cplusplus/NameVisitor.h
new file mode 100644
index 0000000000..5cea38b9f8
--- /dev/null
+++ b/src/shared/cplusplus/NameVisitor.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAMEVISITOR_H
+#define CPLUSPLUS_NAMEVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT NameVisitor
+{
+ NameVisitor(const NameVisitor &other);
+ void operator =(const NameVisitor &other);
+
+public:
+ NameVisitor();
+ virtual ~NameVisitor();
+
+ void accept(Name *name);
+
+ virtual bool preVisit(Name *) { return true; }
+ virtual void postVisit(Name *) {}
+
+ virtual void visit(NameId *) {}
+ virtual void visit(TemplateNameId *) {}
+ virtual void visit(DestructorNameId *) {}
+ virtual void visit(OperatorNameId *) {}
+ virtual void visit(ConversionNameId *) {}
+ virtual void visit(QualifiedNameId *) {}
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_NAMEVISITOR_H
diff --git a/src/shared/cplusplus/Names.cpp b/src/shared/cplusplus/Names.cpp
new file mode 100644
index 0000000000..35bb84b44c
--- /dev/null
+++ b/src/shared/cplusplus/Names.cpp
@@ -0,0 +1,262 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Names.h"
+#include "NameVisitor.h"
+#include "Literals.h"
+#include <cstring>
+#include <algorithm>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+QualifiedNameId::QualifiedNameId(Name *const names[],
+ unsigned nameCount,
+ bool isGlobal)
+ : _names(0),
+ _nameCount(nameCount),
+ _isGlobal(isGlobal)
+{
+ if (_nameCount) {
+ _names = new Name *[_nameCount];
+ std::copy(&names[0], &names[nameCount], _names);
+ }
+}
+
+QualifiedNameId::~QualifiedNameId()
+{ delete[] _names; }
+
+void QualifiedNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+unsigned QualifiedNameId::nameCount() const
+{ return _nameCount; }
+
+Name *QualifiedNameId::nameAt(unsigned index) const
+{ return _names[index]; }
+
+Name *const *QualifiedNameId::names() const
+{ return _names; }
+
+bool QualifiedNameId::isGlobal() const
+{ return _isGlobal; }
+
+Name *QualifiedNameId::unqualifiedNameId() const
+{
+ if (! _nameCount)
+ return 0;
+
+ return _names[_nameCount - 1];
+}
+
+bool QualifiedNameId::isEqualTo(const Name *other) const
+{
+ const QualifiedNameId *q = other->asQualifiedNameId();
+ if (! q)
+ return false;
+ else if (isGlobal() != q->isGlobal())
+ return false;
+ else {
+ const unsigned count = nameCount();
+ if (count != q->nameCount())
+ return false;
+ for (unsigned i = 0; i < count; ++i) {
+ Name *l = nameAt(i);
+ Name *r = q->nameAt(i);
+ if (! l->isEqualTo(r))
+ return false;
+ }
+ }
+ return true;
+}
+
+NameId::NameId(Identifier *identifier)
+ : _identifier(identifier)
+{ }
+
+NameId::~NameId()
+{ }
+
+void NameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+Identifier *NameId::identifier() const
+{ return _identifier; }
+
+bool NameId::isEqualTo(const Name *other) const
+{
+ const NameId *nameId = other->asNameId();
+ if (! nameId)
+ return false;
+ Identifier *l = identifier();
+ Identifier *r = nameId->identifier();
+ return l->isEqualTo(r);
+}
+
+DestructorNameId::DestructorNameId(Identifier *identifier)
+ : _identifier(identifier)
+{ }
+
+DestructorNameId::~DestructorNameId()
+{ }
+
+void DestructorNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+Identifier *DestructorNameId::identifier() const
+{ return _identifier; }
+
+bool DestructorNameId::isEqualTo(const Name *other) const
+{
+ const DestructorNameId *d = other->asDestructorNameId();
+ if (! d)
+ return false;
+ Identifier *l = identifier();
+ Identifier *r = d->identifier();
+ return l->isEqualTo(r);
+}
+
+TemplateNameId::TemplateNameId(Identifier *identifier,
+ const FullySpecifiedType templateArguments[],
+ unsigned templateArgumentCount)
+ : _identifier(identifier),
+ _templateArguments(0),
+ _templateArgumentCount(templateArgumentCount)
+{
+ if (_templateArgumentCount) {
+ _templateArguments = new FullySpecifiedType[_templateArgumentCount];
+ std::copy(&templateArguments[0], &templateArguments[_templateArgumentCount],
+ _templateArguments);
+ }
+}
+
+TemplateNameId::~TemplateNameId()
+{ delete[] _templateArguments; }
+
+void TemplateNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+Identifier *TemplateNameId::identifier() const
+{ return _identifier; }
+
+unsigned TemplateNameId::templateArgumentCount() const
+{ return _templateArgumentCount; }
+
+const FullySpecifiedType &TemplateNameId::templateArgumentAt(unsigned index) const
+{ return _templateArguments[index]; }
+
+const FullySpecifiedType *TemplateNameId::templateArguments() const
+{ return _templateArguments; }
+
+bool TemplateNameId::isEqualTo(const Name *other) const
+{
+ const TemplateNameId *t = other->asTemplateNameId();
+ if (! t)
+ return false;
+ Identifier *l = identifier();
+ Identifier *r = t->identifier();
+ if (! l->isEqualTo(r))
+ return false;
+ if (_templateArgumentCount != t->_templateArgumentCount)
+ return false;
+ for (unsigned i = 0; i < _templateArgumentCount; ++i) {
+ const FullySpecifiedType &l = _templateArguments[i];
+ const FullySpecifiedType &r = t->_templateArguments[i];
+ if (! l.isEqualTo(r))
+ return false;
+ }
+ return true;
+}
+
+OperatorNameId::OperatorNameId(int kind)
+ : _kind(kind)
+{ }
+
+OperatorNameId::~OperatorNameId()
+{ }
+
+void OperatorNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+int OperatorNameId::kind() const
+{ return _kind; }
+
+bool OperatorNameId::isEqualTo(const Name *other) const
+{
+ const OperatorNameId *o = other->asOperatorNameId();
+ if (! o)
+ return false;
+ return _kind == o->kind();
+}
+
+ConversionNameId::ConversionNameId(FullySpecifiedType type)
+ : _type(type)
+{ }
+
+ConversionNameId::~ConversionNameId()
+{ }
+
+void ConversionNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+FullySpecifiedType ConversionNameId::type() const
+{ return _type; }
+
+bool ConversionNameId::isEqualTo(const Name *other) const
+{
+ const ConversionNameId *c = other->asConversionNameId();
+ if (! c)
+ return false;
+ return _type.isEqualTo(c->type());
+}
+
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Names.h b/src/shared/cplusplus/Names.h
new file mode 100644
index 0000000000..86e6813c6c
--- /dev/null
+++ b/src/shared/cplusplus/Names.h
@@ -0,0 +1,241 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_NAMES_H
+#define CPLUSPLUS_NAMES_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Name.h"
+#include "FullySpecifiedType.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT QualifiedNameId: public Name
+{
+public:
+ QualifiedNameId(Name *const names[],
+ unsigned nameCount,
+ bool isGlobal = false);
+ virtual ~QualifiedNameId();
+
+ unsigned nameCount() const;
+ Name *nameAt(unsigned index) const;
+ Name *const *names() const;
+ Name *unqualifiedNameId() const;
+
+ bool isGlobal() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ Name **_names;
+ unsigned _nameCount;
+ bool _isGlobal;
+};
+
+class CPLUSPLUS_EXPORT NameId: public Name
+{
+public:
+ NameId(Identifier *identifier);
+ virtual ~NameId();
+
+ Identifier *identifier() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ Identifier *_identifier;
+};
+
+class CPLUSPLUS_EXPORT DestructorNameId: public Name
+{
+public:
+ DestructorNameId(Identifier *identifier);
+ virtual ~DestructorNameId();
+
+ Identifier *identifier() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ Identifier *_identifier;
+};
+
+class CPLUSPLUS_EXPORT TemplateNameId: public Name
+{
+public:
+ TemplateNameId(Identifier *identifier,
+ const FullySpecifiedType templateArguments[],
+ unsigned templateArgumentCount);
+ virtual ~TemplateNameId();
+
+ Identifier *identifier() const;
+
+ // ### find a better name
+ unsigned templateArgumentCount() const;
+ const FullySpecifiedType &templateArgumentAt(unsigned index) const;
+ const FullySpecifiedType *templateArguments() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ Identifier *_identifier;
+ FullySpecifiedType *_templateArguments;
+ unsigned _templateArgumentCount;
+};
+
+class CPLUSPLUS_EXPORT OperatorNameId: public Name
+{
+public:
+ /*
+ new delete new[] delete[]
+ + - * / % ^ & | ~
+ ! = < > += -= *= /= %=
+ ^= &= |= << >> >>= <<= == !=
+ <= >= && || ++ -- , ->* ->
+ () []
+ */
+ enum Kind {
+ InvalidOp,
+ NewOp,
+ DeleteOp,
+ NewArrayOp,
+ DeleteArrayOp,
+ PlusOp,
+ MinusOp,
+ StarOp,
+ SlashOp,
+ PercentOp,
+ CaretOp,
+ AmpOp,
+ PipeOp,
+ TildeOp,
+ ExclaimOp,
+ EqualOp,
+ LessOp,
+ GreaterOp,
+ PlusEqualOp,
+ MinusEqualOp,
+ StarEqualOp,
+ SlashEqualOp,
+ PercentEqualOp,
+ CaretEqualOp,
+ AmpEqualOp,
+ PipeEqualOp,
+ LessLessOp,
+ GreaterGreaterOp,
+ LessLessEqualOp,
+ GreaterGreaterEqualOp,
+ EqualEqualOp,
+ ExclaimEqualOp,
+ LessEqualOp,
+ GreaterEqualOp,
+ AmpAmpOp,
+ PipePipeOp,
+ PlusPlusOp,
+ MinusMinusOp,
+ CommaOp,
+ ArrowStarOp,
+ ArrowOp,
+ FunctionCallOp,
+ ArrayAccessOp
+ };
+
+public:
+ OperatorNameId(int kind);
+ virtual ~OperatorNameId();
+
+ int kind() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ int _kind;
+};
+
+class CPLUSPLUS_EXPORT ConversionNameId: public Name
+{
+public:
+ ConversionNameId(FullySpecifiedType type);
+ virtual ~ConversionNameId();
+
+ FullySpecifiedType type() const;
+
+ virtual bool isEqualTo(const Name *other) const;
+
+protected:
+ virtual void accept0(NameVisitor *visitor);
+
+private:
+ FullySpecifiedType _type;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_NAMES_H
diff --git a/src/shared/cplusplus/ObjectiveCAtKeywords.cpp b/src/shared/cplusplus/ObjectiveCAtKeywords.cpp
new file mode 100644
index 0000000000..3f8fc7c396
--- /dev/null
+++ b/src/shared/cplusplus/ObjectiveCAtKeywords.cpp
@@ -0,0 +1,464 @@
+#include "Lexer.h"
+#include "Token.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+static inline int classify3(const char *s) {
+ if (s[0] == 'e') {
+ if (s[1] == 'n') {
+ if (s[2] == 'd') {
+ return T_AT_END;
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'r') {
+ if (s[2] == 'y') {
+ return T_AT_TRY;
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify4(const char *s) {
+ if (s[0] == 'd') {
+ if (s[1] == 'e') {
+ if (s[2] == 'f') {
+ if (s[3] == 's') {
+ return T_AT_DEFS;
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify5(const char *s) {
+ if (s[0] == 'c') {
+ if (s[1] == 'a') {
+ if (s[2] == 't') {
+ if (s[3] == 'c') {
+ if (s[4] == 'h') {
+ return T_AT_CATCH;
+ }
+ }
+ }
+ }
+ else if (s[1] == 'l') {
+ if (s[2] == 'a') {
+ if (s[3] == 's') {
+ if (s[4] == 's') {
+ return T_AT_CLASS;
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 't') {
+ if (s[1] == 'h') {
+ if (s[2] == 'r') {
+ if (s[3] == 'o') {
+ if (s[4] == 'w') {
+ return T_AT_THROW;
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify6(const char *s) {
+ if (s[0] == 'e') {
+ if (s[1] == 'n') {
+ if (s[2] == 'c') {
+ if (s[3] == 'o') {
+ if (s[4] == 'd') {
+ if (s[5] == 'e') {
+ return T_AT_ENCODE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'u') {
+ if (s[2] == 'b') {
+ if (s[3] == 'l') {
+ if (s[4] == 'i') {
+ if (s[5] == 'c') {
+ return T_AT_PUBLIC;
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify7(const char *s) {
+ if (s[0] == 'd') {
+ if (s[1] == 'y') {
+ if (s[2] == 'n') {
+ if (s[3] == 'a') {
+ if (s[4] == 'm') {
+ if (s[5] == 'i') {
+ if (s[6] == 'c') {
+ return T_AT_DYNAMIC;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'f') {
+ if (s[1] == 'i') {
+ if (s[2] == 'n') {
+ if (s[3] == 'a') {
+ if (s[4] == 'l') {
+ if (s[5] == 'l') {
+ if (s[6] == 'y') {
+ return T_AT_FINALLY;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'a') {
+ if (s[2] == 'c') {
+ if (s[3] == 'k') {
+ if (s[4] == 'a') {
+ if (s[5] == 'g') {
+ if (s[6] == 'e') {
+ return T_AT_PACKAGE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[1] == 'r') {
+ if (s[2] == 'i') {
+ if (s[3] == 'v') {
+ if (s[4] == 'a') {
+ if (s[5] == 't') {
+ if (s[6] == 'e') {
+ return T_AT_PRIVATE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify8(const char *s) {
+ if (s[0] == 'o') {
+ if (s[1] == 'p') {
+ if (s[2] == 't') {
+ if (s[3] == 'i') {
+ if (s[4] == 'o') {
+ if (s[5] == 'n') {
+ if (s[6] == 'a') {
+ if (s[7] == 'l') {
+ return T_AT_OPTIONAL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'r') {
+ if (s[2] == 'o') {
+ if (s[3] == 'p') {
+ if (s[4] == 'e') {
+ if (s[5] == 'r') {
+ if (s[6] == 't') {
+ if (s[7] == 'y') {
+ return T_AT_PROPERTY;
+ }
+ }
+ }
+ }
+ }
+ else if (s[3] == 't') {
+ if (s[4] == 'o') {
+ if (s[5] == 'c') {
+ if (s[6] == 'o') {
+ if (s[7] == 'l') {
+ return T_AT_PROTOCOL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'r') {
+ if (s[1] == 'e') {
+ if (s[2] == 'q') {
+ if (s[3] == 'u') {
+ if (s[4] == 'i') {
+ if (s[5] == 'r') {
+ if (s[6] == 'e') {
+ if (s[7] == 'd') {
+ return T_AT_REQUIRED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 's') {
+ if (s[1] == 'e') {
+ if (s[2] == 'l') {
+ if (s[3] == 'e') {
+ if (s[4] == 'c') {
+ if (s[5] == 't') {
+ if (s[6] == 'o') {
+ if (s[7] == 'r') {
+ return T_AT_SELECTOR;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify9(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 'n') {
+ if (s[2] == 't') {
+ if (s[3] == 'e') {
+ if (s[4] == 'r') {
+ if (s[5] == 'f') {
+ if (s[6] == 'a') {
+ if (s[7] == 'c') {
+ if (s[8] == 'e') {
+ return T_AT_INTERFACE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (s[0] == 'p') {
+ if (s[1] == 'r') {
+ if (s[2] == 'o') {
+ if (s[3] == 't') {
+ if (s[4] == 'e') {
+ if (s[5] == 'c') {
+ if (s[6] == 't') {
+ if (s[7] == 'e') {
+ if (s[8] == 'd') {
+ return T_AT_PROTECTED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify10(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'y') {
+ if (s[2] == 'n') {
+ if (s[3] == 't') {
+ if (s[4] == 'h') {
+ if (s[5] == 'e') {
+ if (s[6] == 's') {
+ if (s[7] == 'i') {
+ if (s[8] == 'z') {
+ if (s[9] == 'e') {
+ return T_AT_SYNTHESIZE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify11(const char *s) {
+ if (s[0] == 'n') {
+ if (s[1] == 'o') {
+ if (s[2] == 't') {
+ if (s[3] == '_') {
+ if (s[4] == 'k') {
+ if (s[5] == 'e') {
+ if (s[6] == 'y') {
+ if (s[7] == 'w') {
+ if (s[8] == 'o') {
+ if (s[9] == 'r') {
+ if (s[10] == 'd') {
+ return T_AT_NOT_KEYWORD;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify12(const char *s) {
+ if (s[0] == 's') {
+ if (s[1] == 'y') {
+ if (s[2] == 'n') {
+ if (s[3] == 'c') {
+ if (s[4] == 'h') {
+ if (s[5] == 'r') {
+ if (s[6] == 'o') {
+ if (s[7] == 'n') {
+ if (s[8] == 'i') {
+ if (s[9] == 'z') {
+ if (s[10] == 'e') {
+ if (s[11] == 'd') {
+ return T_AT_SYNCHRONIZED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify14(const char *s) {
+ if (s[0] == 'i') {
+ if (s[1] == 'm') {
+ if (s[2] == 'p') {
+ if (s[3] == 'l') {
+ if (s[4] == 'e') {
+ if (s[5] == 'm') {
+ if (s[6] == 'e') {
+ if (s[7] == 'n') {
+ if (s[8] == 't') {
+ if (s[9] == 'a') {
+ if (s[10] == 't') {
+ if (s[11] == 'i') {
+ if (s[12] == 'o') {
+ if (s[13] == 'n') {
+ return T_AT_IMPLEMENTATION;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+static inline int classify19(const char *s) {
+ if (s[0] == 'c') {
+ if (s[1] == 'o') {
+ if (s[2] == 'm') {
+ if (s[3] == 'p') {
+ if (s[4] == 'a') {
+ if (s[5] == 't') {
+ if (s[6] == 'i') {
+ if (s[7] == 'b') {
+ if (s[8] == 'i') {
+ if (s[9] == 'l') {
+ if (s[10] == 'i') {
+ if (s[11] == 't') {
+ if (s[12] == 'y') {
+ if (s[13] == '_') {
+ if (s[14] == 'a') {
+ if (s[15] == 'l') {
+ if (s[16] == 'i') {
+ if (s[17] == 'a') {
+ if (s[18] == 's') {
+ return T_AT_COMPATIBILITY_ALIAS;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return T_ERROR;
+}
+
+int Lexer::classifyObjCAtKeyword(const char *s, int n) {
+ switch (n) {
+ case 3: return classify3(s);
+ case 4: return classify4(s);
+ case 5: return classify5(s);
+ case 6: return classify6(s);
+ case 7: return classify7(s);
+ case 8: return classify8(s);
+ case 9: return classify9(s);
+ case 10: return classify10(s);
+ case 11: return classify11(s);
+ case 12: return classify12(s);
+ case 14: return classify14(s);
+ case 19: return classify19(s);
+ default: return T_ERROR;
+ } // switch
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
new file mode 100644
index 0000000000..085c8cb54e
--- /dev/null
+++ b/src/shared/cplusplus/Parser.cpp
@@ -0,0 +1,3810 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Parser.h"
+#include "Token.h"
+#include "Lexer.h"
+#include "Control.h"
+#include "AST.h"
+#include "Literals.h"
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+Parser::Parser(TranslationUnit *unit)
+ : _translationUnit(unit),
+ _control(_translationUnit->control()),
+ _pool(_translationUnit->memoryPool()),
+ _tokenIndex(1),
+ _templateArguments(0),
+ _qtMocRunEnabled(false),
+ _objCEnabled(false),
+ _inFunctionBody(false),
+ _inObjCImplementationContext(false)
+{ }
+
+Parser::~Parser()
+{ }
+
+bool Parser::qtMocRunEnabled() const
+{ return _qtMocRunEnabled; }
+
+void Parser::setQtMocRunEnabled(bool onoff)
+{ _qtMocRunEnabled = onoff; }
+
+bool Parser::objCEnabled() const
+{ return _objCEnabled; }
+
+void Parser::setObjCEnabled(bool onoff)
+{ _objCEnabled = onoff; }
+
+bool Parser::switchTemplateArguments(bool templateArguments)
+{
+ bool previousTemplateArguments = _templateArguments;
+ _templateArguments = templateArguments;
+ return previousTemplateArguments;
+}
+
+bool Parser::blockErrors(bool block)
+{ return _translationUnit->blockErrors(block); }
+
+bool Parser::skipUntil(int token)
+{
+ while (int tk = LA()) {
+ if (tk == token)
+ return true;
+
+ consumeToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ while (int tk = LA()) {
+ switch (tk) {
+ case T_SEMICOLON:
+ case T_TILDE:
+ case T_COLON_COLON:
+ case T_IDENTIFIER:
+ case T_OPERATOR:
+ case T_CHAR:
+ case T_WCHAR_T:
+ case T_BOOL:
+ case T_SHORT:
+ case T_INT:
+ case T_LONG:
+ case T_SIGNED:
+ case T_UNSIGNED:
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_VOID:
+ case T_EXTERN:
+ case T_NAMESPACE:
+ case T_USING:
+ case T_TYPEDEF:
+ case T_ASM:
+ case T_TEMPLATE:
+ case T_EXPORT:
+ case T_CONST:
+ case T_VOLATILE:
+ case T_PUBLIC:
+ case T_PROTECTED:
+ case T_PRIVATE:
+ return true;
+
+ default:
+ consumeToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ while (int tk = LA()) {
+ switch (tk) {
+ case T_SEMICOLON:
+ case T_LBRACE:
+ case T_RBRACE:
+ case T_CONST:
+ case T_VOLATILE:
+ case T_IDENTIFIER:
+ case T_CASE:
+ case T_DEFAULT:
+ case T_IF:
+ case T_SWITCH:
+ case T_WHILE:
+ case T_DO:
+ case T_FOR:
+ case T_BREAK:
+ case T_CONTINUE:
+ case T_RETURN:
+ case T_GOTO:
+ case T_TRY:
+ case T_CATCH:
+ case T_THROW:
+ case T_CHAR:
+ case T_WCHAR_T:
+ case T_BOOL:
+ case T_SHORT:
+ case T_INT:
+ case T_LONG:
+ case T_SIGNED:
+ case T_UNSIGNED:
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_VOID:
+ case T_CLASS:
+ case T_STRUCT:
+ case T_UNION:
+ case T_ENUM:
+ case T_COLON_COLON:
+ case T_TEMPLATE:
+ case T_USING:
+ return true;
+
+ default:
+ consumeToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+ int count = 0;
+
+ while (int tk = LA()) {
+ if (tk == l)
+ ++count;
+ else if (tk == r)
+ --count;
+ else if (l != T_LBRACE && (tk == T_LBRACE ||
+ tk == T_RBRACE ||
+ tk == T_SEMICOLON))
+ return false;
+
+ if (count == 0)
+ return true;
+
+ consumeToken();
+ }
+
+ return false;
+}
+
+void Parser::match(int kind, unsigned *token)
+{
+ if (LA() == kind)
+ *token = consumeToken();
+ else {
+ *token = 0;
+ _translationUnit->error(_tokenIndex, "expected token `%s' got `%s'",
+ Token::name(kind), tok().spell());
+ }
+}
+
+bool Parser::parseClassOrNamespaceName(NameAST *&node)
+{
+ if (LA() == T_IDENTIFIER) {
+ unsigned identifier_token = cursor();
+
+ if (LA(2) == T_LESS && parseTemplateId(node) && LA() == T_COLON_COLON)
+ return true;
+
+ rewind(identifier_token);
+
+ if (LA(2) == T_COLON_COLON) {
+ SimpleNameAST *ast = new (_pool) SimpleNameAST;
+ ast->identifier_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ } else if (LA() == T_TEMPLATE) {
+ unsigned template_token = consumeToken();
+ if (parseTemplateId(node))
+ return true;
+ rewind(template_token);
+ }
+ return false;
+}
+
+bool Parser::parseTemplateId(NameAST *&node)
+{
+ if (LA() == T_IDENTIFIER && LA(2) == T_LESS) {
+ TemplateIdAST *ast = new (_pool) TemplateIdAST;
+ ast->identifier_token = consumeToken();
+ ast->less_token = consumeToken();
+ if (LA() == T_GREATER || parseTemplateArgumentList(
+ ast->template_arguments)) {
+ if (LA() == T_GREATER) {
+ ast->greater_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Parser::parseNestedNameSpecifier(NestedNameSpecifierAST *&node,
+ bool /*acceptTemplateId*/)
+{
+ NestedNameSpecifierAST **nested_name_specifier = &node;
+ NameAST *class_or_namespace_name = 0;
+ if (parseClassOrNamespaceName(class_or_namespace_name) &&
+ LA() == T_COLON_COLON) {
+ unsigned scope_token = consumeToken();
+ *nested_name_specifier = new (_pool) NestedNameSpecifierAST;
+ (*nested_name_specifier)->class_or_namespace_name
+ = class_or_namespace_name;
+ (*nested_name_specifier)->scope_token = scope_token;
+
+ nested_name_specifier = &(*nested_name_specifier)->next;
+
+ while (parseClassOrNamespaceName(class_or_namespace_name) &&
+ LA() == T_COLON_COLON) {
+ scope_token = consumeToken();
+ *nested_name_specifier = new (_pool) NestedNameSpecifierAST;
+ (*nested_name_specifier)->class_or_namespace_name = class_or_namespace_name;
+ (*nested_name_specifier)->scope_token = scope_token;
+ nested_name_specifier = &(*nested_name_specifier)->next;
+ }
+
+ // ### ugly hack
+ rewind(scope_token);
+ consumeToken();
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name,
+ bool acceptTemplateId)
+{
+ unsigned start = cursor();
+ if (! parseNestedNameSpecifier(name, acceptTemplateId))
+ rewind(start);
+ return true;
+}
+
+bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
+{
+ unsigned global_scope_token = 0;
+ if (LA() == T_COLON_COLON)
+ global_scope_token = consumeToken();
+
+ NestedNameSpecifierAST *nested_name_specifier = 0;
+ parseNestedNameSpecifierOpt(nested_name_specifier,
+ /*acceptTemplateId=*/ true);
+
+ NameAST *unqualified_name = 0;
+ if (parseUnqualifiedName(unqualified_name,
+ /*acceptTemplateId=*/ acceptTemplateId || nested_name_specifier != 0)) {
+ if (! global_scope_token && ! nested_name_specifier) {
+ node = unqualified_name;
+ return true;
+ }
+
+ QualifiedNameAST *ast = new (_pool) QualifiedNameAST;
+ ast->global_scope_token = global_scope_token;
+ ast->nested_name_specifier = nested_name_specifier;
+ ast->unqualified_name = unqualified_name;
+ node = ast;
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+ TranslationUnitAST *ast = new (_pool) TranslationUnitAST;
+ DeclarationAST **decl = &ast->declarations;
+
+ while (LA()) {
+ unsigned start_declaration = cursor();
+
+ if (parseDeclaration(*decl)) {
+ if (*decl)
+ decl = &(*decl)->next;
+ } else {
+ rewind(start_declaration + 1);
+ skipUntilDeclaration();
+ }
+ }
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseEmptyDeclaration(DeclarationAST *&node)
+{
+ if (LA() == T_SEMICOLON) {
+ EmptyDeclarationAST *ast = new (_pool) EmptyDeclarationAST;
+ ast->semicolon_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+ switch (LA()) {
+ case T_SEMICOLON:
+ return parseEmptyDeclaration(node);
+
+ case T_NAMESPACE:
+ return parseNamespace(node);
+
+ case T_USING:
+ return parseUsing(node);
+
+ case T_ASM:
+ return parseAsmDefinition(node);
+
+ case T_TEMPLATE:
+ case T_EXPORT:
+ return parseTemplateDeclaration(node);
+
+ // ObjcC++
+ case T_AT_CLASS:
+ return parseObjCClassDeclaration(node);
+
+ case T_AT_INTERFACE:
+ return parseObjCInterface(node);
+
+ case T_AT_PROTOCOL:
+ return parseObjCProtocol(node);
+
+ case T_AT_IMPLEMENTATION:
+ return parseObjCImplementation(node);
+
+ case T_AT_END:
+ return parseObjCEnd(node);
+
+ default: {
+ if (_objCEnabled && LA() == T___ATTRIBUTE__) {
+ const unsigned start = cursor();
+ SpecifierAST *attributes = 0, **attr = &attributes;
+ while (parseAttributeSpecifier(*attr))
+ attr = &(*attr)->next;
+ if (LA() == T_AT_INTERFACE)
+ return parseObjCInterface(node, attributes);
+ else if (LA() == T_AT_PROTOCOL)
+ return parseObjCProtocol(node, attributes);
+ else if (LA() == T_AT_PROPERTY)
+ return parseObjCPropertyDeclaration(node, attributes);
+ rewind(start);
+ }
+
+ if (LA() == T_EXTERN && LA(2) == T_TEMPLATE)
+ return parseTemplateDeclaration(node);
+ else if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL)
+ return parseLinkageSpecification(node);
+ else
+ return parseSimpleDeclaration(node);
+ } break; // default
+
+ } // end switch
+
+ return false;
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+ if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) {
+ LinkageSpecificationAST *ast = new (_pool) LinkageSpecificationAST;
+ ast->extern_token = consumeToken();
+ ast->extern_type = consumeToken();
+
+ if (LA() == T_LBRACE)
+ parseLinkageBody(ast->declaration);
+ else
+ parseDeclaration(ast->declaration);
+
+ node = ast;
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseLinkageBody(DeclarationAST *&node)
+{
+ if (LA() == T_LBRACE) {
+ LinkageBodyAST *ast = new (_pool) LinkageBodyAST;
+ ast->lbrace_token = consumeToken();
+ DeclarationAST **declaration_ptr = &ast->declarations;
+
+ while (int tk = LA()) {
+ if (tk == T_RBRACE)
+ break;
+
+ unsigned start_declaration = cursor();
+ if (parseDeclaration(*declaration_ptr)) {
+ if (*declaration_ptr) // ### remove me
+ declaration_ptr = &(*declaration_ptr)->next;
+ } else {
+ rewind(start_declaration + 1);
+ skipUntilDeclaration();
+ }
+ }
+ match(T_RBRACE, &ast->rbrace_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+// ### rename parseNamespaceAliarOrDeclaration?
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+ if (LA() != T_NAMESPACE)
+ return false;
+
+ unsigned namespace_token = consumeToken();
+
+ if (LA() == T_IDENTIFIER && LA(2) == T_EQUAL) {
+ NamespaceAliasDefinitionAST *ast =
+ new (_pool) NamespaceAliasDefinitionAST;
+ ast->namespace_token = namespace_token;
+ ast->namespace_name = consumeToken();
+ ast->equal_token = consumeToken();
+ parseName(ast->name);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+
+ NamespaceAST *ast = new (_pool) NamespaceAST;
+ ast->namespace_token = namespace_token;
+ if (LA() == T_IDENTIFIER)
+ ast->identifier_token = consumeToken();
+ SpecifierAST **attr_ptr = &ast->attributes;
+ while (LA() == T___ATTRIBUTE__) {
+ parseAttributeSpecifier(*attr_ptr);
+ attr_ptr = &(*attr_ptr)->next;
+ }
+ if (LA() == T_LBRACE)
+ parseLinkageBody(ast->linkage_body);
+ node = ast;
+ return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+ if (LA() != T_USING)
+ return false;
+
+ if (LA(2) == T_NAMESPACE)
+ return parseUsingDirective(node);
+
+ UsingAST *ast = new (_pool) UsingAST;
+ ast->using_token = consumeToken();
+
+ if (LA() == T_TYPENAME)
+ ast->typename_token = consumeToken();
+
+ parseName(ast->name);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+ if (LA() == T_USING && LA(2) == T_NAMESPACE) {
+ UsingDirectiveAST *ast = new (_pool) UsingDirectiveAST;
+ ast->using_token = consumeToken();
+ ast->namespace_token = consumeToken();
+ if (! parseName(ast->name))
+ _translationUnit->warning(cursor(), "expected `namespace name' before `%s'",
+ tok().spell());
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseConversionFunctionId(NameAST *&node)
+{
+ if (LA() != T_OPERATOR)
+ return false;
+ unsigned operator_token = consumeToken();
+ SpecifierAST *type_specifier = 0;
+ if (! parseTypeSpecifier(type_specifier)) {
+ return false;
+ }
+ PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+ while (parsePtrOperator(*ptr_operators_tail))
+ ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+ ConversionFunctionIdAST *ast = new (_pool) ConversionFunctionIdAST;
+ ast->operator_token = operator_token;
+ ast->type_specifier = type_specifier;
+ ast->ptr_operators = ptr_operators;
+ node = ast;
+ return true;
+}
+
+bool Parser::parseOperatorFunctionId(NameAST *&node)
+{
+ if (LA() != T_OPERATOR)
+ return false;
+ unsigned operator_token = consumeToken();
+
+ OperatorAST *op = 0;
+ if (! parseOperator(op))
+ return false;
+
+ OperatorFunctionIdAST *ast = new (_pool) OperatorFunctionIdAST;
+ ast->operator_token = operator_token;
+ ast->op = op;
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node)
+{
+ TemplateArgumentListAST **template_argument_ptr = &node;
+ ExpressionAST *template_argument = 0;
+ if (parseTemplateArgument(template_argument)) {
+ *template_argument_ptr = new (_pool) TemplateArgumentListAST;
+ (*template_argument_ptr)->template_argument = template_argument;
+ template_argument_ptr = &(*template_argument_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (parseTemplateArgument(template_argument)) {
+ *template_argument_ptr = new (_pool) TemplateArgumentListAST;
+ (*template_argument_ptr)->template_argument = template_argument;
+ template_argument_ptr = &(*template_argument_ptr)->next;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+ if (LA() == T_ASM) {
+ AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST;
+ ast->asm_token = consumeToken();
+ parseCvQualifiers(ast->cv_qualifier_seq);
+ if (LA() == T_LPAREN) {
+ ast->lparen_token = cursor();
+ if (skip(T_LPAREN, T_RPAREN))
+ ast->rparen_token = consumeToken();
+ }
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+ if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN)
+ && LA(2) == T_TEMPLATE)))
+ return false;
+
+ TemplateDeclarationAST *ast = new (_pool) TemplateDeclarationAST;
+
+ if (LA() == T_EXPORT || LA() == T_EXPORT)
+ ast->export_token = consumeToken();
+
+ ast->template_token = consumeToken();
+
+ if (LA() == T_LESS) {
+ ast->less_token = consumeToken();
+ if (LA() == T_GREATER || parseTemplateParameterList(ast->template_parameters))
+ match(T_GREATER, &ast->greater_token);
+ }
+
+ parseDeclaration(ast->declaration);
+ node = ast;
+ return true;
+}
+
+bool Parser::parseOperator(OperatorAST *&node) // ### FIXME
+{
+ OperatorAST *ast = new (_pool) OperatorAST;
+
+ switch (LA()) {
+ case T_NEW:
+ case T_DELETE: {
+ ast->op_token = consumeToken();
+ if (LA() == T_LBRACKET) {
+ ast->open_token = consumeToken();
+ match(T_RBRACKET, &ast->close_token);
+ }
+ } break;
+
+ case T_PLUS:
+ case T_MINUS:
+ case T_STAR:
+ case T_SLASH:
+ case T_PERCENT:
+ case T_CARET:
+ case T_AMPER:
+ case T_PIPE:
+ case T_TILDE:
+ case T_EXCLAIM:
+ case T_LESS:
+ case T_GREATER:
+ case T_COMMA:
+ case T_AMPER_EQUAL:
+ case T_CARET_EQUAL:
+ case T_SLASH_EQUAL:
+ case T_EQUAL:
+ case T_EQUAL_EQUAL:
+ case T_EXCLAIM_EQUAL:
+ case T_GREATER_EQUAL:
+ case T_GREATER_GREATER_EQUAL:
+ case T_LESS_EQUAL:
+ case T_LESS_LESS_EQUAL:
+ case T_MINUS_EQUAL:
+ case T_PERCENT_EQUAL:
+ case T_PIPE_EQUAL:
+ case T_PLUS_EQUAL:
+ case T_STAR_EQUAL:
+ case T_TILDE_EQUAL:
+ case T_LESS_LESS:
+ case T_GREATER_GREATER:
+ case T_AMPER_AMPER:
+ case T_PIPE_PIPE:
+ case T_PLUS_PLUS:
+ case T_MINUS_MINUS:
+ case T_ARROW_STAR:
+ case T_DOT_STAR:
+ case T_ARROW:
+ ast->op_token = consumeToken();
+ break;
+
+ default:
+ if (LA() == T_LPAREN && LA(2) == T_RPAREN) {
+ ast->op_token = ast->open_token = consumeToken();
+ ast->close_token = consumeToken();
+ } else if (LA() == T_LBRACKET && LA(2) == T_RBRACKET) {
+ ast->op_token = ast->open_token = consumeToken();
+ ast->close_token = consumeToken();
+ } else {
+ return false;
+ }
+ }
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseCvQualifiers(SpecifierAST *&node)
+{
+ unsigned start = cursor();
+ SpecifierAST **ast = &node;
+ while (*ast)
+ ast = &(*ast)->next;
+
+ while (int tk = LA()) {
+ if (tk == T_CONST || tk == T_VOLATILE) {
+ SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+ spec->specifier_token = consumeToken();
+ *ast = spec;
+ ast = &(*ast)->next;
+ } else if(LA() == T___ATTRIBUTE__) {
+ parseAttributeSpecifier(*ast);
+ ast = &(*ast)->next;
+ } else {
+ break;
+ }
+ }
+
+ return start != cursor();
+}
+
+bool Parser::parsePtrOperator(PtrOperatorAST *&node)
+{
+ if (LA() == T_AMPER) {
+ ReferenceAST *ast = new (_pool) ReferenceAST;
+ ast->amp_token = consumeToken();
+ node = ast;
+ return true;
+ } else if (LA() == T_STAR) {
+ PointerAST *ast = new (_pool) PointerAST;
+ ast->star_token = consumeToken();
+ parseCvQualifiers(ast->cv_qualifier_seq);
+ node = ast;
+ return true;
+ } else if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER) {
+ unsigned scope_or_identifier_token = cursor();
+
+ unsigned global_scope_token = 0;
+ if (LA() == T_COLON_COLON)
+ global_scope_token = consumeToken();
+
+ NestedNameSpecifierAST *nested_name_specifier = 0;
+ bool has_nested_name_specifier = parseNestedNameSpecifier(
+ nested_name_specifier, true);
+ if (has_nested_name_specifier && LA() == T_STAR) {
+ PointerToMemberAST *ast = new (_pool) PointerToMemberAST;
+ ast->global_scope_token = global_scope_token;
+ ast->nested_name_specifier = nested_name_specifier;
+ ast->star_token = consumeToken();
+ parseCvQualifiers(ast->cv_qualifier_seq);
+ node = ast;
+ return true;
+ }
+ rewind(scope_or_identifier_token);
+ }
+ return false;
+}
+
+bool Parser::parseTemplateArgument(ExpressionAST *&node)
+{
+ unsigned start = cursor();
+ if (parseTypeId(node) && (LA() == T_COMMA || LA() == T_GREATER))
+ return true;
+
+ rewind(start);
+ bool previousTemplateArguments = switchTemplateArguments(true);
+ bool parsed = parseLogicalOrExpression(node);
+ (void) switchTemplateArguments(previousTemplateArguments);
+ return parsed;
+}
+
+bool Parser::parseDeclSpecifierSeq(SpecifierAST *&decl_specifier_seq,
+ bool onlyTypeSpecifiers,
+ bool simplified)
+{
+ bool has_type_specifier = false;
+ NameAST *named_type_specifier = 0;
+ SpecifierAST **decl_specifier_seq_ptr = &decl_specifier_seq;
+ for (;;) {
+ if (lookAtCVQualifier()) {
+ SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+ spec->specifier_token = consumeToken();
+ *decl_specifier_seq_ptr = spec;
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ } else if (! onlyTypeSpecifiers && lookAtStorageClassSpecifier()) {
+ SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+ spec->specifier_token = consumeToken();
+ *decl_specifier_seq_ptr = spec;
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ } else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) {
+ parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else if (! has_type_specifier && (LA() == T_COLON_COLON ||
+ LA() == T_IDENTIFIER)) {
+ if (! parseName(named_type_specifier))
+ return false;
+ NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
+ spec->name = named_type_specifier;
+ *decl_specifier_seq_ptr = spec;
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else if (! simplified && ! has_type_specifier && (LA() == T_TYPENAME ||
+ LA() == T_ENUM ||
+ lookAtClassKey())) {
+ unsigned startOfElaboratedTypeSpecifier = cursor();
+ if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
+ _translationUnit->error(startOfElaboratedTypeSpecifier,
+ "expected an elaborated type specifier");
+ break;
+ }
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else
+ break;
+ }
+
+ return decl_specifier_seq != 0;
+}
+
+bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node)
+{
+ unsigned start = cursor();
+ bool blocked = blockErrors(true);
+ if (parseDeclarator(node)) {
+ blockErrors(blocked);
+ return true;
+ }
+ blockErrors(blocked);
+ rewind(start);
+ return parseAbstractDeclarator(node);
+}
+
+bool Parser::parseCoreDeclarator(DeclaratorAST *&node)
+{
+ PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+ while (parsePtrOperator(*ptr_operators_tail))
+ ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+ if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER || LA() == T_TILDE
+ || LA() == T_OPERATOR) {
+ NameAST *name = 0;
+ if (parseName(name)) {
+ DeclaratorIdAST *declarator_id = new (_pool) DeclaratorIdAST;
+ declarator_id->name = name;
+ DeclaratorAST *ast = new (_pool) DeclaratorAST;
+ ast->ptr_operators = ptr_operators;
+ ast->core_declarator = declarator_id;
+ node = ast;
+ return true;
+ }
+ } else if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ DeclaratorAST *declarator = 0;
+ if (parseDeclarator(declarator) && LA() == T_RPAREN) {
+ NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST;
+ nested_declarator->lparen_token = lparen_token;
+ nested_declarator->declarator = declarator;
+ nested_declarator->rparen_token = consumeToken();
+ DeclaratorAST *ast = new (_pool) DeclaratorAST;
+ ast->ptr_operators = ptr_operators;
+ ast->core_declarator = nested_declarator;
+ node = ast;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+ if (! parseCoreDeclarator(node))
+ return false;
+
+ PostfixDeclaratorAST **postfix_ptr = &node->postfix_declarators;
+
+ for (;;) {
+ unsigned startOfPostDeclarator = cursor();
+
+ if (LA() == T_LPAREN) {
+ FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST;
+ ast->lparen_token = consumeToken();
+ parseParameterDeclarationClause(ast->parameters);
+ if (LA() != T_RPAREN) {
+ rewind(startOfPostDeclarator);
+ break;
+ }
+
+ ast->rparen_token = consumeToken();
+ parseCvQualifiers(ast->cv_qualifier_seq);
+ parseExceptionSpecification(ast->exception_specification);
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else if (LA() == T_LBRACKET) {
+ ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST;
+ ast->lbracket_token = consumeToken();
+ if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) {
+ match(T_RBRACKET, &ast->rbracket_token);
+ }
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else
+ break;
+ }
+
+ SpecifierAST **spec_ptr = &node->attributes;
+ while (LA() == T___ATTRIBUTE__) {
+ parseAttributeSpecifier(*spec_ptr);
+ spec_ptr = &(*spec_ptr)->next;
+ }
+
+ return true;
+}
+
+bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node)
+{
+ PtrOperatorAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
+ while (parsePtrOperator(*ptr_operators_tail))
+ ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+ unsigned after_ptr_operators = cursor();
+
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ DeclaratorAST *declarator = 0;
+ if (parseAbstractDeclarator(declarator) && LA() == T_RPAREN) {
+ NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST;
+ nested_declarator->lparen_token = lparen_token;
+ nested_declarator->declarator = declarator;
+ nested_declarator->rparen_token = consumeToken();
+ DeclaratorAST *ast = new (_pool) DeclaratorAST;
+ ast->ptr_operators = ptr_operators;
+ ast->core_declarator = nested_declarator;
+ node = ast;
+ return true;
+ }
+ }
+
+ rewind(after_ptr_operators);
+ if (ptr_operators) {
+ DeclaratorAST *ast = new (_pool) DeclaratorAST;
+ ast->ptr_operators = ptr_operators;
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+ if (! parseAbstractCoreDeclarator(node))
+ return false;
+
+ PostfixDeclaratorAST *postfix_declarators = 0,
+ **postfix_ptr = &postfix_declarators;
+
+ for (;;) {
+ if (LA() == T_LPAREN) {
+ FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST;
+ ast->lparen_token = consumeToken();
+ if (LA() == T_RPAREN || parseParameterDeclarationClause(ast->parameters)) {
+ if (LA() == T_RPAREN)
+ ast->rparen_token = consumeToken();
+ }
+ parseCvQualifiers(ast->cv_qualifier_seq);
+ parseExceptionSpecification(ast->exception_specification);
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else if (LA() == T_LBRACKET) {
+ ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST;
+ ast->lbracket_token = consumeToken();
+ if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) {
+ if (LA() == T_RBRACKET)
+ ast->rbracket_token = consumeToken();
+ }
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else
+ break;
+ }
+
+ if (postfix_declarators) {
+ if (! node)
+ node = new (_pool) DeclaratorAST;
+
+ node->postfix_declarators = postfix_declarators;
+ }
+
+ return true;
+}
+
+bool Parser::parseEnumSpecifier(SpecifierAST *&node)
+{
+ if (LA() == T_ENUM) {
+ unsigned enum_token = consumeToken();
+ NameAST *name = 0;
+ parseName(name);
+ if (LA() == T_LBRACE) {
+ EnumSpecifierAST *ast = new (_pool) EnumSpecifierAST;
+ ast->enum_token = enum_token;
+ ast->name = name;
+ ast->lbrace_token = consumeToken();
+ EnumeratorAST **enumerator_ptr = &ast->enumerators;
+ while (int tk = LA()) {
+ if (tk == T_RBRACE)
+ break;
+
+ if (LA() != T_IDENTIFIER) {
+ _translationUnit->error(cursor(), "expected identifier before '%s'", tok().spell());
+ skipUntil(T_IDENTIFIER);
+ }
+
+ if (parseEnumerator(*enumerator_ptr))
+ enumerator_ptr = &(*enumerator_ptr)->next;
+
+ if (LA() != T_RBRACE) {
+ unsigned comma_token = 0;
+ match(T_COMMA, &comma_token);
+ }
+ }
+ match(T_RBRACE, &ast->rbrace_token);
+ node = ast;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::parseTemplateParameterList(DeclarationAST *&node)
+{
+ DeclarationAST **template_parameter_ptr = &node;
+ if (parseTemplateParameter(*template_parameter_ptr)) {
+ template_parameter_ptr = &(*template_parameter_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (parseTemplateParameter(*template_parameter_ptr))
+ template_parameter_ptr = &(*template_parameter_ptr)->next;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseTemplateParameter(DeclarationAST *&node)
+{
+ if (parseTypeParameter(node))
+ return true;
+ bool previousTemplateArguments = switchTemplateArguments(true);
+ bool parsed = parseParameterDeclaration(node);
+ (void) switchTemplateArguments(previousTemplateArguments);
+ return parsed;
+}
+
+bool Parser::parseTypenameTypeParameter(DeclarationAST *&node)
+{
+ if (LA() == T_CLASS || LA() == T_TYPENAME) {
+ TypenameTypeParameterAST *ast = new (_pool) TypenameTypeParameterAST;
+ ast->classkey_token = consumeToken();
+ parseName(ast->name);
+ if (LA() == T_EQUAL) {
+ ast->equal_token = consumeToken();
+ parseTypeId(ast->type_id);
+ }
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseTemplateTypeParameter(DeclarationAST *&node)
+{
+ if (LA() == T_TEMPLATE) {
+ TemplateTypeParameterAST *ast = new (_pool) TemplateTypeParameterAST;
+ ast->template_token = consumeToken();
+ if (LA() == T_LESS)
+ ast->less_token = consumeToken();
+ parseTemplateParameterList(ast->template_parameters);
+ if (LA() == T_GREATER)
+ ast->greater_token = consumeToken();
+ if (LA() == T_CLASS)
+ ast->class_token = consumeToken();
+
+ // parse optional name
+ parseName(ast->name);
+
+ if (LA() == T_EQUAL) {
+ ast->equal_token = consumeToken();
+ parseTypeId(ast->type_id);
+ }
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseTypeParameter(DeclarationAST *&node)
+{
+ if (LA() == T_CLASS || LA() == T_TYPENAME)
+ return parseTypenameTypeParameter(node);
+ else if (LA() == T_TEMPLATE)
+ return parseTemplateTypeParameter(node);
+ else
+ return false;
+}
+
+bool Parser::parseTypeId(ExpressionAST *&node)
+{
+ SpecifierAST *type_specifier = 0;
+ if (parseTypeSpecifier(type_specifier)) {
+ TypeIdAST *ast = new (_pool) TypeIdAST;
+ ast->type_specifier = type_specifier;
+ parseAbstractDeclarator(ast->declarator);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+ DeclarationAST *parameter_declarations = 0;
+ if (LA() != T_DOT_DOT_DOT)
+ parseParameterDeclarationList(parameter_declarations);
+ unsigned dot_dot_dot_token = 0;
+ if (LA() == T_DOT_DOT_DOT || (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT)) {
+ if (LA() == T_COMMA)
+ consumeToken();
+ dot_dot_dot_token = consumeToken();
+ }
+ ParameterDeclarationClauseAST *ast = new (_pool) ParameterDeclarationClauseAST;
+ ast->parameter_declarations = parameter_declarations;
+ ast->dot_dot_dot_token = dot_dot_dot_token;
+ node = ast;
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList(DeclarationAST *&node)
+{
+ DeclarationAST **parameter_declaration_ptr = &node;
+ if (parseParameterDeclaration(*parameter_declaration_ptr)) {
+ parameter_declaration_ptr = &(*parameter_declaration_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (LA() == T_DOT_DOT_DOT)
+ break;
+
+ if (parseParameterDeclaration(*parameter_declaration_ptr))
+ parameter_declaration_ptr = &(*parameter_declaration_ptr)->next;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseParameterDeclaration(DeclarationAST *&node)
+{
+ SpecifierAST *decl_specifier_seq = 0;
+ if (parseDeclSpecifierSeq(decl_specifier_seq)) {
+ ParameterDeclarationAST *ast = new (_pool) ParameterDeclarationAST;
+ ast->type_specifier = decl_specifier_seq;
+ parseDeclaratorOrAbstractDeclarator(ast->declarator);
+ if (LA() == T_EQUAL) {
+ ast->equal_token = consumeToken();
+ parseLogicalOrExpression(ast->expression);
+ }
+
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseClassSpecifier(SpecifierAST *&node)
+{
+ if (! lookAtClassKey())
+ return false;
+
+ unsigned classkey_token = consumeToken();
+
+ SpecifierAST *attributes = 0, **attr_ptr = &attributes;
+ while (LA() == T___ATTRIBUTE__) {
+ parseAttributeSpecifier(*attr_ptr);
+ attr_ptr = &(*attr_ptr)->next;
+ }
+
+ if (LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER) {
+ _translationUnit->warning(cursor(), "skip identifier `%s'",
+ tok().spell());
+ consumeToken();
+ }
+
+ NameAST *name = 0;
+ parseName(name);
+
+ bool parsed = false;
+
+ const bool previousInFunctionBody = _inFunctionBody;
+ _inFunctionBody = false;
+
+ unsigned colon_token = 0;
+
+ if (LA() == T_COLON || LA() == T_LBRACE) {
+ BaseSpecifierAST *base_clause = 0;
+ if (LA() == T_COLON) {
+ colon_token = cursor();
+ parseBaseClause(base_clause);
+ if (LA() != T_LBRACE) {
+ _translationUnit->error(cursor(), "expected `{' before `%s'", tok().spell());
+ unsigned saved = cursor();
+ for (int n = 0; n < 3 && LA() != T_EOF_SYMBOL; ++n, consumeToken()) {
+ if (LA() == T_LBRACE)
+ break;
+ }
+ if (LA() != T_LBRACE)
+ rewind(saved);
+ }
+ }
+
+ ClassSpecifierAST *ast = new (_pool) ClassSpecifierAST;
+ ast->classkey_token = classkey_token;
+ ast->attributes = attributes;
+ ast->name = name;
+ ast->colon_token = colon_token;
+ ast->base_clause = base_clause;
+
+ if (LA() == T_LBRACE)
+ ast->lbrace_token = consumeToken();
+
+ DeclarationAST **declaration_ptr = &ast->member_specifiers;
+ while (int tk = LA()) {
+ if (tk == T_RBRACE) {
+ ast->rbrace_token = consumeToken();
+ break;
+ }
+
+ unsigned start_declaration = cursor();
+ if (parseMemberSpecification(*declaration_ptr)) {
+ if (*declaration_ptr)
+ declaration_ptr = &(*declaration_ptr)->next;
+ } else {
+ rewind(start_declaration + 1);
+ skipUntilDeclaration();
+ }
+ }
+ node = ast;
+ parsed = true;
+ }
+
+ _inFunctionBody = previousInFunctionBody;
+
+ return parsed;
+}
+
+bool Parser::parseAccessSpecifier(SpecifierAST *&node)
+{
+ switch (LA()) {
+ case T_PUBLIC:
+ case T_PROTECTED:
+ case T_PRIVATE: {
+ SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST;
+ ast->specifier_token = consumeToken();
+ node = ast;
+ return true;
+ }
+
+ default:
+ return false;
+ } // switch
+}
+
+bool Parser::parseAccessDeclaration(DeclarationAST *&node)
+{
+ if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_SIGNALS) {
+ bool isSignals = LA() == T_SIGNALS;
+ AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST;
+ ast->access_specifier_token = consumeToken();
+ if (! isSignals && LA() == T_SLOTS)
+ ast->slots_token = consumeToken();
+ match(T_COLON, &ast->colon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+ switch (LA()) {
+ case T_SEMICOLON:
+ return parseEmptyDeclaration(node);
+
+ case T_USING:
+ return parseUsing(node);
+
+ case T_TEMPLATE:
+ return parseTemplateDeclaration(node);
+
+ case T_SIGNALS:
+ case T_PUBLIC:
+ case T_PROTECTED:
+ case T_PRIVATE:
+ return parseAccessDeclaration(node);
+
+ default:
+ return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true);
+ } // switch
+}
+
+bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
+{
+ if (LA() == T_COLON) {
+ unsigned colon_token = consumeToken();
+
+ CtorInitializerAST *ast = new (_pool) CtorInitializerAST;
+ ast->colon_token = colon_token;
+
+ parseMemInitializerList(ast->member_initializers);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(SpecifierAST *&node)
+{
+ if (lookAtClassKey() || LA() == T_ENUM || LA() == T_TYPENAME) {
+ unsigned classkey_token = consumeToken();
+ NameAST *name = 0;
+ if (parseName(name)) {
+ ElaboratedTypeSpecifierAST *ast =
+ new (_pool) ElaboratedTypeSpecifierAST;
+
+ ast->classkey_token = classkey_token;
+ ast->name = name;
+ node = ast;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
+{
+ if (LA() == T_THROW) {
+ ExceptionSpecificationAST *ast = new (_pool) ExceptionSpecificationAST;
+ ast->throw_token = consumeToken();
+ if (LA() == T_LPAREN)
+ ast->lparen_token = consumeToken();
+ if (LA() == T_DOT_DOT_DOT)
+ ast->dot_dot_dot_token = consumeToken();
+ else
+ parseTypeIdList(ast->type_ids);
+ if (LA() == T_RPAREN)
+ ast->rparen_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+ if (LA() == T_IDENTIFIER) {
+ EnumeratorAST *ast = new (_pool) EnumeratorAST;
+ ast->identifier_token = consumeToken();
+
+ if (LA() == T_EQUAL) {
+ ast->equal_token = consumeToken();
+ parseConstantExpression(ast->expression);
+ }
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseInitDeclarator(DeclaratorAST *&node,
+ bool acceptStructDeclarator)
+{
+ unsigned start = cursor();
+
+ if (acceptStructDeclarator && LA() == T_COLON) {
+ // anonymous bit-field declaration.
+ // ### TODO create the AST
+ } else if (! parseDeclarator(node)) {
+ return false;
+ }
+
+ if (LA() == T_ASM && LA(2) == T_LPAREN) { // ### FIXME
+ consumeToken();
+
+ if (skip(T_LPAREN, T_RPAREN))
+ consumeToken();
+ }
+
+ if (acceptStructDeclarator && node &&
+ ! node->postfix_declarators &&
+ node->core_declarator &&
+ node->core_declarator->asNestedDeclarator()) {
+ rewind(start);
+ return false;
+ }
+
+ if (acceptStructDeclarator && LA() == T_COLON
+ && (! node || ! node->postfix_declarators)) {
+ unsigned colon_token = consumeToken();
+ ExpressionAST *expression = 0;
+ if (parseConstantExpression(expression) && (LA() == T_COMMA ||
+ LA() == T_SEMICOLON)) {
+ // recognized a bitfielddeclarator.
+ // ### TODO create the AST
+ return true;
+ }
+ rewind(colon_token);
+ } else if (LA() == T_EQUAL || (! acceptStructDeclarator && LA() == T_LPAREN)) {
+ parseInitializer(node->initializer);
+ }
+ return true;
+}
+
+bool Parser::parseBaseClause(BaseSpecifierAST *&node)
+{
+ if (LA() == T_COLON) {
+ consumeToken();
+
+ BaseSpecifierAST **ast = &node;
+ if (parseBaseSpecifier(*ast)) {
+ ast = &(*ast)->next;
+
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (parseBaseSpecifier(*ast))
+ ast = &(*ast)->next;
+ }
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseInitializer(ExpressionAST *&node)
+{
+ if (LA() == T_LPAREN) {
+ return parsePrimaryExpression(node);
+ } else if (LA() == T_EQUAL) {
+ consumeToken();
+ return parseInitializerClause(node);
+ }
+ return false;
+}
+
+bool Parser::parseMemInitializerList(MemInitializerAST *&node)
+{
+ MemInitializerAST **initializer = &node;
+
+ if (parseMemInitializer(*initializer)) {
+ initializer = &(*initializer)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+ if (parseMemInitializer(*initializer))
+ initializer = &(*initializer)->next;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseMemInitializer(MemInitializerAST *&node)
+{
+ NameAST *name = 0;
+ if (parseName(name) && LA() == T_LPAREN) {
+ MemInitializerAST *ast = new (_pool) MemInitializerAST;
+ ast->name = name;
+ ast->lparen_token = consumeToken();
+ parseExpression(ast->expression);
+ if (LA() == T_RPAREN)
+ ast->rparen_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseTypeIdList(ExpressionListAST *&node)
+{
+ ExpressionListAST **expression_list_ptr = &node;
+ ExpressionAST *typeId = 0;
+ if (parseTypeId(typeId)) {
+ *expression_list_ptr = new (_pool) ExpressionListAST;
+ (*expression_list_ptr)->expression = typeId;
+ expression_list_ptr = &(*expression_list_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (parseTypeId(typeId)) {
+ *expression_list_ptr = new (_pool) ExpressionListAST;
+ (*expression_list_ptr)->expression = typeId;
+ expression_list_ptr = &(*expression_list_ptr)->next;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseExpressionList(ExpressionListAST *&node)
+{
+ ExpressionListAST **expression_list_ptr = &node;
+ ExpressionAST *expression = 0;
+ if (parseAssignmentExpression(expression)) {
+ *expression_list_ptr = new (_pool) ExpressionListAST;
+ (*expression_list_ptr)->expression = expression;
+ expression_list_ptr = &(*expression_list_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (parseExpression(expression)) {
+ *expression_list_ptr = new (_pool) ExpressionListAST;
+ (*expression_list_ptr)->expression = expression;
+ expression_list_ptr = &(*expression_list_ptr)->next;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+ BaseSpecifierAST *ast = new (_pool) BaseSpecifierAST;
+
+ if (LA() == T_VIRTUAL) {
+ ast->token_virtual = consumeToken();
+
+ int tk = LA();
+ if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE)
+ ast->token_access_specifier = consumeToken();
+ } else {
+ int tk = LA();
+ if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE)
+ ast->token_access_specifier = consumeToken();
+
+ if (LA() == T_VIRTUAL)
+ ast->token_virtual = consumeToken();
+ }
+
+ parseName(ast->name);
+ if (! ast->name)
+ _translationUnit->error(cursor(), "expected class-name");
+ node = ast;
+ return true;
+}
+
+bool Parser::parseInitializerList(ExpressionListAST *&node)
+{
+ ExpressionListAST **initializer_ptr = &node;
+ ExpressionAST *initializer = 0;
+ if (parseInitializerClause(initializer)) {
+ *initializer_ptr = new (_pool) ExpressionListAST;
+ (*initializer_ptr)->expression = initializer;
+ initializer_ptr = &(*initializer_ptr)->next;
+ while (LA() == T_COMMA) {
+ consumeToken();
+ initializer = 0;
+ parseInitializerClause(initializer);
+ *initializer_ptr = new (_pool) ExpressionListAST;
+ (*initializer_ptr)->expression = initializer;
+ initializer_ptr = &(*initializer_ptr)->next;
+ }
+ }
+ return true;
+}
+
+bool Parser::parseInitializerClause(ExpressionAST *&node)
+{
+ if (LA() == T_LBRACE) {
+ ArrayInitializerAST *ast = new (_pool) ArrayInitializerAST;
+ ast->lbrace_token = consumeToken();
+ parseInitializerList(ast->expression_list);
+ match(T_RBRACE, &ast->rbrace_token);
+ node = ast;
+ return true;
+ }
+ return parseAssignmentExpression(node);
+}
+
+bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId)
+{
+ if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) {
+ DestructorNameAST *ast = new (_pool) DestructorNameAST;
+ ast->tilde_token = consumeToken();
+ ast->identifier_token = consumeToken();
+ node = ast;
+ return true;
+ } else if (LA() == T_OPERATOR) {
+ unsigned operator_token = cursor();
+ if (parseOperatorFunctionId(node))
+ return true;
+ rewind(operator_token);
+ return parseConversionFunctionId(node);
+ } else if (LA() == T_IDENTIFIER) {
+ unsigned identifier_token = cursor();
+ if (acceptTemplateId && LA(2) == T_LESS && parseTemplateId(node)) {
+ if (! _templateArguments || (LA() == T_COMMA || LA() == T_GREATER ||
+ LA() == T_LPAREN || LA() == T_RPAREN ||
+ LA() == T_COLON_COLON))
+ return true;
+ }
+ rewind(identifier_token);
+ SimpleNameAST *ast = new (_pool) SimpleNameAST;
+ ast->identifier_token = consumeToken();
+ node = ast;
+ return true;
+ } else if (LA() == T_TEMPLATE) {
+ unsigned template_token = consumeToken();
+ if (parseTemplateId(node))
+ return true;
+ rewind(template_token);
+ }
+ return false;
+}
+
+bool Parser::parseStringLiteral(ExpressionAST *&node)
+{
+ if (! (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL))
+ return false;
+
+ StringLiteralAST **ast = reinterpret_cast<StringLiteralAST **> (&node);
+
+ while (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL) {
+ *ast = new (_pool) StringLiteralAST;
+ (*ast)->token = consumeToken();
+ ast = &(*ast)->next;
+ }
+ return true;
+}
+
+bool Parser::parseExpressionStatement(StatementAST *&node)
+{
+ ExpressionAST *expression = 0;
+ if (LA() == T_SEMICOLON || parseExpression(expression)) {
+ ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST;
+ ast->expression = expression;
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+ switch (LA()) {
+ case T_WHILE:
+ return parseWhileStatement(node);
+
+ case T_DO:
+ return parseDoStatement(node);
+
+ case T_FOR:
+ return parseForStatement(node);
+
+ case T_IF:
+ return parseIfStatement(node);
+
+ case T_SWITCH:
+ return parseSwitchStatement(node);
+
+ case T_TRY:
+ return parseTryBlockStatement(node);
+
+ case T_CASE:
+ case T_DEFAULT:
+ return parseLabeledStatement(node);
+
+ case T_BREAK:
+ return parseBreakStatement(node);
+
+ case T_CONTINUE:
+ return parseContinueStatement(node);
+
+ case T_GOTO:
+ return parseGotoStatement(node);
+
+ case T_RETURN:
+ return parseReturnStatement(node);
+
+ case T_LBRACE:
+ return parseCompoundStatement(node);
+
+ case T_ASM:
+ case T_NAMESPACE:
+ case T_USING:
+ case T_TEMPLATE:
+ case T_CLASS: case T_STRUCT: case T_UNION:
+ return parseDeclarationStatement(node);
+
+ case T_SEMICOLON: {
+ ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST;
+ ast->semicolon_token = consumeToken();
+ node = ast;
+ return true;
+ }
+
+ default:
+ if (LA() == T_IDENTIFIER && LA(2) == T_COLON)
+ return parseLabeledStatement(node);
+
+ return parseExpressionOrDeclarationStatement(node);
+ } // switch
+ return false;
+}
+
+bool Parser::parseBreakStatement(StatementAST *&node)
+{
+ if (LA() == T_BREAK) {
+ BreakStatementAST *ast = new (_pool) BreakStatementAST;
+ ast->break_token = consumeToken();
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseContinueStatement(StatementAST *&node)
+{
+ if (LA() == T_CONTINUE) {
+ ContinueStatementAST *ast = new (_pool) ContinueStatementAST;
+ ast->continue_token = consumeToken();
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseGotoStatement(StatementAST *&node)
+{
+ if (LA() == T_GOTO) {
+ GotoStatementAST *ast = new (_pool) GotoStatementAST;
+ ast->goto_token = consumeToken();
+ match(T_IDENTIFIER, &ast->identifier_token);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseReturnStatement(StatementAST *&node)
+{
+ if (LA() == T_RETURN) {
+ ReturnStatementAST *ast = new (_pool) ReturnStatementAST;
+ ast->return_token = consumeToken();
+ parseExpression(ast->expression);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const
+{
+ if (! simpleDecl)
+ return false;
+ else if (! simpleDecl->decl_specifier_seq)
+ return false;
+ else if (simpleDecl->decl_specifier_seq->next)
+ return false;
+
+ NamedTypeSpecifierAST *type_spec = simpleDecl->decl_specifier_seq->asNamedTypeSpecifier();
+ if (! type_spec)
+ return false;
+
+ DeclaratorListAST *first_declarator = simpleDecl->declarators;
+ if (! first_declarator)
+ return false;
+ else if (first_declarator->next)
+ return false;
+
+ DeclaratorAST *declarator = first_declarator->declarator;
+ if (! declarator)
+ return false;
+ else if (declarator->ptr_operators)
+ return false;
+ else if (declarator->postfix_declarators)
+ return false;
+ else if (declarator->initializer)
+ return false;
+ else if (! declarator->core_declarator)
+ return false;
+
+ NestedDeclaratorAST *nested_declarator = declarator->core_declarator->asNestedDeclarator();
+ if (! nested_declarator)
+ return false;
+
+ return true;
+}
+
+bool Parser::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const
+{
+ if (! simpleDecl->declarators) {
+ SpecifierAST *spec = simpleDecl->decl_specifier_seq;
+ if (spec && ! spec->next && spec->asNamedTypeSpecifier()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
+{
+ if (LA() == T_SEMICOLON)
+ return parseExpressionStatement(node);
+
+ unsigned start = cursor();
+ bool blocked = blockErrors(true);
+ if (parseDeclarationStatement(node)) {
+ DeclarationStatementAST *stmt = static_cast<DeclarationStatementAST *>(node);
+ SimpleDeclarationAST *simpleDecl = 0;
+ if (stmt->declaration)
+ simpleDecl = stmt->declaration->asSimpleDeclaration();
+
+ if (simpleDecl && simpleDecl->decl_specifier_seq &&
+ ! maybeFunctionCall(simpleDecl) && ! maybeSimpleExpression(simpleDecl)) {
+ unsigned end_of_declaration_statement = cursor();
+ rewind(start);
+ StatementAST *expression = 0;
+ if (! parseExpressionStatement(expression) || cursor() != end_of_declaration_statement) {
+ rewind(end_of_declaration_statement);
+ } else {
+ ExpressionOrDeclarationStatementAST *ast =
+ new (_pool) ExpressionOrDeclarationStatementAST;
+ ast->declaration = node;
+ ast->expression = expression;
+ node = ast;
+ }
+ blockErrors(blocked);
+ return true;
+ }
+ }
+
+ blockErrors(blocked);
+ rewind(start);
+ return parseExpressionStatement(node);
+}
+
+bool Parser::parseCondition(ExpressionAST *&node)
+{
+ unsigned start = cursor();
+
+ bool blocked = blockErrors(true);
+ SpecifierAST *type_specifier = 0;
+ if (parseTypeSpecifier(type_specifier)) {
+ DeclaratorAST *declarator = 0;
+ if (parseInitDeclarator(declarator, /*acceptStructDeclarator=*/false)) {
+ if (declarator->initializer) {
+ ConditionAST *ast = new (_pool) ConditionAST;
+ ast->type_specifier = type_specifier;
+ ast->declarator = declarator;
+ node = ast;
+ blockErrors(blocked);
+ return true;
+ }
+ }
+ }
+
+ blockErrors(blocked);
+ rewind(start);
+ return parseExpression(node);
+}
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+ if (LA() == T_WHILE) {
+ WhileStatementAST *ast = new (_pool) WhileStatementAST;
+ ast->while_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ parseCondition(ast->condition);
+ match(T_RPAREN, &ast->rparen_token);
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+ return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+ if (LA() == T_DO) {
+ DoStatementAST *ast = new (_pool) DoStatementAST;
+ ast->do_token = consumeToken();
+ parseStatement(ast->statement);
+ match(T_WHILE, &ast->while_token);
+ match(T_LPAREN, &ast->lparen_token);
+ parseExpression(ast->expression);
+ match(T_RPAREN, &ast->rparen_token);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+ if (LA() == T_FOR) {
+ ForStatementAST *ast = new (_pool) ForStatementAST;
+ ast->for_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ parseForInitStatement(ast->initializer);
+ parseExpression(ast->condition);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ parseExpression(ast->expression);
+ match(T_RPAREN, &ast->rparen_token);
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+ return parseExpressionOrDeclarationStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+ if (LA() == T_LBRACE) {
+ CompoundStatementAST *ast = new (_pool) CompoundStatementAST;
+ ast->lbrace_token = consumeToken();
+ StatementAST **statement_ptr = &ast->statements;
+ while (int tk = LA()) {
+ if (tk == T_RBRACE)
+ break;
+
+ unsigned start_statement = cursor();
+ if (! parseStatement(*statement_ptr)) {
+ rewind(start_statement + 1);
+ skipUntilStatement();
+ } else {
+ statement_ptr = &(*statement_ptr)->next;
+ }
+ }
+ match(T_RBRACE, &ast->rbrace_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+ if (LA() == T_IF) {
+ IfStatementAST *ast = new (_pool) IfStatementAST;
+ ast->if_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ parseCondition(ast->condition);
+ match(T_RPAREN, &ast->rparen_token);
+ if (! parseStatement(ast->statement))
+ _translationUnit->error(cursor(), "expected statement");
+ if (LA() == T_ELSE) {
+ ast->else_token = consumeToken();
+ if (! parseStatement(ast->else_statement))
+ _translationUnit->error(cursor(), "expected statement");
+ }
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+ if (LA() == T_SWITCH) {
+ SwitchStatementAST *ast = new (_pool) SwitchStatementAST;
+ ast->switch_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ parseCondition(ast->condition);
+ match(T_RPAREN, &ast->rparen_token);
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+ switch (LA()) {
+ case T_IDENTIFIER:
+ if (LA(2) == T_COLON) {
+ LabeledStatementAST *ast = new (_pool) LabeledStatementAST;
+ ast->label_token = consumeToken();
+ ast->colon_token = consumeToken();
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+ break;
+
+ case T_DEFAULT: {
+ LabeledStatementAST *ast = new (_pool) LabeledStatementAST;
+ ast->label_token = consumeToken();
+ match(T_COLON, &ast->colon_token);
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+
+ case T_CASE: {
+ CaseStatementAST *ast = new (_pool) CaseStatementAST;
+ ast->case_token = consumeToken();
+ parseConstantExpression(ast->expression);
+ match(T_COLON, &ast->colon_token);
+ parseStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+
+ default:
+ break;
+ } // switch
+ return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+ switch (LA()) {
+ case T_USING:
+ return parseUsing(node);
+
+ case T_ASM:
+ return parseAsmDefinition(node);
+
+ case T_NAMESPACE:
+ return parseNamespaceAliasDefinition(node);
+
+ default:
+ return parseSimpleDeclaration(node);
+ } // switch
+
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
+{
+ if (LA() == T_NAMESPACE && LA(2) == T_IDENTIFIER && LA(3) == T_EQUAL) {
+ NamespaceAliasDefinitionAST *ast = new (_pool) NamespaceAliasDefinitionAST;
+ ast->namespace_token = consumeToken();
+ ast->namespace_name = consumeToken();
+ ast->equal_token = consumeToken();
+ parseName(ast->name);
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+ DeclarationAST *declaration = 0;
+ if (! parseBlockDeclaration(declaration))
+ return false;
+
+ DeclarationStatementAST *ast = new (_pool) DeclarationStatementAST;
+ ast->declaration = declaration;
+ node = ast;
+ return true;
+}
+
+bool Parser::lookAtCVQualifier() const
+{
+ switch (LA()) {
+ case T_CONST:
+ case T_VOLATILE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::lookAtFunctionSpecifier() const
+{
+ switch (LA()) {
+ case T_INLINE:
+ case T_VIRTUAL:
+ case T_EXPLICIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::lookAtStorageClassSpecifier() const
+{
+ switch (LA()) {
+ case T_FRIEND:
+ case T_AUTO:
+ case T_REGISTER:
+ case T_STATIC:
+ case T_EXTERN:
+ case T_MUTABLE:
+ case T_TYPEDEF:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::lookAtBuiltinTypeSpecifier() const
+{
+ switch (LA()) {
+ case T_CHAR:
+ case T_WCHAR_T:
+ case T_BOOL:
+ case T_SHORT:
+ case T_INT:
+ case T_LONG:
+ case T_SIGNED:
+ case T_UNSIGNED:
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_VOID:
+ return true;
+ // [gcc] extensions
+ case T___TYPEOF__:
+ case T___ATTRIBUTE__:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::lookAtClassKey() const
+{
+ switch (LA()) {
+ case T_CLASS:
+ case T_STRUCT:
+ case T_UNION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Parser::parseAttributeSpecifier(SpecifierAST *&node)
+{
+ if (LA() != T___ATTRIBUTE__)
+ return false;
+
+ AttributeSpecifierAST *ast = new (_pool) AttributeSpecifierAST;
+ ast->attribute_token = consumeToken();
+ match(T_LPAREN, &ast->first_lparen_token);
+ match(T_LPAREN, &ast->second_lparen_token);
+ parseAttributeList(ast->attributes);
+ match(T_RPAREN, &ast->first_rparen_token);
+ match(T_RPAREN, &ast->second_rparen_token);
+ node = ast;
+ return true;
+}
+
+bool Parser::parseAttributeList(AttributeAST *&node)
+{
+ AttributeAST **attribute_ptr = &node;
+ while (LA() == T_IDENTIFIER || LA() == T_CONST) {
+ AttributeAST *ast = new (_pool) AttributeAST;
+ ast->identifier_token = consumeToken();
+ if (LA() == T_LPAREN) {
+ consumeToken();
+ if (LA() == T_IDENTIFIER && (LA(2) == T_COMMA || LA(2) == T_RPAREN)) {
+ ast->tag_token = consumeToken();
+ if (LA() == T_COMMA) {
+ consumeToken();
+ parseExpressionList(ast->expression_list);
+ }
+ } else {
+ parseExpressionList(ast->expression_list);
+ }
+ unsigned rparen_token = 0;
+ match(T_RPAREN, &rparen_token);
+ }
+ *attribute_ptr = ast;
+
+ if (LA() != T_COMMA)
+ break;
+
+ consumeToken();
+ attribute_ptr = &(*attribute_ptr)->next;
+ }
+ return true;
+}
+
+bool Parser::parseBuiltinTypeSpecifier(SpecifierAST *&node)
+{
+ if (LA() == T___ATTRIBUTE__) {
+ return parseAttributeSpecifier(node);
+ } else if (LA() == T___TYPEOF__) {
+ TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST;
+ ast->typeof_token = consumeToken();
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ if (parseTypeId(ast->expression) && LA() == T_RPAREN) {
+ consumeToken();
+ node = ast;
+ return true;
+ }
+ rewind(lparen_token);
+ }
+ parseUnaryExpression(ast->expression);
+ node = ast;
+ return true;
+ } else if (lookAtBuiltinTypeSpecifier()) {
+ SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST;
+ ast->specifier_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
+ bool acceptStructDeclarator)
+{
+ // parse a simple declaration, a function definition,
+ // or a contructor declaration.
+ cursor();
+
+ bool has_type_specifier = false;
+ bool has_complex_type_specifier = false;
+ unsigned startOfNamedTypeSpecifier = 0;
+ NameAST *named_type_specifier = 0;
+ SpecifierAST *decl_specifier_seq = 0,
+ **decl_specifier_seq_ptr = &decl_specifier_seq;
+ for (;;) {
+ if (lookAtCVQualifier() || lookAtFunctionSpecifier()
+ || lookAtStorageClassSpecifier()) {
+ SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
+ spec->specifier_token = consumeToken();
+ *decl_specifier_seq_ptr = spec;
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ } else if (LA() == T___ATTRIBUTE__) {
+ parseAttributeSpecifier(*decl_specifier_seq_ptr);
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ } else if (! named_type_specifier && ! has_complex_type_specifier && lookAtBuiltinTypeSpecifier()) {
+ parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else if (! has_type_specifier && (LA() == T_COLON_COLON ||
+ LA() == T_IDENTIFIER)) {
+ startOfNamedTypeSpecifier = cursor();
+ if (parseName(named_type_specifier)) {
+ NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
+ spec->name = named_type_specifier;
+ *decl_specifier_seq_ptr = spec;
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else {
+ rewind(startOfNamedTypeSpecifier);
+ break;
+ }
+ } else if (! has_type_specifier && LA() == T_ENUM) {
+ unsigned startOfTypeSpecifier = cursor();
+ if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) || LA() == T_LBRACE) {
+ rewind(startOfTypeSpecifier);
+ if (! parseEnumSpecifier(*decl_specifier_seq_ptr)) {
+ _translationUnit->error(startOfTypeSpecifier,
+ "expected an enum specifier");
+ break;
+ }
+ has_complex_type_specifier = true;
+ }
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else if (! has_type_specifier && LA() == T_TYPENAME) {
+ unsigned startOfElaboratedTypeSpecifier = cursor();
+ if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
+ _translationUnit->error(startOfElaboratedTypeSpecifier,
+ "expected an elaborated type specifier");
+ break;
+ }
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else if (! has_type_specifier && lookAtClassKey()) {
+ unsigned startOfTypeSpecifier = cursor();
+ if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) ||
+ (LA() == T_COLON || LA() == T_LBRACE || (LA(0) == T_IDENTIFIER && LA(1) == T_IDENTIFIER &&
+ (LA(2) == T_COLON || LA(2) == T_LBRACE)))) {
+ rewind(startOfTypeSpecifier);
+ if (! parseClassSpecifier(*decl_specifier_seq_ptr)) {
+ _translationUnit->error(startOfTypeSpecifier,
+ "wrong type specifier");
+ break;
+ }
+ has_complex_type_specifier = true;
+ }
+ decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
+ has_type_specifier = true;
+ } else
+ break;
+ }
+
+ DeclaratorListAST *declarator_list = 0,
+ **declarator_ptr = &declarator_list;
+
+ const bool maybeCtor = (LA() == T_LPAREN && named_type_specifier);
+ DeclaratorAST *declarator = 0;
+ if (! parseInitDeclarator(declarator, acceptStructDeclarator) && maybeCtor) {
+ rewind(startOfNamedTypeSpecifier);
+ named_type_specifier = 0;
+ // pop the named type specifier from the decl-specifier-seq
+ SpecifierAST **spec_ptr = &decl_specifier_seq;
+ for (; *spec_ptr; spec_ptr = &(*spec_ptr)->next) {
+ if (! (*spec_ptr)->next) {
+ *spec_ptr = 0;
+ break;
+ }
+ }
+ if (! parseInitDeclarator(declarator, acceptStructDeclarator))
+ return false;
+ }
+
+ DeclaratorAST *firstDeclarator = declarator;
+
+ if (declarator) {
+ *declarator_ptr = new (_pool) DeclaratorListAST;
+ (*declarator_ptr)->declarator = declarator;
+ declarator_ptr = &(*declarator_ptr)->next;
+ }
+
+ if (LA() == T_COMMA || LA() == T_SEMICOLON || has_complex_type_specifier) {
+ while (LA() == T_COMMA) {
+ consumeToken();
+ declarator = 0;
+ if (parseInitDeclarator(declarator, acceptStructDeclarator)) {
+ *declarator_ptr = new (_pool) DeclaratorListAST;
+ (*declarator_ptr)->declarator = declarator;
+ declarator_ptr = &(*declarator_ptr)->next;
+ }
+ }
+ SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST;
+ ast->decl_specifier_seq = decl_specifier_seq;
+ ast->declarators = declarator_list;
+ match(T_SEMICOLON, &ast->semicolon_token);
+ node = ast;
+ return true;
+ } else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) {
+ CtorInitializerAST *ctor_initializer = 0;
+ if (LA() == T_COLON)
+ parseCtorInitializer(ctor_initializer);
+
+ if (LA() == T_LBRACE) {
+ FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
+ ast->decl_specifier_seq = decl_specifier_seq;
+ ast->declarator = firstDeclarator;
+ ast->ctor_initializer = ctor_initializer;
+ parseFunctionBody(ast->function_body);
+ node = ast;
+ return true; // recognized a function definition.
+ } else if (LA() == T_TRY) {
+ FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
+ ast->decl_specifier_seq = decl_specifier_seq;
+ ast->declarator = firstDeclarator;
+ ast->ctor_initializer = ctor_initializer;
+ parseTryBlockStatement(ast->function_body);
+ node = ast;
+ return true; // recognized a function definition.
+ }
+ }
+
+ _translationUnit->error(cursor(), "unexpected token `%s'", tok().spell());
+ return false;
+}
+
+bool Parser::parseFunctionBody(StatementAST *&node)
+{
+ if (_translationUnit->skipFunctionBody()) {
+ unsigned token_lbrace = 0;
+ match(T_LBRACE, &token_lbrace);
+ if (! token_lbrace)
+ return false;
+
+ const Token &tk = _translationUnit->tokenAt(token_lbrace);
+ if (tk.close_brace)
+ rewind(tk.close_brace);
+ unsigned token_rbrace = 0;
+ match(T_RBRACE, &token_rbrace);
+ return true;
+ }
+
+ _inFunctionBody = true;
+ const bool parsed = parseCompoundStatement(node);
+ _inFunctionBody = false;
+ return parsed;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+ if (LA() == T_TRY) {
+ TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST;
+ ast->try_token = consumeToken();
+ parseCompoundStatement(ast->statement);
+ CatchClauseAST **catch_clause_ptr = &ast->catch_clause_seq;
+ while (parseCatchClause(*catch_clause_ptr))
+ catch_clause_ptr = &(*catch_clause_ptr)->next;
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseCatchClause(CatchClauseAST *&node)
+{
+ if (LA() == T_CATCH) {
+ CatchClauseAST *ast = new (_pool) CatchClauseAST;
+ ast->catch_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ parseExceptionDeclaration(ast->exception_declaration);
+ match(T_RPAREN, &ast->rparen_token);
+ parseCompoundStatement(ast->statement);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseExceptionDeclaration(ExceptionDeclarationAST *&node)
+{
+ if (LA() == T_DOT_DOT_DOT) {
+ ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST;
+ ast->dot_dot_dot_token = consumeToken();
+ node = ast;
+ return true;
+ }
+
+ SpecifierAST *type_specifier = 0;
+ if (parseTypeSpecifier(type_specifier)) {
+ ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST;
+ ast->type_specifier = type_specifier;
+ parseDeclaratorOrAbstractDeclarator(ast->declarator);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseBoolLiteral(ExpressionAST *&node)
+{
+ if (LA() == T_TRUE || LA() == T_FALSE) {
+ BoolLiteralAST *ast = new (_pool) BoolLiteralAST;
+ ast->token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseNumericLiteral(ExpressionAST *&node)
+{
+ if (LA() == T_INT_LITERAL || LA() == T_FLOAT_LITERAL || LA() == T_CHAR_LITERAL) {
+ NumericLiteralAST *ast = new (_pool) NumericLiteralAST;
+ ast->token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseThisExpression(ExpressionAST *&node)
+{
+ if (LA() == T_THIS) {
+ ThisExpressionAST *ast = new (_pool) ThisExpressionAST;
+ ast->this_token = consumeToken();
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parsePrimaryExpression(ExpressionAST *&node)
+{
+ switch (LA()) {
+ case T_STRING_LITERAL:
+ case T_WIDE_STRING_LITERAL:
+ return parseStringLiteral(node);
+
+ case T_INT_LITERAL:
+ case T_FLOAT_LITERAL:
+ case T_CHAR_LITERAL:
+ case T_WIDE_CHAR_LITERAL:
+ return parseNumericLiteral(node);
+
+ case T_TRUE:
+ case T_FALSE:
+ return parseBoolLiteral(node);
+
+ case T_THIS:
+ return parseThisExpression(node);
+
+ case T_LPAREN:
+ return parseNestedExpression(node);
+
+ case T_SIGNAL:
+ case T_SLOT:
+ return parseQtMethod(node);
+
+ default: {
+ NameAST *name = 0;
+ if (parseNameId(name)) {
+ node = name;
+ return true;
+ }
+ break;
+ } // default
+
+ } // switch
+
+ return false;
+}
+
+bool Parser::parseNameId(NameAST *&name)
+{
+ unsigned start = cursor();
+ if (! parseName(name))
+ return false;
+
+ if (LA() == T_IDENTIFIER ||
+ tok().isLiteral() ||
+ (tok().isOperator() && LA() != T_LPAREN && LA() != T_LBRACKET))
+ {
+ rewind(start);
+ return parseName(name, false);
+ }
+
+ return true;
+}
+
+bool Parser::parseNestedExpression(ExpressionAST *&node)
+{
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+
+ if (LA() == T_LBRACE) {
+ NestedExpressionAST *ast = new (_pool) NestedExpressionAST;
+ ast->lparen_token = lparen_token;
+
+ // ### ast
+ StatementAST *statement = 0;
+ parseCompoundStatement(statement);
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+
+ bool previousTemplateArguments = switchTemplateArguments(false);
+
+ ExpressionAST *expression = 0;
+ if (parseExpression(expression) && LA() == T_RPAREN) {
+ NestedExpressionAST *ast = new (_pool) NestedExpressionAST;
+ ast->lparen_token = lparen_token;
+ ast->expression = expression;
+ ast->rparen_token = consumeToken();
+ node = ast;
+ (void) switchTemplateArguments(previousTemplateArguments);
+ return true;
+ }
+ (void) switchTemplateArguments(previousTemplateArguments);
+ }
+ return false;
+}
+
+bool Parser::parseCppCastExpression(ExpressionAST *&node)
+{
+ if (LA() == T_DYNAMIC_CAST || LA() == T_STATIC_CAST ||
+ LA() == T_REINTERPRET_CAST || LA() == T_CONST_CAST) {
+ CppCastExpressionAST *ast = new (_pool) CppCastExpressionAST;
+ ast->cast_token = consumeToken();
+ match(T_LESS, &ast->less_token);
+ parseTypeId(ast->type_id);
+ match(T_GREATER, &ast->greater_token);
+ match(T_LPAREN, &ast->lparen_token);
+ parseExpression(ast->expression);
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+// typename ::opt nested-name-specifier identifier ( expression-listopt )
+// typename ::opt nested-name-specifier templateopt template-id ( expression-listopt )
+bool Parser::parseTypenameCallExpression(ExpressionAST *&node)
+{
+ if (LA() == T_TYPENAME) {
+ unsigned typename_token = consumeToken();
+ NameAST *name = 0;
+ if (parseName(name) && LA() == T_LPAREN) {
+ TypenameCallExpressionAST *ast = new (_pool) TypenameCallExpressionAST;
+ ast->typename_token = typename_token;
+ ast->name = name;
+ ast->lparen_token = consumeToken();
+ parseExpressionList(ast->expression_list);
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+ }
+ return false;
+}
+
+// typeid ( expression )
+// typeid ( type-id )
+bool Parser::parseTypeidExpression(ExpressionAST *&node)
+{
+ if (LA() == T_TYPEID) {
+ TypeidExpressionAST *ast = new (_pool) TypeidExpressionAST;
+ ast->typeid_token = consumeToken();
+ if (LA() == T_LPAREN)
+ ast->lparen_token = consumeToken();
+ unsigned saved = cursor();
+ if (! (parseTypeId(ast->expression) && LA() == T_RPAREN)) {
+ rewind(saved);
+ parseExpression(ast->expression);
+ }
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseCorePostfixExpression(ExpressionAST *&node)
+{
+ if (parseCppCastExpression(node))
+ return true;
+ else if (parseTypenameCallExpression(node))
+ return true;
+ else if (parseTypeidExpression(node))
+ return true;
+ else {
+ unsigned start = cursor();
+ SpecifierAST *type_specifier = 0;
+ bool blocked = blockErrors(true);
+ if (lookAtBuiltinTypeSpecifier() &&
+ parseSimpleTypeSpecifier(type_specifier) &&
+ LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ ExpressionListAST *expression_list = 0;
+ parseExpressionList(expression_list);
+ if (LA() == T_RPAREN) {
+ unsigned rparen_token = consumeToken();
+ TypeConstructorCallAST *ast = new (_pool) TypeConstructorCallAST;
+ ast->type_specifier = type_specifier;
+ ast->lparen_token = lparen_token;
+ ast->expression_list = expression_list;
+ ast->rparen_token = rparen_token;
+ node = ast;
+ blockErrors(blocked);
+ return true;
+ }
+ }
+ rewind(start);
+
+ // look for compound literals
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ ExpressionAST *type_id = 0;
+ if (parseTypeId(type_id) && LA() == T_RPAREN) {
+ unsigned rparen_token = consumeToken();
+ if (LA() == T_LBRACE) {
+ blockErrors(blocked);
+
+ CompoundLiteralAST *ast = new (_pool) CompoundLiteralAST;
+ ast->lparen_token = lparen_token;
+ ast->type_id = type_id;
+ ast->rparen_token = rparen_token;
+ parseInitializerClause(ast->initializer);
+ node = ast;
+ return true;
+ }
+ }
+ rewind(start);
+ }
+
+ blockErrors(blocked);
+ return parsePrimaryExpression(node);
+ }
+}
+
+bool Parser::parsePostfixExpression(ExpressionAST *&node)
+{
+ if (parseCorePostfixExpression(node)) {
+ PostfixAST *postfix_expressions = 0,
+ **postfix_ptr = &postfix_expressions;
+ while (LA()) {
+ if (LA() == T_LPAREN) {
+ CallAST *ast = new (_pool) CallAST;
+ ast->lparen_token = consumeToken();
+ parseExpressionList(ast->expression_list);
+ match(T_RPAREN, &ast->rparen_token);
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else if (LA() == T_LBRACKET) {
+ ArrayAccessAST *ast = new (_pool) ArrayAccessAST;
+ ast->lbracket_token = consumeToken();
+ parseExpression(ast->expression);
+ match(T_RBRACKET, &ast->rbracket_token);
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else if (LA() == T_PLUS_PLUS || LA() == T_MINUS_MINUS) {
+ PostIncrDecrAST *ast = new (_pool) PostIncrDecrAST;
+ ast->incr_decr_token = consumeToken();
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else if (LA() == T_DOT || LA() == T_ARROW) {
+ MemberAccessAST *ast = new (_pool) MemberAccessAST;
+ ast->access_token = consumeToken();
+ if (LA() == T_TEMPLATE)
+ ast->template_token = consumeToken();
+ if (! parseNameId(ast->member_name))
+ _translationUnit->error(cursor(), "expected unqualified-id before token `%s'",
+ tok().spell());
+ *postfix_ptr = ast;
+ postfix_ptr = &(*postfix_ptr)->next;
+ } else break;
+ } // while
+
+ if (postfix_expressions) {
+ PostfixExpressionAST *ast = new (_pool) PostfixExpressionAST;
+ ast->base_expression = node;
+ ast->postfix_expressions = postfix_expressions;
+ node = ast;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseUnaryExpression(ExpressionAST *&node)
+{
+ switch (LA()) {
+ case T_PLUS_PLUS:
+ case T_MINUS_MINUS:
+ case T_STAR:
+ case T_AMPER:
+ case T_PLUS:
+ case T_MINUS:
+ case T_EXCLAIM: {
+ UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST;
+ ast->unary_op_token = consumeToken();
+ parseCastExpression(ast->expression);
+ node = ast;
+ return true;
+ }
+
+ case T_TILDE: {
+ if (LA(2) == T_IDENTIFIER && LA(3) == T_LPAREN)
+ break; // prefer destructor names
+
+ UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST;
+ ast->unary_op_token = consumeToken();
+ parseCastExpression(ast->expression);
+ node = ast;
+ return true;
+ }
+
+ case T_SIZEOF: {
+ SizeofExpressionAST *ast = new (_pool) SizeofExpressionAST;
+ ast->sizeof_token = consumeToken();
+
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ if (parseTypeId(ast->expression) && LA() == T_RPAREN) {
+ consumeToken();
+ node = ast;
+ return true;
+ } else {
+ rewind(lparen_token);
+ }
+ }
+
+ parseUnaryExpression(ast->expression);
+ node = ast;
+ return true;
+ }
+
+ default:
+ break;
+ } // switch
+
+ if (LA() == T_NEW || (LA(1) == T_COLON_COLON &&
+ LA(2) == T_NEW))
+ return parseNewExpression(node);
+ else if (LA() == T_DELETE || (LA(1) == T_COLON_COLON &&
+ LA(2) == T_DELETE))
+ return parseDeleteExpression(node);
+ else
+ return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(ExpressionAST *&node)
+{
+ if (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW)) {
+ NewExpressionAST *ast = new (_pool) NewExpressionAST;
+
+ if (LA() == T_COLON_COLON)
+ ast->scope_token = consumeToken();
+
+ ast->new_token = consumeToken();
+
+ if (LA() == T_LPAREN) {
+ consumeToken();
+ parseExpression(ast->expression);
+ if (LA() == T_RPAREN)
+ consumeToken();
+ }
+
+ if (LA() == T_LPAREN) {
+ consumeToken();
+ parseTypeId(ast->type_id);
+ if (LA() == T_RPAREN)
+ consumeToken();
+ } else {
+ parseNewTypeId(ast->new_type_id);
+ }
+
+ parseNewInitializer(ast->new_initializer);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseNewTypeId(NewTypeIdAST *&node)
+{
+ SpecifierAST *typeSpec = 0;
+ if (! parseTypeSpecifier(typeSpec))
+ return false;
+
+ NewTypeIdAST *ast = new (_pool) NewTypeIdAST;
+ ast->type_specifier = typeSpec;
+ parseNewDeclarator(ast->new_declarator);
+ node = ast;
+ return true;
+}
+
+bool Parser::parseNewDeclarator(NewDeclaratorAST *&node)
+{
+ NewDeclaratorAST *ast = new (_pool) NewDeclaratorAST;
+
+ PtrOperatorAST **ptr_operators_tail = &ast->ptr_operators;
+ while (parsePtrOperator(*ptr_operators_tail))
+ ptr_operators_tail = &(*ptr_operators_tail)->next;
+
+ while (LA() == T_LBRACKET) { // ### create the AST
+ consumeToken();
+ ExpressionAST *expression = 0;
+ parseExpression(expression);
+ unsigned rbracket_token = 0;
+ match(T_RBRACKET, &rbracket_token);
+ }
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseNewInitializer(NewInitializerAST *&node)
+{
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ ExpressionAST *expression = 0;
+ if (LA() == T_RPAREN || parseExpression(expression)) {
+ NewInitializerAST *ast = new (_pool) NewInitializerAST;
+ ast->lparen_token = lparen_token;
+ ast->expression = expression;
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::parseDeleteExpression(ExpressionAST *&node)
+{
+ if (LA() == T_DELETE || (LA() == T_COLON_COLON && LA(2) == T_DELETE)) {
+ DeleteExpressionAST *ast = new (_pool) DeleteExpressionAST;
+
+ if (LA() == T_COLON_COLON)
+ ast->scope_token = consumeToken();
+
+ ast->delete_token = consumeToken();
+
+ if (LA() == T_LBRACKET) {
+ ast->lbracket_token = consumeToken();
+ match(T_RBRACKET, &ast->rbracket_token);
+ }
+
+ parseCastExpression(ast->expression);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseCastExpression(ExpressionAST *&node)
+{
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = consumeToken();
+ ExpressionAST *type_id = 0;
+ if (parseTypeId(type_id) && LA() == T_RPAREN) {
+ unsigned rparen_token = consumeToken();
+ ExpressionAST *expression = 0;
+ if (parseCastExpression(expression)) {
+ CastExpressionAST *ast = new (_pool) CastExpressionAST;
+ ast->lparen_token = lparen_token;
+ ast->type_id = type_id;
+ ast->rparen_token = rparen_token;
+ ast->expression = expression;
+ node = ast;
+ return true;
+ }
+ }
+ rewind(lparen_token);
+ }
+ return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(ExpressionAST *&node)
+{
+ if (! parseCastExpression(node))
+ return false;
+
+ while (LA() == T_ARROW_STAR || LA() == T_DOT_STAR) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseCastExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
+{
+ if (! parsePmExpression(node))
+ return false;
+
+ while (LA() == T_STAR || LA() == T_SLASH || LA() == T_PERCENT) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parsePmExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseAdditiveExpression(ExpressionAST *&node)
+{
+ if (! parseMultiplicativeExpression(node))
+ return false;
+
+ while (LA() == T_PLUS || LA() == T_MINUS) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseMultiplicativeExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseShiftExpression(ExpressionAST *&node)
+{
+ if (! parseAdditiveExpression(node))
+ return false;
+
+ while (LA() == T_LESS_LESS || LA() == T_GREATER_GREATER) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseAdditiveExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseRelationalExpression(ExpressionAST *&node)
+{
+ if (! parseShiftExpression(node))
+ return false;
+
+ while (LA() == T_LESS || (LA() == T_GREATER && ! _templateArguments) ||
+ LA() == T_LESS_EQUAL || LA() == T_GREATER_EQUAL) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseShiftExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseEqualityExpression(ExpressionAST *&node)
+{
+ if (! parseRelationalExpression(node))
+ return false;
+
+ while (LA() == T_EQUAL_EQUAL || LA() == T_EXCLAIM_EQUAL) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseRelationalExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseAndExpression(ExpressionAST *&node)
+{
+ if (! parseEqualityExpression(node))
+ return false;
+
+ while (LA() == T_AMPER) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseEqualityExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression(ExpressionAST *&node)
+{
+ if (! parseAndExpression(node))
+ return false;
+
+ while (LA() == T_CARET) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseAndExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression(ExpressionAST *&node)
+{
+ if (! parseExclusiveOrExpression(node))
+ return false;
+
+ while (LA() == T_PIPE) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseExclusiveOrExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression(ExpressionAST *&node)
+{
+ if (! parseInclusiveOrExpression(node))
+ return false;
+
+ while (LA() == T_AMPER_AMPER) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseInclusiveOrExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression(ExpressionAST *&node)
+{
+ if (! parseLogicalAndExpression(node))
+ return false;
+
+ while (LA() == T_PIPE_PIPE) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseLogicalAndExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseConditionalExpression(ExpressionAST *&node)
+{
+ if (! parseLogicalOrExpression(node))
+ return false;
+
+ if (LA() != T_QUESTION)
+ return true;
+
+ ConditionalExpressionAST *ast = new (_pool) ConditionalExpressionAST;
+ ast->condition = node;
+ ast->question_token = consumeToken();
+ parseAssignmentExpression(ast->left_expression);
+ match(T_COLON, &ast->colon_token);
+ parseAssignmentExpression(ast->right_expression);
+ node = ast;
+ return true;
+}
+
+bool Parser::lookAtAssignmentOperator() const
+{
+ switch (LA()) {
+ case T_EQUAL:
+ case T_AMPER_EQUAL:
+ case T_CARET_EQUAL:
+ case T_SLASH_EQUAL:
+ case T_GREATER_GREATER_EQUAL:
+ case T_LESS_LESS_EQUAL:
+ case T_MINUS_EQUAL:
+ case T_PERCENT_EQUAL:
+ case T_PIPE_EQUAL:
+ case T_PLUS_EQUAL:
+ case T_STAR_EQUAL:
+ case T_TILDE_EQUAL:
+ return true;
+ default:
+ return false;
+ } // switch
+}
+
+bool Parser::parseAssignmentExpression(ExpressionAST *&node)
+{
+ if (LA() == T_THROW)
+ return parseThrowExpression(node);
+ else if (! parseConditionalExpression(node))
+ return false;
+
+ if (lookAtAssignmentOperator()) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseAssignmentExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseQtMethod(ExpressionAST *&node)
+{
+ if (LA() == T_SIGNAL || LA() == T_SLOT) {
+ QtMethodAST *ast = new (_pool) QtMethodAST;
+ ast->method_token = consumeToken();
+ match(T_LPAREN, &ast->lparen_token);
+ if (! parseDeclarator(ast->declarator))
+ _translationUnit->error(cursor(), "expected a function declarator before token `%s'",
+ tok().spell());
+ match(T_RPAREN, &ast->rparen_token);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseConstantExpression(ExpressionAST *&node)
+{
+ return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(ExpressionAST *&node)
+{
+ return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(ExpressionAST *&node)
+{
+ if (! parseAssignmentExpression(node))
+ return false;
+
+ while (LA() == T_COMMA) {
+ unsigned op = consumeToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (! parseAssignmentExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = new (_pool) BinaryExpressionAST;
+ ast->binary_op_token = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+ node = ast;
+ }
+ return true;
+}
+
+bool Parser::parseThrowExpression(ExpressionAST *&node)
+{
+ if (LA() == T_THROW) {
+ ThrowExpressionAST *ast = new (_pool) ThrowExpressionAST;
+ ast->throw_token = consumeToken();
+ parseAssignmentExpression(ast->expression);
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::lookAtObjCSelector() const
+{
+ switch (LA()) {
+ case T_IDENTIFIER:
+ case T_OR:
+ case T_AND:
+ case T_NOT:
+ case T_XOR:
+ case T_BITOR:
+ case T_COMPL:
+ case T_OR_EQ:
+ case T_AND_EQ:
+ case T_BITAND:
+ case T_NOT_EQ:
+ case T_XOR_EQ:
+ return true;
+
+ default:
+ if (tok().isKeyword())
+ return true;
+ } // switch
+
+ return false;
+}
+
+// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
+//
+bool Parser::parseObjCClassDeclaration(DeclarationAST *&)
+{
+ if (LA() != T_AT_CLASS)
+ return false;
+
+ /*unsigned objc_class_token = */ consumeToken();
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+ while (LA() == T_COMMA) {
+ consumeToken(); // skip T_COMMA
+ match(T_IDENTIFIER, &identifier_token);
+ }
+
+ unsigned semicolon_token = 0;
+ match(T_SEMICOLON, &semicolon_token);
+ return true;
+}
+
+// objc-interface ::= attribute-specifier-list-opt objc-class-interface
+// objc-interface ::= objc-category-interface
+//
+// objc-class-interface ::= T_AT_INTERFACE T_IDENTIFIER (T_COLON T_IDENTIFIER)?
+// objc-protocol-refs-opt
+// objc-class-instance-variables-opt
+// objc-interface-declaration-list
+// T_AT_END
+//
+// objc-category-interface ::= T_AT_INTERFACE T_IDENTIFIER
+// T_LPAREN T_IDENTIFIER? T_RPAREN
+// objc-protocol-refs-opt
+// objc-interface-declaration-list
+// T_AT_END
+//
+bool Parser::parseObjCInterface(DeclarationAST *&,
+ SpecifierAST *attributes)
+{
+ if (! attributes && LA() == T___ATTRIBUTE__) {
+ SpecifierAST **attr = &attributes;
+ while (parseAttributeSpecifier(*attr))
+ attr = &(*attr)->next;
+ }
+
+ if (LA() != T_AT_INTERFACE)
+ return false;
+
+ /*unsigned objc_interface_token = */ consumeToken();
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+
+ if (LA() == T_LPAREN) {
+ // a category interface
+
+ if (attributes)
+ _translationUnit->error(attributes->firstToken(),
+ "invalid attributes for category interface declaration");
+
+ unsigned lparen_token = 0, rparen_token = 0;
+ match(T_LPAREN, &lparen_token);
+ if (LA() == T_IDENTIFIER)
+ consumeToken();
+
+ match(T_RPAREN, &rparen_token);
+
+ parseObjCProtocolRefs();
+ while (parseObjCInterfaceMemberDeclaration()) {
+ }
+ unsigned objc_end_token = 0;
+ match(T_AT_END, &objc_end_token);
+ return true;
+ }
+
+ // a class interface declaration
+ if (LA() == T_COLON) {
+ consumeToken();
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+ }
+
+ parseObjCProtocolRefs();
+ parseObjClassInstanceVariables();
+ while (parseObjCInterfaceMemberDeclaration()) {
+ }
+ unsigned objc_end_token = 0;
+ match(T_AT_END, &objc_end_token);
+ return true;
+}
+
+// objc-protocol ::= T_AT_PROTOCOL (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
+//
+bool Parser::parseObjCProtocol(DeclarationAST *&,
+ SpecifierAST *attributes)
+{
+ if (! attributes && LA() == T___ATTRIBUTE__) {
+ SpecifierAST **attr = &attributes;
+ while (parseAttributeSpecifier(*attr))
+ attr = &(*attr)->next;
+ }
+
+ if (LA() != T_AT_PROTOCOL)
+ return false;
+
+ /*unsigned objc_protocol_token = */ consumeToken();
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+
+ if (LA() == T_COMMA || LA() == T_SEMICOLON) {
+ // a protocol forward declaration
+
+ while (LA() == T_COMMA) {
+ consumeToken();
+ match(T_IDENTIFIER, &identifier_token);
+ }
+ unsigned semicolon_token = 0;
+ match(T_SEMICOLON, &semicolon_token);
+ return true;
+ }
+
+ // a protocol definition
+ parseObjCProtocolRefs();
+
+ while (parseObjCInterfaceMemberDeclaration()) {
+ }
+
+ unsigned objc_end_token = 0;
+ match(T_AT_END, &objc_end_token);
+
+ return true;
+}
+
+// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER (T_COLON T_IDENTIFIER)?
+// objc-class-instance-variables-opt
+// objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER T_LPAREN T_IDENTIFIER T_RPAREN
+//
+bool Parser::parseObjCImplementation(DeclarationAST *&)
+{
+ if (LA() != T_AT_IMPLEMENTATION)
+ return false;
+
+ consumeToken();
+
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+
+ if (LA() == T_LPAREN) {
+ // a category implementation
+ unsigned lparen_token = 0, rparen_token = 0;
+ unsigned category_name_token = 0;
+ match(T_LPAREN, &lparen_token);
+ match(T_IDENTIFIER, &category_name_token);
+ match(T_RPAREN, &rparen_token);
+ return true;
+ }
+
+ // a class implementation
+ if (LA() == T_COLON) {
+ consumeToken();
+ unsigned super_class_name_token = 0;
+ match(T_IDENTIFIER, &super_class_name_token);
+ }
+
+ parseObjClassInstanceVariables();
+ return true;
+}
+
+// objc-protocol-refs ::= T_LESS (T_IDENTIFIER @ T_COMMA) T_GREATER
+//
+bool Parser::parseObjCProtocolRefs()
+{
+ if (LA() != T_LESS)
+ return false;
+ unsigned less_token = 0, greater_token = 0;
+ unsigned identifier_token = 0;
+ match(T_LESS, &less_token);
+ match(T_IDENTIFIER, &identifier_token);
+ while (LA() == T_COMMA) {
+ consumeToken();
+ match(T_IDENTIFIER, &identifier_token);
+ }
+ match(T_GREATER, &greater_token);
+ return true;
+}
+
+// objc-class-instance-variables ::= T_LBRACE
+// objc-instance-variable-decl-list-opt
+// T_RBRACE
+//
+bool Parser::parseObjClassInstanceVariables()
+{
+ if (LA() != T_LBRACE)
+ return false;
+
+ unsigned lbrace_token = 0, rbrace_token = 0;
+
+ match(T_LBRACE, &lbrace_token);
+ while (LA()) {
+ if (LA() == T_RBRACE)
+ break;
+
+ const unsigned start = cursor();
+
+ DeclarationAST *declaration = 0;
+ parseObjCInstanceVariableDeclaration(declaration);
+
+ if (start == cursor()) {
+ // skip stray token.
+ _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell());
+ consumeToken();
+ }
+ }
+
+ match(T_RBRACE, &rbrace_token);
+ return true;
+}
+
+// objc-interface-declaration ::= T_AT_REQUIRED
+// objc-interface-declaration ::= T_AT_OPTIONAL
+// objc-interface-declaration ::= T_SEMICOLON
+// objc-interface-declaration ::= objc-property-declaration
+// objc-interface-declaration ::= objc-method-prototype
+bool Parser::parseObjCInterfaceMemberDeclaration()
+{
+ switch (LA()) {
+ case T_AT_END:
+ return false;
+
+ case T_AT_REQUIRED:
+ case T_AT_OPTIONAL:
+ consumeToken();
+ return true;
+
+ case T_SEMICOLON:
+ consumeToken();
+ return true;
+
+ case T_AT_PROPERTY: {
+ DeclarationAST *declaration = 0;
+ return parseObjCPropertyDeclaration(declaration);
+ }
+
+ case T_PLUS:
+ case T_MINUS:
+ return parseObjCMethodPrototype();
+
+ case T_ENUM:
+ case T_CLASS:
+ case T_STRUCT:
+ case T_UNION: {
+ DeclarationAST *declaration = 0;
+ return parseSimpleDeclaration(declaration, /*accept struct declarators */ true);
+ }
+
+ default: {
+ DeclarationAST *declaration = 0;
+ return parseSimpleDeclaration(declaration, /*accept struct declarators */ true);
+ } // default
+
+ } // switch
+}
+
+// objc-instance-variable-declaration ::= objc-visibility-specifier
+// objc-instance-variable-declaration ::= block-declaration
+//
+bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node)
+{
+ switch (LA()) {
+ case T_AT_PRIVATE:
+ case T_AT_PROTECTED:
+ case T_AT_PUBLIC:
+ case T_AT_PACKAGE:
+ consumeToken();
+ return true;
+
+ default:
+ return parseSimpleDeclaration(node, true);
+ }
+}
+
+// objc-property-declaration ::=
+// T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration
+//
+bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&, SpecifierAST *)
+{
+ if (LA() != T_AT_PROPERTY)
+ return false;
+
+ /*unsigned objc_property_token = */ consumeToken();
+
+ if (LA() == T_LPAREN) {
+ unsigned lparen_token = 0, rparen_token = 0;
+ match(T_LPAREN, &lparen_token);
+ while (parseObjCPropertyAttribute()) {
+ }
+ match(T_RPAREN, &rparen_token);
+ }
+
+ DeclarationAST *simple_declaration = 0;
+ parseSimpleDeclaration(simple_declaration, /*accept-struct-declarators = */ true);
+ return true;
+}
+
+// objc-method-prototype ::= (T_PLUS | T_MINUS) objc-method-decl objc-method-attrs-opt
+//
+// objc-method-decl ::= objc-type-name? objc-selector
+// objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt
+//
+bool Parser::parseObjCMethodPrototype()
+{
+ if (LA() != T_PLUS && LA() != T_MINUS)
+ return false;
+
+ /*unsigned method_type_token = */ consumeToken();
+
+ parseObjCTypeName();
+
+ if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) {
+ while (parseObjCKeywordDeclaration()) {
+ }
+
+ while (LA() == T_COMMA) {
+ consumeToken();
+
+ if (LA() == T_DOT_DOT_DOT) {
+ consumeToken();
+ break;
+ }
+
+ DeclarationAST *parameter_declaration = 0;
+ parseParameterDeclaration(parameter_declaration);
+ }
+ } else if (lookAtObjCSelector()) {
+ parseObjCSelector();
+ } else {
+ _translationUnit->error(cursor(), "expected a selector");
+ }
+
+ SpecifierAST *attributes = 0, **attr = &attributes;
+ while (parseAttributeSpecifier(*attr))
+ attr = &(*attr)->next;
+
+ return true;
+}
+
+// objc-property-attribute ::= getter '=' identifier
+// objc-property-attribute ::= setter '=' identifier ':'
+// objc-property-attribute ::= readonly
+// objc-property-attribute ::= readwrite
+// objc-property-attribute ::= assign
+// objc-property-attribute ::= retain
+// objc-property-attribute ::= copy
+// objc-property-attribute ::= nonatomic
+bool Parser::parseObjCPropertyAttribute()
+{
+ if (LA() != T_IDENTIFIER)
+ return false;
+
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+ if (LA() == T_EQUAL) {
+ consumeToken();
+ match(T_IDENTIFIER, &identifier_token);
+ if (LA() == T_COLON)
+ consumeToken();
+ }
+
+ return true;
+}
+
+// objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN
+//
+bool Parser::parseObjCTypeName()
+{
+ if (LA() != T_LPAREN)
+ return false;
+
+ unsigned lparen_token = 0, rparen_token = 0;
+ match(T_LPAREN, &lparen_token);
+ parseObjCTypeQualifiers();
+ ExpressionAST *type_id = 0;
+ parseTypeId(type_id);
+ match(T_RPAREN, &rparen_token);
+ return true;
+}
+
+// objc-selector ::= T_IDENTIFIER | keyword
+//
+bool Parser::parseObjCSelector()
+{
+ if (! lookAtObjCSelector())
+ return false;
+
+ consumeToken();
+ return true;
+}
+
+// objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER
+//
+bool Parser::parseObjCKeywordDeclaration()
+{
+ if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON)))
+ return false;
+
+ parseObjCSelector();
+
+ unsigned colon_token = 0;
+ match(T_COLON, &colon_token);
+
+ parseObjCTypeName();
+
+ SpecifierAST *attributes = 0, **attr = &attributes;
+ while (parseAttributeSpecifier(*attr))
+ attr = &(*attr)->next;
+
+ unsigned identifier_token = 0;
+ match(T_IDENTIFIER, &identifier_token);
+
+ return true;
+}
+
+bool Parser::parseObjCTypeQualifiers()
+{
+ if (LA() != T_IDENTIFIER)
+ return false;
+
+ Identifier *id = tok().identifier;
+ if (! strcmp("in", id->chars()) ||
+ ! strcmp("out", id->chars()) ||
+ ! strcmp("inout", id->chars()) ||
+ ! strcmp("bycopy", id->chars()) ||
+ ! strcmp("byref", id->chars()) ||
+ ! strcmp("oneway", id->chars())) {
+ consumeToken();
+ return true;
+ }
+ return false;
+}
+
+// objc-end: T_AT_END
+bool Parser::parseObjCEnd(DeclarationAST *&)
+{
+ if (LA() != T_AT_END)
+ return false;
+
+ consumeToken();
+ return true;
+}
+
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
new file mode 100644
index 0000000000..d99d8d27fc
--- /dev/null
+++ b/src/shared/cplusplus/Parser.h
@@ -0,0 +1,292 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_PARSER_H
+#define CPLUSPLUS_PARSER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "Token.h"
+#include "TranslationUnit.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Parser
+{
+public:
+ Parser(TranslationUnit *translationUnit);
+ ~Parser();
+
+ bool qtMocRunEnabled() const;
+ void setQtMocRunEnabled(bool onoff);
+
+ bool objCEnabled() const;
+ void setObjCEnabled(bool onoff);
+
+ bool parseTranslationUnit(TranslationUnitAST *&node);
+
+public:
+ bool parseAccessSpecifier(SpecifierAST *&node);
+ bool parseExpressionList(ExpressionListAST *&node);
+ bool parseAbstractCoreDeclarator(DeclaratorAST *&node);
+ bool parseAbstractDeclarator(DeclaratorAST *&node);
+ bool parseEmptyDeclaration(DeclarationAST *&node);
+ bool parseAccessDeclaration(DeclarationAST *&node);
+ bool parseAdditiveExpression(ExpressionAST *&node);
+ bool parseAndExpression(ExpressionAST *&node);
+ bool parseAsmDefinition(DeclarationAST *&node);
+ bool parseAssignmentExpression(ExpressionAST *&node);
+ bool parseBaseClause(BaseSpecifierAST *&node);
+ bool parseBaseSpecifier(BaseSpecifierAST *&node);
+ bool parseBlockDeclaration(DeclarationAST *&node);
+ bool parseCppCastExpression(ExpressionAST *&node);
+ bool parseCastExpression(ExpressionAST *&node);
+ bool parseClassSpecifier(SpecifierAST *&node);
+ bool parseCommaExpression(ExpressionAST *&node);
+ bool parseCompoundStatement(StatementAST *&node);
+ bool parseBreakStatement(StatementAST *&node);
+ bool parseContinueStatement(StatementAST *&node);
+ bool parseGotoStatement(StatementAST *&node);
+ bool parseReturnStatement(StatementAST *&node);
+ bool parseCondition(ExpressionAST *&node);
+ bool parseConditionalExpression(ExpressionAST *&node);
+ bool parseConstantExpression(ExpressionAST *&node);
+ bool parseCtorInitializer(CtorInitializerAST *&node);
+ bool parseCvQualifiers(SpecifierAST *&node);
+ bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node);
+ bool parseDeclaration(DeclarationAST *&node);
+ bool parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator = false);
+ bool parseDeclarationStatement(StatementAST *&node);
+ bool parseCoreDeclarator(DeclaratorAST *&node);
+ bool parseDeclarator(DeclaratorAST *&node);
+ bool parseDeleteExpression(ExpressionAST *&node);
+ bool parseDoStatement(StatementAST *&node);
+ bool parseElaboratedTypeSpecifier(SpecifierAST *&node);
+ bool parseEnumSpecifier(SpecifierAST *&node);
+ bool parseEnumerator(EnumeratorAST *&node);
+ bool parseEqualityExpression(ExpressionAST *&node);
+ bool parseExceptionDeclaration(ExceptionDeclarationAST *&node);
+ bool parseExceptionSpecification(ExceptionSpecificationAST *&node);
+ bool parseExclusiveOrExpression(ExpressionAST *&node);
+ bool parseExpression(ExpressionAST *&node);
+ bool parseExpressionOrDeclarationStatement(StatementAST *&node);
+ bool parseExpressionStatement(StatementAST *&node);
+ bool parseForInitStatement(StatementAST *&node);
+ bool parseForStatement(StatementAST *&node);
+ bool parseFunctionBody(StatementAST *&node);
+ bool parseIfStatement(StatementAST *&node);
+ bool parseInclusiveOrExpression(ExpressionAST *&node);
+ bool parseInitDeclarator(DeclaratorAST *&node, bool acceptStructDeclarator);
+ bool parseInitializerList(ExpressionListAST *&node);
+ bool parseInitializer(ExpressionAST *&node);
+ bool parseInitializerClause(ExpressionAST *&node);
+ bool parseLabeledStatement(StatementAST *&node);
+ bool parseLinkageBody(DeclarationAST *&node);
+ bool parseLinkageSpecification(DeclarationAST *&node);
+ bool parseLogicalAndExpression(ExpressionAST *&node);
+ bool parseLogicalOrExpression(ExpressionAST *&node);
+ bool parseMemInitializer(MemInitializerAST *&node);
+ bool parseMemInitializerList(MemInitializerAST *&node);
+ bool parseMemberSpecification(DeclarationAST *&node);
+ bool parseMultiplicativeExpression(ExpressionAST *&node);
+ bool parseTemplateId(NameAST *&node);
+ bool parseClassOrNamespaceName(NameAST *&node);
+ bool parseNameId(NameAST *&node);
+ bool parseName(NameAST *&node, bool acceptTemplateId = true);
+ bool parseNestedNameSpecifier(NestedNameSpecifierAST *&node, bool acceptTemplateId);
+ bool parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name, bool acceptTemplateId);
+ bool parseNamespace(DeclarationAST *&node);
+ bool parseNamespaceAliasDefinition(DeclarationAST *&node);
+ bool parseNewDeclarator(NewDeclaratorAST *&node);
+ bool parseNewExpression(ExpressionAST *&node);
+ bool parseNewInitializer(NewInitializerAST *&node);
+ bool parseNewTypeId(NewTypeIdAST *&node);
+ bool parseOperator(OperatorAST *&node);
+ bool parseConversionFunctionId(NameAST *&node);
+ bool parseOperatorFunctionId(NameAST *&node);
+ bool parseParameterDeclaration(DeclarationAST *&node);
+ bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node);
+ bool parseParameterDeclarationList(DeclarationAST *&node);
+ bool parsePmExpression(ExpressionAST *&node);
+ bool parseTypeidExpression(ExpressionAST *&node);
+ bool parseTypenameCallExpression(ExpressionAST *&node);
+ bool parseCorePostfixExpression(ExpressionAST *&node);
+ bool parsePostfixExpression(ExpressionAST *&node);
+ bool parsePostfixExpressionInternal(ExpressionAST *&node);
+ bool parsePrimaryExpression(ExpressionAST *&node);
+ bool parseNestedExpression(ExpressionAST *&node);
+ bool parsePtrOperator(PtrOperatorAST *&node);
+ bool parseRelationalExpression(ExpressionAST *&node);
+ bool parseShiftExpression(ExpressionAST *&node);
+ bool parseStatement(StatementAST *&node);
+ bool parseThisExpression(ExpressionAST *&node);
+ bool parseBoolLiteral(ExpressionAST *&node);
+ bool parseNumericLiteral(ExpressionAST *&node);
+ bool parseStringLiteral(ExpressionAST *&node);
+ bool parseSwitchStatement(StatementAST *&node);
+ bool parseTemplateArgument(ExpressionAST *&node);
+ bool parseTemplateArgumentList(TemplateArgumentListAST *&node);
+ bool parseTemplateDeclaration(DeclarationAST *&node);
+ bool parseTemplateParameter(DeclarationAST *&node);
+ bool parseTemplateParameterList(DeclarationAST *&node);
+ bool parseThrowExpression(ExpressionAST *&node);
+ bool parseTryBlockStatement(StatementAST *&node);
+ bool parseCatchClause(CatchClauseAST *&node);
+ bool parseTypeId(ExpressionAST *&node);
+ bool parseTypeIdList(ExpressionListAST *&node);
+ bool parseTypenameTypeParameter(DeclarationAST *&node);
+ bool parseTemplateTypeParameter(DeclarationAST *&node);
+ bool parseTypeParameter(DeclarationAST *&node);
+
+ bool parseBuiltinTypeSpecifier(SpecifierAST *&node);
+ bool parseAttributeSpecifier(SpecifierAST *&node);
+ bool parseAttributeList(AttributeAST *&node);
+
+ bool parseSimpleTypeSpecifier(SpecifierAST *&node)
+ { return parseDeclSpecifierSeq(node, true, true); }
+
+ bool parseTypeSpecifier(SpecifierAST *&node)
+ { return parseDeclSpecifierSeq(node, true); }
+
+ bool parseDeclSpecifierSeq(SpecifierAST *&node,
+ bool onlyTypeSpecifiers = false,
+ bool simplified = false);
+ bool parseUnaryExpression(ExpressionAST *&node);
+ bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true);
+ bool parseUsing(DeclarationAST *&node);
+ bool parseUsingDirective(DeclarationAST *&node);
+ bool parseWhileStatement(StatementAST *&node);
+
+ // Qt MOC run
+ bool parseQtMethod(ExpressionAST *&node);
+
+ // ObjC++
+ bool parseObjCClassDeclaration(DeclarationAST *&node);
+ bool parseObjCInterface(DeclarationAST *&node,
+ SpecifierAST *attributes = 0);
+ bool parseObjCProtocol(DeclarationAST *&node,
+ SpecifierAST *attributes = 0);
+
+ bool parseObjCProtocolRefs();
+ bool parseObjClassInstanceVariables();
+ bool parseObjCInterfaceMemberDeclaration();
+ bool parseObjCInstanceVariableDeclaration(DeclarationAST *&node);
+ bool parseObjCPropertyDeclaration(DeclarationAST *&node,
+ SpecifierAST *attributes = 0);
+ bool parseObjCImplementation(DeclarationAST *&node);
+ bool parseObjCMethodPrototype();
+ bool parseObjCPropertyAttribute();
+ bool parseObjCTypeName();
+ bool parseObjCSelector();
+ bool parseObjCKeywordDeclaration();
+ bool parseObjCTypeQualifiers();
+ bool parseObjCEnd(DeclarationAST *&node);
+
+ bool lookAtObjCSelector() const;
+
+ bool skipUntil(int token);
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip(int l, int r);
+
+ bool lookAtCVQualifier() const;
+ bool lookAtFunctionSpecifier() const;
+ bool lookAtStorageClassSpecifier() const;
+ bool lookAtBuiltinTypeSpecifier() const;
+ bool lookAtClassKey() const;
+ bool lookAtAssignmentOperator() const;
+
+ void match(int kind, unsigned *token);
+
+ bool maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const;
+ bool maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const;
+
+private:
+ bool switchTemplateArguments(bool templateArguments);
+ bool blockErrors(bool block);
+
+ inline const Token &tok(int i = 1) const
+ { return _translationUnit->tokenAt(_tokenIndex + i - 1); }
+
+ inline int LA(int n = 1) const
+ { return _translationUnit->tokenKind(_tokenIndex + n - 1); }
+
+ inline int consumeToken()
+ { return _tokenIndex++; }
+
+ inline unsigned cursor() const
+ { return _tokenIndex; }
+
+ inline void rewind(unsigned cursor)
+ { _tokenIndex = cursor; }
+
+private:
+ TranslationUnit *_translationUnit;
+ Control *_control;
+ MemoryPool *_pool;
+ unsigned _tokenIndex;
+ bool _templateArguments: 1;
+ bool _qtMocRunEnabled: 1;
+ bool _objCEnabled: 1;
+ bool _inFunctionBody: 1;
+ bool _inObjCImplementationContext: 1;
+
+private:
+ Parser(const Parser& source);
+ void operator =(const Parser& source);
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_PARSER_H
diff --git a/src/shared/cplusplus/PrettyPrinter.cpp b/src/shared/cplusplus/PrettyPrinter.cpp
new file mode 100644
index 0000000000..6acb109dcf
--- /dev/null
+++ b/src/shared/cplusplus/PrettyPrinter.cpp
@@ -0,0 +1,1293 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "PrettyPrinter.h"
+#include "AST.h"
+#include "Token.h"
+#include <iostream>
+#include <string>
+#include <cassert>
+
+CPLUSPLUS_USE_NAMESPACE
+
+PrettyPrinter::PrettyPrinter(Control *control, std::ostream &out)
+ : ASTVisitor(control),
+ out(out),
+ depth(0)
+{ }
+
+void PrettyPrinter::operator()(AST *ast)
+{ accept(ast); }
+
+void PrettyPrinter::indent()
+{ ++depth; }
+
+void PrettyPrinter::deindent()
+{ --depth; }
+
+void PrettyPrinter::newline()
+{ out << '\n' << std::string(depth * 4, ' '); }
+
+bool PrettyPrinter::visit(AccessDeclarationAST *ast)
+{
+ deindent();
+ newline();
+ out << spell(ast->access_specifier_token);
+ if (ast->slots_token)
+ out << ' ' << spell(ast->slots_token);
+ out << ':' << std::endl;
+ indent();
+ return false;
+}
+
+bool PrettyPrinter::visit(ArrayAccessAST *ast)
+{
+ out << '[';
+ accept(ast->expression);
+ out << ']';
+ return false;
+}
+
+bool PrettyPrinter::visit(ArrayDeclaratorAST *ast)
+{
+ out << '[';
+ accept(ast->expression);
+ out << ']';
+ return false;
+}
+
+bool PrettyPrinter::visit(ArrayInitializerAST *ast)
+{
+ out << '{';
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ out << '}';
+ return false;
+}
+
+bool PrettyPrinter::visit(AsmDefinitionAST *ast)
+{
+ out << spell(ast->asm_token);
+ for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+ out << ' ';
+ accept(it);
+ }
+ out << '(';
+ out << "/* ### implement me */";
+ out << ");";
+ return false;
+}
+
+bool PrettyPrinter::visit(AttributeSpecifierAST *ast)
+{
+ out << "attribute((";
+ for (AttributeAST *it = ast->attributes; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ", ";
+ }
+ out << "))";
+ return false;
+}
+
+bool PrettyPrinter::visit(AttributeAST *ast)
+{
+ out << spell(ast->identifier_token);
+ if (ast->lparen_token) {
+ out << '(';
+ out << spell(ast->tag_token);
+ if (ast->expression_list) {
+ out << '(';
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ out << ')';
+ }
+ out << ')';
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(BaseSpecifierAST *ast)
+{
+ if (ast->token_virtual && ast->token_access_specifier) {
+ out << "virtual";
+ out << ' ';
+ out << spell(ast->token_access_specifier);
+ out << ' ';
+ } else if (ast->token_virtual) {
+ out << "virtual";
+ out << ' ';
+ } else if (ast->token_access_specifier) {
+ out << spell(ast->token_access_specifier);
+ out << ' ';
+ }
+ accept(ast->name);
+ return false;
+}
+
+bool PrettyPrinter::visit(BinaryExpressionAST *ast)
+{
+ accept(ast->left_expression);
+ out << ' ' << spell(ast->binary_op_token) << ' ';
+ accept(ast->right_expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(BoolLiteralAST *ast)
+{
+ out << spell(ast->token);
+ return false;
+}
+
+bool PrettyPrinter::visit(BreakStatementAST *)
+{
+ out << "break;";
+ return false;
+}
+
+bool PrettyPrinter::visit(CallAST *ast)
+{
+ out << '(';
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(CaseStatementAST *ast)
+{
+ out << "case ";
+ accept(ast->expression);
+ out << ':';
+ if (! ast->statement) {
+ newline();
+ return false;
+ }
+
+ if (ast->statement->asCompoundStatement()) {
+ out << ' ';
+ accept(ast->statement);
+ } else if (ast->statement->asCaseStatement() || ast->statement->asLabeledStatement()) {
+ newline();
+ accept(ast->statement);
+ } else {
+ indent();
+ newline();
+ accept(ast->statement);
+ deindent();
+ newline();
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(CastExpressionAST *ast)
+{
+ out << '(';
+ accept(ast->type_id);
+ out << ')';
+ accept(ast->expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(CatchClauseAST *ast)
+{
+ out << "catch";
+ out << '(';
+ accept(ast->exception_declaration);
+ out << ')';
+ accept(ast->statement);
+ return false;
+}
+
+bool PrettyPrinter::visit(ClassSpecifierAST *ast)
+{
+ out << spell(ast->classkey_token);
+ out << ' ';
+ if (ast->attributes) {
+ accept(ast->attributes);
+ out << ' ';
+ }
+ accept(ast->name);
+ if (ast->colon_token) {
+ out << ':';
+ out << ' ';
+ for (BaseSpecifierAST *it = ast->base_clause; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ", ";
+ }
+ }
+ newline();
+ out << '{';
+ if (ast->member_specifiers) {
+ indent();
+ newline();
+ if (ast->member_specifiers) {
+ for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ newline();
+ }
+ }
+ deindent();
+ newline();
+ }
+ out << '}';
+ return false;
+}
+
+bool PrettyPrinter::visit(CompoundStatementAST *ast)
+{
+ out << '{';
+ if (ast->statements) {
+ indent();
+ newline();
+ for (StatementAST *it = ast->statements; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ newline();
+ }
+ deindent();
+ newline();
+ }
+ out << '}';
+ return false;
+}
+
+bool PrettyPrinter::visit(ConditionAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarator) {
+ if (ast->type_specifier)
+ out << ' ';
+
+ accept(ast->declarator);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(ConditionalExpressionAST *ast)
+{
+ accept(ast->condition);
+ out << '?';
+ accept(ast->left_expression);
+ out << ':';
+ accept(ast->right_expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(ContinueStatementAST *)
+{
+ out << "continue";
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(ConversionFunctionIdAST *ast)
+{
+ out << "operator";
+ out << ' ';
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) {
+ accept(it);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(CppCastExpressionAST *ast)
+{
+ out << spell(ast->cast_token);
+ out << '<';
+ out << ' ';
+ accept(ast->type_id);
+ out << ' ';
+ out << '>';
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(CtorInitializerAST *ast)
+{
+ out << ':';
+ out << ' ';
+ for (MemInitializerAST *it = ast->member_initializers; it; it = it->next) {
+ accept(it->name);
+ out << '(';
+ accept(it->expression);
+ out << ')';
+ if (it->next)
+ out << ", ";
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(DeclaratorAST *ast)
+{
+ for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) {
+ accept(it);
+ }
+ if (ast->core_declarator) {
+ if (ast->ptr_operators)
+ out << ' ';
+ accept(ast->core_declarator);
+ }
+ for (PostfixDeclaratorAST *it = ast->postfix_declarators; it; it = it->next) {
+ accept(it);
+ }
+ for (SpecifierAST *it = ast->attributes; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->initializer) {
+ out << ' ';
+ out << '=';
+ out << ' ';
+ accept(ast->initializer);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(DeclarationStatementAST *ast)
+{
+ accept(ast->declaration);
+ return false;
+}
+
+bool PrettyPrinter::visit(DeclaratorIdAST *ast)
+{
+ accept(ast->name);
+ return false;
+}
+
+bool PrettyPrinter::visit(DeclaratorListAST *ast)
+{
+ for (DeclaratorListAST *it = ast; it; it = it->next) {
+ accept(it->declarator);
+ if (it->next)
+ out << ", ";
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(DeleteExpressionAST *ast)
+{
+ if (ast->scope_token)
+ out << "::";
+ out << "delete";
+ if (ast->expression) {
+ out << ' ';
+ accept(ast->expression);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(DestructorNameAST *ast)
+{
+ out << '~';
+ out << spell(ast->identifier_token);
+ return false;
+}
+
+bool PrettyPrinter::visit(DoStatementAST *ast)
+{
+ out << "do";
+ if (ast->statement) {
+ out << ' ';
+ accept(ast->statement);
+ }
+ out << "while";
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(ElaboratedTypeSpecifierAST *ast)
+{
+ out << spell(ast->classkey_token);
+ if (ast->name) {
+ out << ' ';
+ accept(ast->name);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(EmptyDeclarationAST *)
+{
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(EnumSpecifierAST *ast)
+{
+ out << "enum";
+ if (ast->name) {
+ out << ' ';
+ accept(ast->name);
+ }
+ out << ' ';
+ out << '{';
+ if (ast->enumerators) {
+ indent();
+ newline();
+ for (EnumeratorAST *it = ast->enumerators; it; it = it->next) {
+ accept(it);
+ if (it->next) {
+ out << ", ";
+ newline();
+ }
+ }
+ deindent();
+ newline();
+ }
+ out << '}';
+ return false;
+}
+
+bool PrettyPrinter::visit(EnumeratorAST *ast)
+{
+ out << spell(ast->identifier_token);
+ if (ast->equal_token) {
+ out << ' ';
+ out << '=';
+ out << ' ';
+ accept(ast->expression);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(ExceptionDeclarationAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarator) {
+ if (ast->type_specifier)
+ out << ' ';
+ accept(ast->declarator);
+ }
+ if (ast->dot_dot_dot_token)
+ out << "...";
+ return false;
+}
+
+bool PrettyPrinter::visit(ExceptionSpecificationAST *ast)
+{
+ out << "throw";
+ out << '(';
+ if (ast->dot_dot_dot_token)
+ out << "...";
+ else {
+ for (ExpressionListAST *it = ast->type_ids; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ }
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(ExpressionListAST *ast)
+{
+ for (ExpressionListAST *it = ast; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(ExpressionOrDeclarationStatementAST *ast)
+{
+ accept(ast->declaration);
+ return false;
+}
+
+bool PrettyPrinter::visit(ExpressionStatementAST *ast)
+{
+ accept(ast->expression);
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(ForStatementAST *ast)
+{
+ out << "for";
+ out << ' ';
+ out << '(';
+ accept(ast->initializer);
+ accept(ast->condition);
+ out << ';';
+ accept(ast->expression);
+ out << ')';
+ accept(ast->statement);
+ return false;
+}
+
+bool PrettyPrinter::visit(FunctionDeclaratorAST *ast)
+{
+ out << '(';
+ accept(ast->parameters);
+ out << ')';
+ for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+ out << ' ';
+ accept(it);
+ }
+ if (ast->exception_specification) {
+ out << ' ';
+ accept(ast->exception_specification);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(FunctionDefinitionAST *ast)
+{
+ for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarator) {
+ if (ast->decl_specifier_seq)
+ out << ' ';
+ accept(ast->declarator);
+ }
+ accept(ast->ctor_initializer);
+ newline();
+ accept(ast->function_body);
+ if (ast->next)
+ newline(); // one extra line after the function definiton.
+ return false;
+}
+
+bool PrettyPrinter::visit(GotoStatementAST *ast)
+{
+ out << "goto";
+ out << ' ';
+ out << spell(ast->identifier_token);
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(IfStatementAST *ast)
+{
+ out << "if";
+ out << ' ';
+ out << '(';
+ accept(ast->condition);
+ out << ')';
+ if (ast->statement->asCompoundStatement()) {
+ out << ' ';
+ accept(ast->statement);
+ } else {
+ indent();
+ newline();
+ accept(ast->statement);
+ deindent();
+ newline();
+ }
+ if (ast->else_token) {
+ out << "else";
+ out << ' ';
+ accept(ast->else_statement);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(LabeledStatementAST *ast)
+{
+ out << spell(ast->label_token);
+ out << ':';
+ accept(ast->statement);
+ return false;
+}
+
+bool PrettyPrinter::visit(LinkageBodyAST *ast)
+{
+ out << '{';
+ if (ast->declarations) {
+ indent();
+ newline();
+ for (DeclarationAST *it = ast->declarations; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ newline();
+ }
+ deindent();
+ newline();
+ }
+ out << '}';
+ return false;
+}
+
+bool PrettyPrinter::visit(LinkageSpecificationAST *ast)
+{
+ out << "extern";
+ out << ' ';
+ if (ast->extern_type) {
+ out << '"' << spell(ast->extern_type) << '"';
+ out << ' ';
+ }
+
+ accept(ast->declaration);
+ return false;
+}
+
+bool PrettyPrinter::visit(MemInitializerAST *ast)
+{
+ accept(ast->name);
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(MemberAccessAST *ast)
+{
+ out << spell(ast->access_token);
+ if (ast->template_token) {
+ out << "template";
+ out << ' ';
+ }
+ accept(ast->member_name);
+ return false;
+}
+
+bool PrettyPrinter::visit(NamedTypeSpecifierAST *ast)
+{
+ accept(ast->name);
+ return false;
+}
+
+bool PrettyPrinter::visit(NamespaceAST *ast)
+{
+ out << "namespace";
+ if (ast->identifier_token) {
+ out << ' ';
+ out << spell(ast->identifier_token);
+ }
+ for (SpecifierAST *it = ast->attributes; it; it = it->next) {
+ out << ' ';
+ accept(it);
+ }
+ out << ' ';
+ accept(ast->linkage_body);
+ return false;
+}
+
+bool PrettyPrinter::visit(NamespaceAliasDefinitionAST *ast)
+{
+ out << "namespace";
+ out << ' ';
+ out << spell(ast->namespace_name);
+ out << ' ';
+ out << '=';
+ out << ' ';
+ accept(ast->name);
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(NestedDeclaratorAST *ast)
+{
+ out << '(';
+ accept(ast->declarator);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(NestedExpressionAST *ast)
+{
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(NestedNameSpecifierAST *ast)
+{
+ accept(ast->class_or_namespace_name);
+ if (ast->scope_token)
+ out << "::";
+ return false;
+}
+
+bool PrettyPrinter::visit(NewDeclaratorAST *ast)
+{
+ for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarator)
+ accept(ast->declarator);
+ return false;
+}
+
+bool PrettyPrinter::visit(NewExpressionAST *ast)
+{
+ if (ast->scope_token)
+ out << "::";
+ out << "new";
+ out << ' ';
+ if (ast->expression) {
+ accept(ast->expression);
+ if (ast->type_id)
+ out << ' ';
+ }
+ if (ast->type_id) {
+ accept(ast->type_id);
+ if (ast->new_type_id)
+ out << ' ';
+ }
+ if (ast->new_type_id) {
+ accept(ast->new_type_id);
+ if (ast->new_initializer)
+ out << ' ';
+ }
+ accept(ast->new_initializer);
+ return false;
+}
+
+bool PrettyPrinter::visit(NewInitializerAST *ast)
+{
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(NewTypeIdAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->type_specifier)
+ out << ' ';
+ if (ast->new_initializer) {
+ accept(ast->new_initializer);
+ if (ast->new_declarator)
+ out << ' ';
+ }
+ accept(ast->new_declarator);
+ return false;
+}
+
+bool PrettyPrinter::visit(NumericLiteralAST *ast)
+{
+ switch (tokenKind(ast->token)) {
+ case T_CHAR_LITERAL:
+ out << '\'' << spell(ast->token) << '\'';
+ break;
+ case T_WIDE_CHAR_LITERAL:
+ out << "L\'" << spell(ast->token) << '\'';
+ break;
+
+ default:
+ out << spell(ast->token);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(OperatorAST *ast)
+{
+ out << spell(ast->op_token);
+ if (ast->open_token) {
+ out << spell(ast->open_token);
+ out << spell(ast->close_token);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(OperatorFunctionIdAST *ast)
+{
+ out << "operator";
+ out << ' ';
+ accept(ast->op);
+ return false;
+}
+
+bool PrettyPrinter::visit(ParameterDeclarationAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarator) {
+ out << ' ';
+ accept(ast->declarator);
+ }
+ if (ast->equal_token) {
+ out << ' ';
+ out << '=';
+ out << ' ';
+ }
+ accept(ast->expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(ParameterDeclarationClauseAST *ast)
+{
+ for (DeclarationAST *it = ast->parameter_declarations; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ", ";
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(PointerAST *ast)
+{
+ out << '*';
+ for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(PointerToMemberAST *ast)
+{
+ if (ast->global_scope_token)
+ out << "::";
+ for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) {
+ accept(it);
+ }
+ out << '*';
+ for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(PostIncrDecrAST *ast)
+{
+ out << spell(ast->incr_decr_token);
+ return false;
+}
+
+bool PrettyPrinter::visit(PostfixExpressionAST *ast)
+{
+ accept(ast->base_expression);
+ for (PostfixAST *it = ast->postfix_expressions; it; it = it->next) {
+ accept(it);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(QualifiedNameAST *ast)
+{
+ if (ast->global_scope_token)
+ out << "::";
+ for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) {
+ accept(it);
+ }
+ accept(ast->unqualified_name);
+ return false;
+}
+
+bool PrettyPrinter::visit(ReferenceAST *)
+{
+ out << '&';
+ return false;
+}
+
+bool PrettyPrinter::visit(ReturnStatementAST *ast)
+{
+ out << "return";
+ if (ast->expression) {
+ out << ' ';
+ accept(ast->expression);
+ }
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(SimpleDeclarationAST *ast)
+{
+ for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->declarators) {
+ if (ast->decl_specifier_seq)
+ out << ' ';
+
+ for (DeclaratorListAST *it = ast->declarators; it; it = it->next) {
+ accept(it->declarator);
+ if (it->next)
+ out << ", ";
+ }
+ }
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(SimpleNameAST *ast)
+{
+ out << spell(ast->identifier_token);
+ return false;
+}
+
+bool PrettyPrinter::visit(SimpleSpecifierAST *ast)
+{
+ out << spell(ast->specifier_token);
+ return false;
+}
+
+bool PrettyPrinter::visit(SizeofExpressionAST *ast)
+{
+ out << "sizeof";
+ out << ' ';
+ accept(ast->expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(StringLiteralAST *ast)
+{
+ for (StringLiteralAST *it = ast; it; it = it->next) {
+ if (tokenKind(ast->token) == T_STRING_LITERAL)
+ out << '"' << spell(ast->token) << '"';
+ else
+ out << "L\"" << spell(ast->token) << '"';
+ if (it->next)
+ out << ' ';
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(SwitchStatementAST *ast)
+{
+ out << "switch";
+ out << ' ';
+ out << '(';
+ accept(ast->condition);
+ out << ')';
+ accept(ast->statement);
+ return false;
+}
+
+bool PrettyPrinter::visit(TemplateArgumentListAST *ast)
+{
+ for (TemplateArgumentListAST *it = ast; it; it = it->next) {
+ accept(it->template_argument);
+ if (it->next)
+ out << ", ";
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(TemplateDeclarationAST *ast)
+{
+ if (ast->export_token) {
+ out << "export";
+ out << ' ';
+ }
+ out << "template";
+ out << ' ';
+ out << '<';
+ if (ast->template_parameters) {
+ out << ' ';
+ for (DeclarationAST *it = ast->template_parameters; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ", ";
+ }
+ out << ' ';
+ }
+ out << '>';
+ newline();
+ accept(ast->declaration);
+ return false;
+}
+
+bool PrettyPrinter::visit(TemplateIdAST *ast)
+{
+ out << spell(ast->identifier_token);
+ out << '<';
+ if (ast->template_arguments) {
+ out << ' ';
+ for (TemplateArgumentListAST *it = ast->template_arguments; it; it = it->next) {
+ accept(it->template_argument);
+ if (it->next)
+ out << ", ";
+ }
+ out << ' ';
+ }
+ out << '>';
+ return false;
+}
+
+bool PrettyPrinter::visit(TemplateTypeParameterAST *ast)
+{
+ out << "template";
+ out << ' ';
+ out << '<';
+ if (ast->template_parameters) {
+ out << ' ';
+ for (DeclarationAST *it = ast->template_parameters; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ", ";
+ }
+ out << ' ';
+ }
+ out << '>';
+ out << ' ';
+ out << "class";
+ out << ' ';
+ accept(ast->name);
+ if (ast->equal_token) {
+ out << ' ';
+ out << '=';
+ out << ' ';
+ accept(ast->type_id);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(ThisExpressionAST *)
+{
+ out << "this";
+ return false;
+}
+
+bool PrettyPrinter::visit(ThrowExpressionAST *ast)
+{
+ out << "throw";
+ out << ' ';
+ accept(ast->expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(TranslationUnitAST *ast)
+{
+ for (DeclarationAST *it = ast->declarations; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ newline();
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(TryBlockStatementAST *ast)
+{
+ out << "try";
+ out << ' ';
+ accept(ast->statement);
+ for (CatchClauseAST *it = ast->catch_clause_seq; it; it = it->next) {
+ accept(it);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(TypeConstructorCallAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ out << '(';
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(TypeIdAST *ast)
+{
+ for (SpecifierAST *it = ast->type_specifier; it; it = it->next) {
+ accept(it);
+ if (it->next)
+ out << ' ';
+ }
+ if (ast->type_specifier && ast->declarator) {
+ out << ' ';
+ accept(ast->declarator);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(TypeidExpressionAST *ast)
+{
+ out << "typeid";
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(TypeofSpecifierAST *ast)
+{
+ out << "typeof";
+ out << '(';
+ accept(ast->expression);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(TypenameCallExpressionAST *ast)
+{
+ out << "typename";
+ out << ' ';
+ accept(ast->name);
+ out << '(';
+ for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
+ accept(it->expression);
+ if (it->next)
+ out << ", ";
+ }
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(TypenameTypeParameterAST *ast)
+{
+ out << spell(ast->classkey_token);
+ if (ast->name) {
+ out << ' ';
+ accept(ast->name);
+ }
+ if (ast->equal_token) {
+ out << ' ';
+ out << '=';
+ out << ' ';
+ accept(ast->type_id);
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(UnaryExpressionAST *ast)
+{
+ out << spell(ast->unary_op_token);
+ accept(ast->expression);
+ return false;
+}
+
+bool PrettyPrinter::visit(UsingAST *ast)
+{
+ out << "using";
+ out << ' ';
+ if (ast->typename_token) {
+ out << "typename";
+ out << ' ';
+ }
+ accept(ast->name);
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(UsingDirectiveAST *ast)
+{
+ out << "using";
+ out << ' ';
+ out << "namespace";
+ out << ' ';
+ accept(ast->name);
+ out << ';';
+ return false;
+}
+
+bool PrettyPrinter::visit(WhileStatementAST *ast)
+{
+ out << "while";
+ out << ' ';
+ out << '(';
+ accept(ast->condition);
+ out << ')';
+ out << ' ';
+ if (ast->statement && ast->statement->asCompoundStatement())
+ accept(ast->statement);
+ else {
+ indent();
+ newline();
+ accept(ast->statement);
+ deindent();
+ newline();
+ }
+ return false;
+}
+
+bool PrettyPrinter::visit(QtMethodAST *ast)
+{
+ out << ast->method_token;
+ out << '(';
+ accept(ast->declarator);
+ out << ')';
+ return false;
+}
+
+bool PrettyPrinter::visit(CompoundLiteralAST *ast)
+{
+ out << '(';
+ accept(ast->type_id);
+ out << ')';
+ out << ' ';
+ accept(ast->initializer);
+ return false;
+}
diff --git a/src/shared/cplusplus/PrettyPrinter.h b/src/shared/cplusplus/PrettyPrinter.h
new file mode 100644
index 0000000000..c69ea2cf54
--- /dev/null
+++ b/src/shared/cplusplus/PrettyPrinter.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#ifndef CPLUSPLUS_PRETTYPRINTER_H
+#define CPLUSPLUS_PRETTYPRINTER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTVisitor.h"
+
+#include <iosfwd>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class PrettyPrinter: protected ASTVisitor
+{
+public:
+ PrettyPrinter(Control *control, std::ostream &out);
+
+ void operator()(AST *ast);
+
+protected:
+ virtual bool visit(AccessDeclarationAST *ast);
+ virtual bool visit(ArrayAccessAST *ast);
+ virtual bool visit(ArrayDeclaratorAST *ast);
+ virtual bool visit(ArrayInitializerAST *ast);
+ virtual bool visit(AsmDefinitionAST *ast);
+ virtual bool visit(AttributeSpecifierAST *ast);
+ virtual bool visit(AttributeAST *ast);
+ virtual bool visit(BaseSpecifierAST *ast);
+ virtual bool visit(BinaryExpressionAST *ast);
+ virtual bool visit(BoolLiteralAST *ast);
+ virtual bool visit(BreakStatementAST *ast);
+ virtual bool visit(CallAST *ast);
+ virtual bool visit(CaseStatementAST *ast);
+ virtual bool visit(CastExpressionAST *ast);
+ virtual bool visit(CatchClauseAST *ast);
+ virtual bool visit(ClassSpecifierAST *ast);
+ virtual bool visit(CompoundLiteralAST *ast);
+ virtual bool visit(CompoundStatementAST *ast);
+ virtual bool visit(ConditionAST *ast);
+ virtual bool visit(ConditionalExpressionAST *ast);
+ virtual bool visit(ContinueStatementAST *ast);
+ virtual bool visit(ConversionFunctionIdAST *ast);
+ virtual bool visit(CppCastExpressionAST *ast);
+ virtual bool visit(CtorInitializerAST *ast);
+ virtual bool visit(DeclaratorAST *ast);
+ virtual bool visit(DeclarationStatementAST *ast);
+ virtual bool visit(DeclaratorIdAST *ast);
+ virtual bool visit(DeclaratorListAST *ast);
+ virtual bool visit(DeleteExpressionAST *ast);
+ virtual bool visit(DestructorNameAST *ast);
+ virtual bool visit(DoStatementAST *ast);
+ virtual bool visit(ElaboratedTypeSpecifierAST *ast);
+ virtual bool visit(EmptyDeclarationAST *ast);
+ virtual bool visit(EnumSpecifierAST *ast);
+ virtual bool visit(EnumeratorAST *ast);
+ virtual bool visit(ExceptionDeclarationAST *ast);
+ virtual bool visit(ExceptionSpecificationAST *ast);
+ virtual bool visit(ExpressionListAST *ast);
+ virtual bool visit(ExpressionOrDeclarationStatementAST *ast);
+ virtual bool visit(ExpressionStatementAST *ast);
+ virtual bool visit(ForStatementAST *ast);
+ virtual bool visit(FunctionDeclaratorAST *ast);
+ virtual bool visit(FunctionDefinitionAST *ast);
+ virtual bool visit(GotoStatementAST *ast);
+ virtual bool visit(IfStatementAST *ast);
+ virtual bool visit(LabeledStatementAST *ast);
+ virtual bool visit(LinkageBodyAST *ast);
+ virtual bool visit(LinkageSpecificationAST *ast);
+ virtual bool visit(MemInitializerAST *ast);
+ virtual bool visit(MemberAccessAST *ast);
+ virtual bool visit(NamedTypeSpecifierAST *ast);
+ virtual bool visit(NamespaceAST *ast);
+ virtual bool visit(NamespaceAliasDefinitionAST *ast);
+ virtual bool visit(NestedDeclaratorAST *ast);
+ virtual bool visit(NestedExpressionAST *ast);
+ virtual bool visit(NestedNameSpecifierAST *ast);
+ virtual bool visit(NewDeclaratorAST *ast);
+ virtual bool visit(NewExpressionAST *ast);
+ virtual bool visit(NewInitializerAST *ast);
+ virtual bool visit(NewTypeIdAST *ast);
+ virtual bool visit(NumericLiteralAST *ast);
+ virtual bool visit(OperatorAST *ast);
+ virtual bool visit(OperatorFunctionIdAST *ast);
+ virtual bool visit(ParameterDeclarationAST *ast);
+ virtual bool visit(ParameterDeclarationClauseAST *ast);
+ virtual bool visit(PointerAST *ast);
+ virtual bool visit(PointerToMemberAST *ast);
+ virtual bool visit(PostIncrDecrAST *ast);
+ virtual bool visit(PostfixExpressionAST *ast);
+ virtual bool visit(QualifiedNameAST *ast);
+ virtual bool visit(ReferenceAST *ast);
+ virtual bool visit(ReturnStatementAST *ast);
+ virtual bool visit(SimpleDeclarationAST *ast);
+ virtual bool visit(SimpleNameAST *ast);
+ virtual bool visit(SimpleSpecifierAST *ast);
+ virtual bool visit(SizeofExpressionAST *ast);
+ virtual bool visit(StringLiteralAST *ast);
+ virtual bool visit(SwitchStatementAST *ast);
+ virtual bool visit(TemplateArgumentListAST *ast);
+ virtual bool visit(TemplateDeclarationAST *ast);
+ virtual bool visit(TemplateIdAST *ast);
+ virtual bool visit(TemplateTypeParameterAST *ast);
+ virtual bool visit(ThisExpressionAST *ast);
+ virtual bool visit(ThrowExpressionAST *ast);
+ virtual bool visit(TranslationUnitAST *ast);
+ virtual bool visit(TryBlockStatementAST *ast);
+ virtual bool visit(TypeConstructorCallAST *ast);
+ virtual bool visit(TypeIdAST *ast);
+ virtual bool visit(TypeidExpressionAST *ast);
+ virtual bool visit(TypeofSpecifierAST *ast);
+ virtual bool visit(TypenameCallExpressionAST *ast);
+ virtual bool visit(TypenameTypeParameterAST *ast);
+ virtual bool visit(UnaryExpressionAST *ast);
+ virtual bool visit(UsingAST *ast);
+ virtual bool visit(UsingDirectiveAST *ast);
+ virtual bool visit(WhileStatementAST *ast);
+ virtual bool visit(QtMethodAST *ast);
+
+ void indent();
+ void deindent();
+ void newline();
+
+private:
+ std::ostream &out;
+ unsigned depth;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_PRETTYPRINTER_H
diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp
new file mode 100644
index 0000000000..bdca9f8536
--- /dev/null
+++ b/src/shared/cplusplus/Scope.cpp
@@ -0,0 +1,310 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Scope.h"
+#include "Symbols.h"
+#include "Names.h"
+#include "Literals.h"
+#include <cstdlib>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+Scope::Scope(ScopedSymbol *owner)
+ : _owner(owner),
+ _symbols(0),
+ _allocatedSymbols(0),
+ _symbolCount(-1),
+ _hash(0),
+ _hashSize(0),
+ _uses(0),
+ _allocatedUses(0),
+ _useCount(-1)
+{ }
+
+Scope::~Scope()
+{
+ if (_symbols)
+ free(_symbols);
+ if (_hash)
+ free(_hash);
+ if (_uses)
+ free(_uses);
+}
+
+ScopedSymbol *Scope::owner() const
+{ return _owner; }
+
+void Scope::setOwner(ScopedSymbol *owner)
+{ _owner = owner; }
+
+Scope *Scope::enclosingScope() const
+{
+ if (! _owner)
+ return 0;
+
+ return _owner->scope();
+}
+
+Scope *Scope::enclosingNamespaceScope() const
+{
+ Scope *scope = enclosingScope();
+ for (; scope; scope = scope->enclosingScope()) {
+ if (scope->owner()->isNamespace())
+ break;
+ }
+ return scope;
+}
+
+Scope *Scope::enclosingClassScope() const
+{
+ Scope *scope = enclosingScope();
+ for (; scope; scope = scope->enclosingScope()) {
+ if (scope->owner()->isClass())
+ break;
+ }
+ return scope;
+}
+
+Scope *Scope::enclosingEnumScope() const
+{
+ Scope *scope = enclosingScope();
+ for (; scope; scope = scope->enclosingScope()) {
+ if (scope->owner()->isEnum())
+ break;
+ }
+ return scope;
+}
+
+Scope *Scope::enclosingFunctionScope() const
+{
+ Scope *scope = enclosingScope();
+ for (; scope; scope = scope->enclosingScope()) {
+ if (scope->owner()->isFunction())
+ break;
+ }
+ return scope;
+}
+
+Scope *Scope::enclosingBlockScope() const
+{
+ Scope *scope = enclosingScope();
+ for (; scope; scope = scope->enclosingScope()) {
+ if (scope->owner()->isBlock())
+ break;
+ }
+ return scope;
+}
+
+bool Scope::isNamespaceScope() const
+{ return dynamic_cast<const Namespace *>(_owner) != 0; }
+
+bool Scope::isClassScope() const
+{ return dynamic_cast<const Class *>(_owner) != 0; }
+
+bool Scope::isEnumScope() const
+{ return dynamic_cast<const Enum *>(_owner) != 0; }
+
+bool Scope::isBlockScope() const
+{ return dynamic_cast<const Block *>(_owner) != 0; }
+
+bool Scope::isPrototypeScope() const
+{
+ if (const Function *f = dynamic_cast<const Function *>(_owner))
+ return f->arguments() == this;
+ return false;
+}
+
+bool Scope::isFunctionScope() const
+{
+ if (const Function *f = dynamic_cast<const Function *>(_owner))
+ return f->arguments() != this;
+ return false;
+}
+
+void Scope::enterSymbol(Symbol *symbol)
+{
+ if (++_symbolCount == _allocatedSymbols) {
+ _allocatedSymbols <<= 1;
+ if (! _allocatedSymbols)
+ _allocatedSymbols = DefaultInitialSize;
+
+ _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols));
+ }
+
+ assert(! symbol->_scope || symbol->scope() == this);
+ symbol->_index = _symbolCount;
+ symbol->_scope = this;
+ _symbols[_symbolCount] = symbol;
+
+ if (_symbolCount >= _hashSize * 0.6)
+ rehash();
+ else {
+ const unsigned h = hashValue(symbol);
+ symbol->_next = _hash[h];
+ _hash[h] = symbol;
+ }
+}
+
+Symbol *Scope::lookat(Identifier *id) const
+{
+ if (! _hash)
+ return 0;
+
+ const unsigned h = id->hashCode() % _hashSize;
+ Symbol *symbol = _hash[h];
+ for (; symbol; symbol = symbol->_next) {
+ Name *identity = symbol->identity();
+ if (NameId *nameId = identity->asNameId()) {
+ if (nameId->identifier()->isEqualTo(id))
+ break;
+ } else if (TemplateNameId *t = identity->asTemplateNameId()) {
+ if (t->identifier()->isEqualTo(id))
+ break;
+ } else if (DestructorNameId *d = identity->asDestructorNameId()) {
+ if (d->identifier()->isEqualTo(id))
+ break;
+ } else if (identity->isQualifiedNameId()) {
+ assert(0);
+ }
+ }
+ return symbol;
+}
+
+Symbol *Scope::lookat(int operatorId) const
+{
+ if (! _hash)
+ return 0;
+
+ const unsigned h = operatorId % _hashSize;
+ Symbol *symbol = _hash[h];
+ for (; symbol; symbol = symbol->_next) {
+ Name *identity = symbol->identity();
+ if (OperatorNameId *op = identity->asOperatorNameId()) {
+ if (op->kind() == operatorId)
+ break;
+ }
+ }
+ return symbol;
+}
+
+void Scope::rehash()
+{
+ _hashSize <<= 1;
+
+ if (! _hashSize)
+ _hashSize = DefaultInitialSize;
+
+ _hash = reinterpret_cast<Symbol **>(realloc(_hash, sizeof(Symbol *) * _hashSize));
+ memset(_hash, 0, sizeof(Symbol *) * _hashSize);
+
+ for (int index = 0; index < _symbolCount + 1; ++index) {
+ Symbol *symbol = _symbols[index];
+ const unsigned h = hashValue(symbol);
+ symbol->_next = _hash[h];
+ _hash[h] = symbol;
+ }
+}
+
+unsigned Scope::hashValue(Symbol *symbol) const
+{
+ if (! symbol)
+ return 0;
+
+ return symbol->hashCode() % _hashSize;
+}
+
+bool Scope::isEmpty() const
+{ return _symbolCount == -1; }
+
+unsigned Scope::symbolCount() const
+{ return _symbolCount + 1; }
+
+Symbol *Scope::symbolAt(unsigned index) const
+{
+ if (! _symbols)
+ return 0;
+ return _symbols[index];
+}
+
+Scope::iterator Scope::firstSymbol() const
+{ return _symbols; }
+
+Scope::iterator Scope::lastSymbol() const
+{ return _symbols + _symbolCount + 1; }
+
+unsigned Scope::useCount() const
+{ return _useCount + 1; }
+
+Use *Scope::useAt(unsigned index) const
+{ return &_uses[index]; }
+
+void Scope::addUse(unsigned sourceOffset, Name *name)
+{
+#ifdef CPLUSPLUS_WITH_USES
+ if (++_useCount == _allocatedUses) {
+ _allocatedUses += 4;
+ _uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use)));
+ }
+
+ Symbol *lastVisibleSymbol;
+ if (_symbolCount == -1)
+ lastVisibleSymbol = owner();
+ else
+ lastVisibleSymbol = _symbols[_symbolCount];
+ _uses[_useCount].init(sourceOffset, name, lastVisibleSymbol);
+#endif
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Scope.h b/src/shared/cplusplus/Scope.h
new file mode 100644
index 0000000000..44387718ff
--- /dev/null
+++ b/src/shared/cplusplus/Scope.h
@@ -0,0 +1,198 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SCOPE_H
+#define CPLUSPLUS_SCOPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Use
+{
+public:
+ inline Name *name() const
+ { return _name; }
+
+ inline unsigned sourceOffset() const
+ { return _sourceOffset; }
+
+ inline Symbol *lastVisibleSymbol() const
+ { return _lastVisibleSymbol; }
+
+private:
+ void init(unsigned sourceOffset, Name *name, Symbol *lastVisibleSymbol)
+ {
+ _sourceOffset = sourceOffset;
+ _name = name;
+ _lastVisibleSymbol = lastVisibleSymbol;
+ }
+
+ unsigned _sourceOffset;
+
+ Name *_name;
+ Symbol *_lastVisibleSymbol;
+
+ friend class Scope;
+};
+
+class CPLUSPLUS_EXPORT Scope
+{
+ Scope(const Scope &other);
+ void operator =(const Scope &other);
+
+public:
+ typedef Symbol **iterator;
+
+public:
+ /// Constructs an empty Scope.
+ Scope(ScopedSymbol *owner = 0);
+
+ /// Destroy this scope.
+ ~Scope();
+
+ /// Returns this scope's owner Symbol.
+ ScopedSymbol *owner() const;
+
+ /// Sets this scope's owner Symbol.
+ void setOwner(ScopedSymbol *owner); // ### remove me
+
+ /// Returns the enclosing scope.
+ Scope *enclosingScope() const;
+
+ /// Returns the eclosing namespace scope.
+ Scope *enclosingNamespaceScope() const;
+
+ /// Returns the enclosing class scope.
+ Scope *enclosingClassScope() const;
+
+ /// Returns the enclosing enum scope.
+ Scope *enclosingEnumScope() const;
+
+ /// Rerturns the enclosing function scope.
+ Scope *enclosingFunctionScope() const;
+
+ /// Rerturns the enclosing Block scope.
+ Scope *enclosingBlockScope() const;
+
+ /// Returns true if this scope's owner is a Namespace Symbol.
+ bool isNamespaceScope() const;
+
+ /// Returns true if this scope's owner is a Class Symbol.
+ bool isClassScope() const;
+
+ /// Returns true if this scope's owner is an Enum Symbol.
+ bool isEnumScope() const;
+
+ /// Returns true if this scope's owner is a Block Symbol.
+ bool isBlockScope() const;
+
+ /// Returns true if this scope's owner is a Function Symbol.
+ bool isFunctionScope() const;
+
+ /// Returns true if this scope's owner is a Prototype Symbol.
+ bool isPrototypeScope() const;
+
+ /// Adds a Symbol to this Scope.
+ void enterSymbol(Symbol *symbol);
+
+ /// Returns true if this Scope is empty; otherwise returns false.
+ bool isEmpty() const;
+
+ /// Returns the number of symbols is in the scope.
+ unsigned symbolCount() const;
+
+ /// Returns the Symbol at the given position.
+ Symbol *symbolAt(unsigned index) const;
+
+ /// Returns the first Symbol in the scope.
+ iterator firstSymbol() const;
+
+ /// Returns the last Symbol in the scope.
+ iterator lastSymbol() const;
+
+ Symbol *lookat(Identifier *id) const;
+ Symbol *lookat(int operatorId) const;
+
+ unsigned useCount() const;
+ Use *useAt(unsigned index) const;
+ void addUse(unsigned sourceOffset, Name *name);
+
+private:
+ /// Returns the hash value for the given Symbol.
+ unsigned hashValue(Symbol *symbol) const;
+
+ /// Updates the hash table.
+ void rehash();
+
+private:
+ enum { DefaultInitialSize = 11 };
+
+ ScopedSymbol *_owner;
+
+ Symbol **_symbols;
+ int _allocatedSymbols;
+ int _symbolCount;
+
+ Symbol **_hash;
+ int _hashSize;
+
+ Use *_uses;
+ int _allocatedUses;
+ int _useCount;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_SCOPE_H
diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp
new file mode 100644
index 0000000000..41716eb5aa
--- /dev/null
+++ b/src/shared/cplusplus/Semantic.cpp
@@ -0,0 +1,198 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Semantic.h"
+#include "TranslationUnit.h"
+#include "Control.h"
+#include "Scope.h"
+#include "Symbols.h"
+#include "Token.h"
+#include "CheckSpecifier.h"
+#include "CheckDeclaration.h"
+#include "CheckDeclarator.h"
+#include "CheckStatement.h"
+#include "CheckExpression.h"
+#include "CheckName.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class Semantic::Data
+{
+public:
+ Data(Semantic *semantic, Control *control)
+ : semantic(semantic),
+ control(control),
+ visibility(Symbol::Public),
+ methodKey(Function::NormalMethod),
+ checkSpecifier(0),
+ checkDeclaration(0),
+ checkDeclarator(0),
+ checkExpression(0),
+ checkStatement(0),
+ checkName(0)
+ { }
+
+ ~Data()
+ {
+ delete checkSpecifier;
+ delete checkDeclaration;
+ delete checkDeclarator;
+ delete checkExpression;
+ delete checkStatement;
+ delete checkName;
+ }
+
+ Semantic *semantic;
+ Control *control;
+ int visibility;
+ int methodKey;
+ CheckSpecifier *checkSpecifier;
+ CheckDeclaration *checkDeclaration;
+ CheckDeclarator *checkDeclarator;
+ CheckExpression *checkExpression;
+ CheckStatement *checkStatement;
+ CheckName *checkName;
+};
+
+Semantic::Semantic(Control *control)
+{
+ d = new Data(this, control);
+ d->checkSpecifier = new CheckSpecifier(this);
+ d->checkDeclaration = new CheckDeclaration(this);
+ d->checkDeclarator = new CheckDeclarator(this);
+ d->checkExpression = new CheckExpression(this);
+ d->checkStatement = new CheckStatement(this);
+ d->checkName = new CheckName(this);
+}
+
+Semantic::~Semantic()
+{ delete d; }
+
+Control *Semantic::control() const
+{ return d->control; }
+
+FullySpecifiedType Semantic::check(SpecifierAST *specifier, Scope *scope)
+{ return d->checkSpecifier->check(specifier, scope); }
+
+void Semantic::check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters)
+{ d->checkDeclaration->check(declaration, scope, templateParameters); }
+
+FullySpecifiedType Semantic::check(DeclaratorAST *declarator, FullySpecifiedType type,
+ Scope *scope, Name **name)
+{ return d->checkDeclarator->check(declarator, type, scope, name); }
+
+FullySpecifiedType Semantic::check(PtrOperatorAST *ptrOperators, FullySpecifiedType type,
+ Scope *scope)
+{ return d->checkDeclarator->check(ptrOperators, type, scope); }
+
+FullySpecifiedType Semantic::check(ExpressionAST *expression, Scope *scope)
+{ return d->checkExpression->check(expression, scope); }
+
+void Semantic::check(StatementAST *statement, Scope *scope)
+{ d->checkStatement->check(statement, scope); }
+
+Name *Semantic::check(NameAST *name, Scope *scope)
+{ return d->checkName->check(name, scope); }
+
+Name *Semantic::check(NestedNameSpecifierAST *name, Scope *scope)
+{ return d->checkName->check(name, scope); }
+
+int Semantic::currentVisibility() const
+{ return d->visibility; }
+
+int Semantic::switchVisibility(int visibility)
+{
+ int previousVisibility = d->visibility;
+ d->visibility = visibility;
+ return previousVisibility;
+}
+
+int Semantic::currentMethodKey() const
+{ return d->methodKey; }
+
+int Semantic::switchMethodKey(int methodKey)
+{
+ int previousMethodKey = d->methodKey;
+ d->methodKey = methodKey;
+ return previousMethodKey;
+}
+
+int Semantic::visibilityForAccessSpecifier(int tokenKind) const
+{
+ switch (tokenKind) {
+ case T_PUBLIC:
+ return Symbol::Public;
+ case T_PROTECTED:
+ return Symbol::Protected;
+ case T_PRIVATE:
+ return Symbol::Private;
+ case T_SIGNALS:
+ return Symbol::Protected;
+ default:
+ return Symbol::Public;
+ }
+}
+
+int Semantic::visibilityForClassKey(int tokenKind) const
+{
+ switch (tokenKind) {
+ case T_CLASS:
+ return Symbol::Private;
+ case T_STRUCT:
+ case T_UNION:
+ return Symbol::Public;
+ default:
+ return Symbol::Public;
+ }
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Semantic.h b/src/shared/cplusplus/Semantic.h
new file mode 100644
index 0000000000..ac7b1b8c86
--- /dev/null
+++ b/src/shared/cplusplus/Semantic.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SEMANTIC_H
+#define CPLUSPLUS_SEMANTIC_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Semantic
+{
+ Semantic(const Semantic &other);
+ void operator =(const Semantic &other);
+
+public:
+ Semantic(Control *control);
+ virtual ~Semantic();
+
+ Control *control() const;
+
+ FullySpecifiedType check(SpecifierAST *specifier, Scope *scope);
+
+ FullySpecifiedType check(DeclaratorAST *declarator, FullySpecifiedType type,
+ Scope *scope, Name **name = 0); // ### ugly
+
+ FullySpecifiedType check(PtrOperatorAST *ptrOperators, FullySpecifiedType type,
+ Scope *scope);
+
+ FullySpecifiedType check(ExpressionAST *expression, Scope *scope);
+
+ void check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters = 0);
+
+ void check(StatementAST *statement, Scope *scope);
+
+ Name *check(NameAST *name, Scope *scope);
+
+ Name *check(NestedNameSpecifierAST *name, Scope *scope);
+
+ int currentVisibility() const;
+ int switchVisibility(int visibility);
+
+ int currentMethodKey() const;
+ int switchMethodKey(int methodKey);
+
+ int visibilityForClassKey(int tokenKind) const;
+ int visibilityForAccessSpecifier(int tokenKind) const;
+
+private:
+ class Data;
+ friend class Data;
+ Data *d;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_SEMANTIC_H
diff --git a/src/shared/cplusplus/SemanticCheck.cpp b/src/shared/cplusplus/SemanticCheck.cpp
new file mode 100644
index 0000000000..27b1a56429
--- /dev/null
+++ b/src/shared/cplusplus/SemanticCheck.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "SemanticCheck.h"
+#include "Semantic.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+SemanticCheck::SemanticCheck(Semantic *semantic)
+ : ASTVisitor(semantic->control()),
+ _semantic(semantic)
+{ }
+
+SemanticCheck::~SemanticCheck()
+{ }
+
+Semantic *SemanticCheck::semantic() const
+{ return _semantic; }
+
+Control *SemanticCheck::control() const
+{ return _semantic->control(); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/SemanticCheck.h b/src/shared/cplusplus/SemanticCheck.h
new file mode 100644
index 0000000000..0ecdeac603
--- /dev/null
+++ b/src/shared/cplusplus/SemanticCheck.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SEMANTICCHECK_H
+#define CPLUSPLUS_SEMANTICCHECK_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTVisitor.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT SemanticCheck: public ASTVisitor
+{
+public:
+ SemanticCheck(Semantic *semantic);
+ virtual ~SemanticCheck();
+
+ Control *control() const;
+ Semantic *semantic() const;
+
+private:
+ Semantic *_semantic;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_SEMANTICCHECK_H
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
new file mode 100644
index 0000000000..cdcd389118
--- /dev/null
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -0,0 +1,421 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Symbol.h"
+#include "Symbols.h"
+#include "Control.h"
+#include "Names.h"
+#include "TranslationUnit.h"
+#include "Literals.h"
+#include "MemoryPool.h"
+#include "SymbolVisitor.h"
+#include "NameVisitor.h"
+#include <cstddef>
+#include <cassert>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class Symbol::HashCode: protected NameVisitor
+{
+public:
+ HashCode()
+ : _value(0)
+ { }
+
+ virtual ~HashCode()
+ { }
+
+ unsigned operator()(Name *name)
+ {
+ unsigned previousValue = switchValue(0);
+ accept(name);
+ return switchValue(previousValue);
+ }
+
+protected:
+ unsigned switchValue(unsigned value)
+ {
+ unsigned previousValue = _value;
+ _value = value;
+ return previousValue;
+ }
+
+ virtual void visit(NameId *name)
+ { _value = name->identifier()->hashCode(); }
+
+ virtual void visit(TemplateNameId *name)
+ { _value = name->identifier()->hashCode(); }
+
+ virtual void visit(DestructorNameId *name)
+ { _value = name->identifier()->hashCode(); }
+
+ virtual void visit(OperatorNameId *name)
+ { _value = unsigned(name->kind()); }
+
+ virtual void visit(ConversionNameId *)
+ { _value = 0; } // ### TODO: implement me
+
+ virtual void visit(QualifiedNameId *name)
+ { _value = operator()(name->unqualifiedNameId()); }
+
+private:
+ unsigned _value;
+};
+
+class Symbol::IdentityForName: protected NameVisitor
+{
+public:
+ IdentityForName()
+ : _identity(0)
+ { }
+
+ virtual ~IdentityForName()
+ { }
+
+ Name *operator()(Name *name)
+ {
+ Name *previousIdentity = switchIdentity(0);
+ accept(name);
+ return switchIdentity(previousIdentity);
+ }
+
+protected:
+ Name *switchIdentity(Name *identity)
+ {
+ Name *previousIdentity = _identity;
+ _identity = identity;
+ return previousIdentity;
+ }
+
+ virtual void visit(NameId *name)
+ { _identity = name; }
+
+ virtual void visit(TemplateNameId *name)
+ { _identity = name; }
+
+ virtual void visit(DestructorNameId *name)
+ { _identity = name; }
+
+ virtual void visit(OperatorNameId *name)
+ { _identity = name; }
+
+ virtual void visit(ConversionNameId *name)
+ { _identity = name; }
+
+ virtual void visit(QualifiedNameId *name)
+ { _identity = name->unqualifiedNameId(); }
+
+private:
+ Name *_identity;
+};
+
+Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : _control(translationUnit->control()),
+ _sourceLocation(sourceLocation),
+ _sourceOffset(0),
+ _name(0),
+ _hashCode(0),
+ _storage(Symbol::NoStorage),
+ _visibility(Symbol::Public),
+ _scope(0),
+ _index(0),
+ _next(0)
+{
+ if (sourceLocation)
+ _sourceOffset = translationUnit->tokenAt(sourceLocation).offset;
+
+ setName(name);
+}
+
+Symbol::~Symbol()
+{ }
+
+Control *Symbol::control() const
+{ return _control; }
+
+TranslationUnit *Symbol::translationUnit() const
+{ return _control->translationUnit(); }
+
+void Symbol::visitSymbol(SymbolVisitor *visitor)
+{
+ if (visitor->preVisit(this))
+ visitSymbol0(visitor);
+ visitor->postVisit(this);
+}
+
+void Symbol::visitSymbol(Symbol *symbol, SymbolVisitor *visitor)
+{
+ if (! symbol)
+ return;
+
+ symbol->visitSymbol(visitor);
+}
+
+unsigned Symbol::sourceLocation() const
+{ return _sourceLocation; }
+
+unsigned Symbol::sourceOffset() const
+{ return _sourceOffset; }
+
+unsigned Symbol::line() const
+{
+ unsigned line = 0, column = 0;
+ StringLiteral *fileId = 0;
+ translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId);
+ return line;
+}
+
+unsigned Symbol::column() const
+{
+#ifdef CPLUSPLUS_WITH_COLUMNS
+ unsigned line = 0, column = 0;
+ StringLiteral *fileId = 0;
+ translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId);
+ return column;
+#else
+ return 0;
+#endif
+}
+
+StringLiteral *Symbol::fileId() const
+{
+ unsigned line = 0, column = 0;
+ StringLiteral *fileId = 0;
+ translationUnit()->getPosition(_sourceOffset, &line, &column, &fileId);
+ return fileId;
+}
+
+const char *Symbol::fileName() const
+{ return fileId()->chars(); }
+
+unsigned Symbol::fileNameLength() const
+{ return fileId()->size(); }
+
+Name *Symbol::identity() const
+{
+ IdentityForName id;
+ return id(_name);
+}
+
+Name *Symbol::name() const
+{ return _name; }
+
+void Symbol::setName(Name *name)
+{
+ _name = name;
+
+ if (! _name)
+ _hashCode = 0;
+ else {
+ IdentityForName identityForName;
+ HashCode hh;
+ _hashCode = hh(identityForName(_name));
+ }
+}
+
+Scope *Symbol::scope() const
+{ return _scope; }
+
+void Symbol::setScope(Scope *scope)
+{
+ assert(! _scope);
+ _scope = scope;
+}
+
+unsigned Symbol::index() const
+{ return _index; }
+
+Symbol *Symbol::next() const
+{ return _next; }
+
+unsigned Symbol::hashCode() const
+{ return _hashCode; }
+
+int Symbol::storage() const
+{ return _storage; }
+
+void Symbol::setStorage(int storage)
+{ _storage = storage; }
+
+int Symbol::visibility() const
+{ return _visibility; }
+
+void Symbol::setVisibility(int visibility)
+{ _visibility = visibility; }
+
+bool Symbol::isFriend() const
+{ return _storage == Friend; }
+
+bool Symbol::isRegister() const
+{ return _storage == Register; }
+
+bool Symbol::isStatic() const
+{ return _storage == Static; }
+
+bool Symbol::isExtern() const
+{ return _storage == Extern; }
+
+bool Symbol::isMutable() const
+{ return _storage == Mutable; }
+
+bool Symbol::isTypedef() const
+{ return _storage == Typedef; }
+
+bool Symbol::isPublic() const
+{ return _visibility == Public; }
+
+bool Symbol::isProtected() const
+{ return _visibility == Protected; }
+
+bool Symbol::isPrivate() const
+{ return _visibility == Private; }
+
+bool Symbol::isScopedSymbol() const
+{ return dynamic_cast<const ScopedSymbol *>(this) != 0; }
+
+bool Symbol::isEnum() const
+{ return dynamic_cast<const Enum *>(this) != 0; }
+
+bool Symbol::isFunction() const
+{ return dynamic_cast<const Function *>(this) != 0; }
+
+bool Symbol::isNamespace() const
+{ return dynamic_cast<const Namespace *>(this) != 0; }
+
+bool Symbol::isClass() const
+{ return dynamic_cast<const Class *>(this) != 0; }
+
+bool Symbol::isBlock() const
+{ return dynamic_cast<const Block *>(this) != 0; }
+
+bool Symbol::isUsingNamespaceDirective() const
+{ return dynamic_cast<const UsingNamespaceDirective *>(this) != 0; }
+
+bool Symbol::isUsingDeclaration() const
+{ return dynamic_cast<const UsingDeclaration *>(this) != 0; }
+
+bool Symbol::isDeclaration() const
+{ return dynamic_cast<const Declaration *>(this) != 0; }
+
+bool Symbol::isArgument() const
+{ return dynamic_cast<const Argument *>(this) != 0; }
+
+bool Symbol::isBaseClass() const
+{ return dynamic_cast<const BaseClass *>(this) != 0; }
+
+const ScopedSymbol *Symbol::asScopedSymbol() const
+{ return dynamic_cast<const ScopedSymbol *>(this); }
+
+const Enum *Symbol::asEnum() const
+{ return dynamic_cast<const Enum *>(this); }
+
+const Function *Symbol::asFunction() const
+{ return dynamic_cast<const Function *>(this); }
+
+const Namespace *Symbol::asNamespace() const
+{ return dynamic_cast<const Namespace *>(this); }
+
+const Class *Symbol::asClass() const
+{ return dynamic_cast<const Class *>(this); }
+
+const Block *Symbol::asBlock() const
+{ return dynamic_cast<const Block *>(this); }
+
+const UsingNamespaceDirective *Symbol::asUsingNamespaceDirective() const
+{ return dynamic_cast<const UsingNamespaceDirective *>(this); }
+
+const UsingDeclaration *Symbol::asUsingDeclaration() const
+{ return dynamic_cast<const UsingDeclaration *>(this); }
+
+const Declaration *Symbol::asDeclaration() const
+{ return dynamic_cast<const Declaration *>(this); }
+
+const Argument *Symbol::asArgument() const
+{ return dynamic_cast<const Argument *>(this); }
+
+const BaseClass *Symbol::asBaseClass() const
+{ return dynamic_cast<const BaseClass *>(this); }
+
+ScopedSymbol *Symbol::asScopedSymbol()
+{ return dynamic_cast<ScopedSymbol *>(this); }
+
+Enum *Symbol::asEnum()
+{ return dynamic_cast<Enum *>(this); }
+
+Function *Symbol::asFunction()
+{ return dynamic_cast<Function *>(this); }
+
+Namespace *Symbol::asNamespace()
+{ return dynamic_cast<Namespace *>(this); }
+
+Class *Symbol::asClass()
+{ return dynamic_cast<Class *>(this); }
+
+Block *Symbol::asBlock()
+{ return dynamic_cast<Block *>(this); }
+
+UsingNamespaceDirective *Symbol::asUsingNamespaceDirective()
+{ return dynamic_cast<UsingNamespaceDirective *>(this); }
+
+UsingDeclaration *Symbol::asUsingDeclaration()
+{ return dynamic_cast<UsingDeclaration *>(this); }
+
+Declaration *Symbol::asDeclaration()
+{ return dynamic_cast<Declaration *>(this); }
+
+Argument *Symbol::asArgument()
+{ return dynamic_cast<Argument *>(this); }
+
+BaseClass *Symbol::asBaseClass()
+{ return dynamic_cast<BaseClass *>(this); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
new file mode 100644
index 0000000000..e9d150e8d5
--- /dev/null
+++ b/src/shared/cplusplus/Symbol.h
@@ -0,0 +1,266 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SYMBOL_H
+#define CPLUSPLUS_SYMBOL_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Symbol
+{
+ Symbol(const Symbol &other);
+ void operator =(const Symbol &other);
+
+public:
+ /// Storage class specifier
+ enum Storage {
+ NoStorage = 0,
+ Friend,
+ Register,
+ Static,
+ Extern,
+ Mutable,
+ Typedef
+ };
+
+ /// Access specifier.
+ enum Visibility {
+ Public,
+ Protected,
+ Private
+ };
+
+public:
+ /// Constructs a Symbol with the given source location, name and translation unit.
+ Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+
+ /// Destroy this Symbol.
+ virtual ~Symbol();
+
+ /// Returns this Symbol's Control object.
+ Control *control() const;
+
+ /// Returns this Symbol's source location.
+ unsigned sourceLocation() const;
+
+ /// Returns this Symbol's source offset.
+ unsigned sourceOffset() const;
+
+ /// Returns this Symbol's line number.
+ unsigned line() const;
+
+ /// Returns this Symbol's column number.
+ unsigned column() const;
+
+ /// Returns this Symbol's file name.
+ StringLiteral *fileId() const;
+
+ /// Returns this Symbol's file name.
+ const char *fileName() const;
+
+ /// Returns this Symbol's file name length.
+ unsigned fileNameLength() const;
+
+ /// Returns this Symbol's name.
+ Name *name() const;
+
+ /// Sets this Symbol's name.
+ void setName(Name *name); // ### dangerous
+
+ /// Returns this Symbol's storage class specifier.
+ int storage() const;
+
+ /// Sets this Symbol's storage class specifier.
+ void setStorage(int storage);
+
+ /// Returns this Symbol's visibility.
+ int visibility() const;
+
+ /// Sets this Symbol's visibility.
+ void setVisibility(int visibility);
+
+ /// Returns this Symbol's scope.
+ Scope *scope() const;
+
+ /// Returns the next chained Symbol.
+ Symbol *next() const;
+
+ /// Returns true if this Symbol has friend storage specifier.
+ bool isFriend() const;
+
+ /// Returns true if this Symbol has register storage specifier.
+ bool isRegister() const;
+
+ /// Returns true if this Symbol has static storage specifier.
+ bool isStatic() const;
+
+ /// Returns true if this Symbol has extern storage specifier.
+ bool isExtern() const;
+
+ /// Returns true if this Symbol has mutable storage specifier.
+ bool isMutable() const;
+
+ /// Returns true if this Symbol has typedef storage specifier.
+ bool isTypedef() const;
+
+ /// Returns true if this Symbol's visibility is public.
+ bool isPublic() const;
+
+ /// Returns true if this Symbol's visibility is protected.
+ bool isProtected() const;
+
+ /// Returns true if this Symbol's visibility is private.
+ bool isPrivate() const;
+
+ /// Returns true if this Symbol is a ScopedSymbol.
+ bool isScopedSymbol() const;
+
+ /// Returns true if this Symbol is an Enum.
+ bool isEnum() const;
+
+ /// Returns true if this Symbol is an Function.
+ bool isFunction() const;
+
+ /// Returns true if this Symbol is a Namespace.
+ bool isNamespace() const;
+
+ /// Returns true if this Symbol is a Class.
+ bool isClass() const;
+
+ /// Returns true if this Symbol is a Block.
+ bool isBlock() const;
+
+ /// Returns true if this Symbol is a UsingNamespaceDirective.
+ bool isUsingNamespaceDirective() const;
+
+ /// Returns true if this Symbol is a UsingDeclaration.
+ bool isUsingDeclaration() const;
+
+ /// Returns true if this Symbol is a Declaration.
+ bool isDeclaration() const;
+
+ /// Returns true if this Symbol is an Argument.
+ bool isArgument() const;
+
+ /// Returns true if this Symbol is a BaseClass.
+ bool isBaseClass() const;
+
+ const ScopedSymbol *asScopedSymbol() const;
+ const Enum *asEnum() const;
+ const Function *asFunction() const;
+ const Namespace *asNamespace() const;
+ const Class *asClass() const;
+ const Block *asBlock() const;
+ const UsingNamespaceDirective *asUsingNamespaceDirective() const;
+ const UsingDeclaration *asUsingDeclaration() const;
+ const Declaration *asDeclaration() const;
+ const Argument *asArgument() const;
+ const BaseClass *asBaseClass() const;
+
+ ScopedSymbol *asScopedSymbol();
+ Enum *asEnum();
+ Function *asFunction();
+ Namespace *asNamespace();
+ Class *asClass();
+ Block *asBlock();
+ UsingNamespaceDirective *asUsingNamespaceDirective();
+ UsingDeclaration *asUsingDeclaration();
+ Declaration *asDeclaration();
+ Argument *asArgument();
+ BaseClass *asBaseClass();
+
+ /// Returns this Symbol's type.
+ virtual FullySpecifiedType type() const = 0;
+
+ /// Returns this Symbol's hash value.
+ unsigned hashCode() const;
+
+ /// Returns this Symbol's index.
+ unsigned index() const;
+
+ Name *identity() const;
+
+ void setScope(Scope *scope); // ### make me private
+
+ void visitSymbol(SymbolVisitor *visitor);
+ static void visitSymbol(Symbol *symbol, SymbolVisitor *visitor);
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor) = 0;
+
+ TranslationUnit *translationUnit() const;
+
+private:
+ Control *_control;
+ unsigned _sourceLocation;
+ unsigned _sourceOffset;
+ Name *_name;
+ unsigned _hashCode;
+ int _storage;
+ int _visibility;
+ Scope *_scope;
+ unsigned _index;
+ Symbol *_next;
+
+ class IdentityForName;
+ class HashCode;
+
+ friend class Scope;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_SYMBOL_H
diff --git a/src/shared/cplusplus/SymbolVisitor.cpp b/src/shared/cplusplus/SymbolVisitor.cpp
new file mode 100644
index 0000000000..95cab998ed
--- /dev/null
+++ b/src/shared/cplusplus/SymbolVisitor.cpp
@@ -0,0 +1,66 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "SymbolVisitor.h"
+#include "Symbol.h"
+
+CPLUSPLUS_USE_NAMESPACE
+
+SymbolVisitor::SymbolVisitor()
+{ }
+
+SymbolVisitor::~SymbolVisitor()
+{ }
+
+void SymbolVisitor::accept(Symbol *symbol)
+{ Symbol::visitSymbol(symbol, this); }
+
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
new file mode 100644
index 0000000000..f0f4738de7
--- /dev/null
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef SYMBOLVISITOR_H
+#define SYMBOLVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT SymbolVisitor
+{
+ SymbolVisitor(const SymbolVisitor &other);
+ void operator =(const SymbolVisitor &other);
+
+public:
+ SymbolVisitor();
+ virtual ~SymbolVisitor();
+
+ void accept(Symbol *symbol);
+
+ virtual bool preVisit(Symbol *) { return true; }
+ virtual void postVisit(Symbol *) {}
+
+ virtual bool visit(UsingNamespaceDirective *) { return true; }
+ virtual bool visit(UsingDeclaration *) { return true; }
+ virtual bool visit(Declaration *) { return true; }
+ virtual bool visit(Argument *) { return true; }
+ virtual bool visit(BaseClass *) { return true; }
+ virtual bool visit(Enum *) { return true; }
+ virtual bool visit(Function *) { return true; }
+ virtual bool visit(Namespace *) { return true; }
+ virtual bool visit(Class *) { return true; }
+ virtual bool visit(Block *) { return true; }
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // SYMBOLVISITOR_H
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
new file mode 100644
index 0000000000..a7ed4682ff
--- /dev/null
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -0,0 +1,484 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Symbols.h"
+#include "Names.h"
+#include "TypeVisitor.h"
+#include "SymbolVisitor.h"
+#include "Scope.h"
+#include <cstdlib>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+UsingNamespaceDirective::UsingNamespaceDirective(TranslationUnit *translationUnit,
+ unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+UsingNamespaceDirective::~UsingNamespaceDirective()
+{ }
+
+FullySpecifiedType UsingNamespaceDirective::type() const
+{ return FullySpecifiedType(); }
+
+void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+UsingDeclaration::UsingDeclaration(TranslationUnit *translationUnit,
+ unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name)
+{ }
+
+UsingDeclaration::~UsingDeclaration()
+{ }
+
+FullySpecifiedType UsingDeclaration::type() const
+{ return FullySpecifiedType(); }
+
+void UsingDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Declaration::Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name),
+ _templateParameters(0)
+{ }
+
+Declaration::~Declaration()
+{ delete _templateParameters; }
+
+unsigned Declaration::templateParameterCount() const
+{
+ if (! _templateParameters)
+ return 0;
+ return _templateParameters->symbolCount();
+}
+
+Symbol *Declaration::templateParameterAt(unsigned index) const
+{ return _templateParameters->symbolAt(index); }
+
+Scope *Declaration::templateParameters() const
+{ return _templateParameters; }
+
+void Declaration::setTemplateParameters(Scope *templateParameters)
+{ _templateParameters = templateParameters; }
+
+void Declaration::setType(FullySpecifiedType type)
+{ _type = type; }
+
+FullySpecifiedType Declaration::type() const
+{ return _type; }
+
+void Declaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Argument::Argument(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name),
+ _initializer(false)
+{ }
+
+Argument::~Argument()
+{ }
+
+bool Argument::hasInitializer() const
+{ return _initializer; }
+
+void Argument::setInitializer(bool hasInitializer)
+{ _initializer = hasInitializer; }
+
+void Argument::setType(FullySpecifiedType type)
+{ _type = type; }
+
+FullySpecifiedType Argument::type() const
+{ return _type; }
+
+void Argument::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Function::Function(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : ScopedSymbol(translationUnit, sourceLocation, name),
+ _templateParameters(0),
+ _flags(0)
+{ _arguments = new Scope(this); }
+
+Function::~Function()
+{
+ delete _templateParameters;
+ delete _arguments;
+}
+
+bool Function::isNormal() const
+{ return _methodKey == NormalMethod; }
+
+bool Function::isSignal() const
+{ return _methodKey == SignalMethod; }
+
+bool Function::isSlot() const
+{ return _methodKey == SlotMethod; }
+
+int Function::methodKey() const
+{ return _methodKey; }
+
+void Function::setMethodKey(int key)
+{ _methodKey = key; }
+
+unsigned Function::templateParameterCount() const
+{
+ if (! _templateParameters)
+ return 0;
+ return _templateParameters->symbolCount();
+}
+
+Symbol *Function::templateParameterAt(unsigned index) const
+{ return _templateParameters->symbolAt(index); }
+
+Scope *Function::templateParameters() const
+{ return _templateParameters; }
+
+void Function::setTemplateParameters(Scope *templateParameters)
+{ _templateParameters = templateParameters; }
+
+bool Function::isEqualTo(const Type *other) const
+{
+ const Function *o = other->asFunction();
+ if (! o)
+ return false;
+ Name *l = identity();
+ Name *r = o->identity();
+ if (l == r || (l && l->isEqualTo(r))) {
+ if (_arguments->symbolCount() != o->_arguments->symbolCount())
+ return false;
+ else if (! _returnType.isEqualTo(o->_returnType))
+ return false;
+ for (unsigned i = 0; i < _arguments->symbolCount(); ++i) {
+ Symbol *l = _arguments->symbolAt(i);
+ Symbol *r = o->_arguments->symbolAt(i);
+ if (! l->type().isEqualTo(r->type()))
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+void Function::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+FullySpecifiedType Function::type() const
+{ return FullySpecifiedType(const_cast<Function *>(this)); }
+
+FullySpecifiedType Function::returnType() const
+{ return _returnType; }
+
+void Function::setReturnType(FullySpecifiedType returnType)
+{ _returnType = returnType; }
+
+unsigned Function::argumentCount() const
+{
+ if (! _arguments)
+ return 0;
+
+ return _arguments->symbolCount();
+}
+
+Symbol *Function::argumentAt(unsigned index) const
+{ return _arguments->symbolAt(index); }
+
+Scope *Function::arguments() const
+{ return _arguments; }
+
+bool Function::isVariadic() const
+{ return _isVariadic; }
+
+void Function::setVariadic(bool isVariadic)
+{ _isVariadic = isVariadic; }
+
+bool Function::isConst() const
+{ return _isConst; }
+
+void Function::setConst(bool isConst)
+{ _isConst = isConst; }
+
+bool Function::isVolatile() const
+{ return _isVolatile; }
+
+void Function::setVolatile(bool isVolatile)
+{ _isVolatile = isVolatile; }
+
+bool Function::isPureVirtual() const
+{ return _isPureVirtual; }
+
+void Function::setPureVirtual(bool isPureVirtual)
+{ _isPureVirtual = isPureVirtual; }
+
+void Function::visitSymbol0(SymbolVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (unsigned i = 0; i < _arguments->symbolCount(); ++i) {
+ visitSymbol(_arguments->symbolAt(i), visitor);
+ }
+ for (unsigned i = 0; i < memberCount(); ++i) {
+ visitSymbol(memberAt(i), visitor);
+ }
+ }
+}
+
+ScopedSymbol::ScopedSymbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name)
+{ _members = new Scope(this); }
+
+ScopedSymbol::~ScopedSymbol()
+{ delete _members; }
+
+unsigned ScopedSymbol::memberCount() const
+{
+ if (! _members)
+ return 0;
+ return _members->symbolCount();
+}
+
+Symbol *ScopedSymbol::memberAt(unsigned index) const
+{
+ if (! _members)
+ return 0;
+ return _members->symbolAt(index);
+}
+
+Scope *ScopedSymbol::members() const
+{ return _members; }
+
+void ScopedSymbol::addMember(Symbol *member)
+{ _members->enterSymbol(member); }
+
+Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
+ : ScopedSymbol(translationUnit, sourceLocation, /*name = */ 0)
+{ }
+
+Block::~Block()
+{ }
+
+FullySpecifiedType Block::type() const
+{ return FullySpecifiedType(); }
+
+void Block::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : ScopedSymbol(translationUnit, sourceLocation, name)
+{ }
+
+Enum::~Enum()
+{ }
+
+FullySpecifiedType Enum::type() const
+{ return FullySpecifiedType(const_cast<Enum *>(this)); }
+
+bool Enum::isEqualTo(const Type *other) const
+{
+ const Enum *o = other->asEnum();
+ if (! o)
+ return false;
+ Name *l = identity();
+ Name *r = o->identity();
+ if (l == r)
+ return true;
+ else if (! l)
+ return false;
+ return l->isEqualTo(r);
+}
+
+void Enum::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+void Enum::visitSymbol0(SymbolVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (unsigned i = 0; i < memberCount(); ++i) {
+ visitSymbol(memberAt(i), visitor);
+ }
+ }
+}
+
+Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : ScopedSymbol(translationUnit, sourceLocation, name)
+{ }
+
+Namespace::~Namespace()
+{ }
+
+bool Namespace::isEqualTo(const Type *other) const
+{
+ const Namespace *o = other->asNamespace();
+ if (! o)
+ return false;
+ Name *l = identity();
+ Name *r = o->identity();
+ if (l == r || (l && l->isEqualTo(r)))
+ return true;
+ return false;
+}
+
+void Namespace::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+void Namespace::visitSymbol0(SymbolVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (unsigned i = 0; i < memberCount(); ++i) {
+ visitSymbol(memberAt(i), visitor);
+ }
+ }
+}
+
+FullySpecifiedType Namespace::type() const
+{ return FullySpecifiedType(const_cast<Namespace *>(this)); }
+
+BaseClass::BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : Symbol(translationUnit, sourceLocation, name),
+ _isVirtual(false)
+{ }
+
+BaseClass::~BaseClass()
+{ }
+
+FullySpecifiedType BaseClass::type() const
+{ return FullySpecifiedType(); }
+
+bool BaseClass::isVirtual() const
+{ return _isVirtual; }
+
+void BaseClass::setVirtual(bool isVirtual)
+{ _isVirtual = isVirtual; }
+
+void BaseClass::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
+ : ScopedSymbol(translationUnit, sourceLocation, name),
+ _key(ClassKey),
+ _templateParameters(0)
+{ }
+
+Class::~Class()
+{ delete _templateParameters; }
+
+bool Class::isClass() const
+{ return _key == ClassKey; }
+
+bool Class::isStruct() const
+{ return _key == StructKey; }
+
+bool Class::isUnion() const
+{ return _key == UnionKey; }
+
+Class::Key Class::classKey() const
+{ return _key; }
+
+void Class::setClassKey(Key key)
+{ _key = key; }
+
+unsigned Class::templateParameterCount() const
+{
+ if (! _templateParameters)
+ return 0;
+ return _templateParameters->symbolCount();
+}
+
+Symbol *Class::templateParameterAt(unsigned index) const
+{ return _templateParameters->symbolAt(index); }
+
+Scope *Class::templateParameters() const
+{ return _templateParameters; }
+
+void Class::setTemplateParameters(Scope *templateParameters)
+{ _templateParameters = templateParameters; }
+
+void Class::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+unsigned Class::baseClassCount() const
+{ return _baseClasses.count(); }
+
+BaseClass *Class::baseClassAt(unsigned index) const
+{ return _baseClasses.at(index); }
+
+void Class::addBaseClass(BaseClass *baseClass)
+{ _baseClasses.push_back(baseClass); }
+
+FullySpecifiedType Class::type() const
+{ return FullySpecifiedType(const_cast<Class *>(this)); }
+
+bool Class::isEqualTo(const Type *other) const
+{
+ const Class *o = other->asClass();
+ if (! o)
+ return false;
+ Name *l = identity();
+ Name *r = o->identity();
+ if (l == r || (l && l->isEqualTo(r)))
+ return true;
+ else
+ return false;
+}
+
+void Class::visitSymbol0(SymbolVisitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (unsigned i = 0; i < _baseClasses.size(); ++i) {
+ visitSymbol(_baseClasses.at(i), visitor);
+ }
+ for (unsigned i = 0; i < memberCount(); ++i) {
+ visitSymbol(memberAt(i), visitor);
+ }
+ }
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
new file mode 100644
index 0000000000..c69483a251
--- /dev/null
+++ b/src/shared/cplusplus/Symbols.h
@@ -0,0 +1,338 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_SYMBOLS_H
+#define CPLUSPLUS_SYMBOLS_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Symbol.h"
+#include "Type.h"
+#include "FullySpecifiedType.h"
+#include "Array.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT UsingNamespaceDirective: public Symbol
+{
+public:
+ UsingNamespaceDirective(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~UsingNamespaceDirective();
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT UsingDeclaration: public Symbol
+{
+public:
+ UsingDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~UsingDeclaration();
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT Declaration: public Symbol
+{
+public:
+ Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Declaration();
+
+ unsigned templateParameterCount() const;
+ Symbol *templateParameterAt(unsigned index) const;
+
+ Scope *templateParameters() const;
+ void setTemplateParameters(Scope *templateParameters);
+
+ void setType(FullySpecifiedType type);
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+ FullySpecifiedType _type;
+ Scope *_templateParameters;
+};
+
+class CPLUSPLUS_EXPORT Argument: public Symbol
+{
+public:
+ Argument(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Argument();
+
+ void setType(FullySpecifiedType type);
+
+ bool hasInitializer() const;
+ void setInitializer(bool hasInitializer);
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+ FullySpecifiedType _type;
+ bool _initializer: 1;
+};
+
+class CPLUSPLUS_EXPORT ScopedSymbol: public Symbol
+{
+public:
+ ScopedSymbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~ScopedSymbol();
+
+ unsigned memberCount() const;
+ Symbol *memberAt(unsigned index) const;
+ Scope *members() const;
+ void addMember(Symbol *member);
+
+private:
+ Scope *_members;
+};
+
+class CPLUSPLUS_EXPORT Block: public ScopedSymbol
+{
+public:
+ Block(TranslationUnit *translationUnit, unsigned sourceLocation);
+ virtual ~Block();
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT Enum: public ScopedSymbol, public Type
+{
+public:
+ Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Enum();
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+ // Type's interface
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+ virtual void accept0(TypeVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT Function: public ScopedSymbol, public Type
+{
+public:
+ enum MethodKey {
+ NormalMethod,
+ SlotMethod,
+ SignalMethod
+ };
+
+public:
+ Function(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Function();
+
+ bool isNormal() const;
+ bool isSignal() const;
+ bool isSlot() const;
+ int methodKey() const;
+ void setMethodKey(int key);
+
+ unsigned templateParameterCount() const;
+ Symbol *templateParameterAt(unsigned index) const;
+
+ Scope *templateParameters() const;
+ void setTemplateParameters(Scope *templateParameters);
+
+ FullySpecifiedType returnType() const;
+ void setReturnType(FullySpecifiedType returnType);
+
+ unsigned argumentCount() const;
+ Symbol *argumentAt(unsigned index) const;
+ Scope *arguments() const;
+
+ bool isVariadic() const;
+ void setVariadic(bool isVariadic);
+
+ bool isConst() const;
+ void setConst(bool isConst);
+
+ bool isVolatile() const;
+ void setVolatile(bool isVolatile);
+
+ bool isPureVirtual() const;
+ void setPureVirtual(bool isPureVirtual);
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+ // Type's interface
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ Name *_name;
+ Scope *_templateParameters;
+ FullySpecifiedType _returnType;
+ union {
+ unsigned _flags;
+
+ struct {
+ unsigned _isVariadic: 1;
+ unsigned _isPureVirtual: 1;
+ unsigned _isConst: 1;
+ unsigned _isVolatile: 1;
+ unsigned _methodKey: 3;
+ };
+ };
+ Scope *_arguments;
+};
+
+class CPLUSPLUS_EXPORT Namespace: public ScopedSymbol, public Type
+{
+public:
+ Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Namespace();
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+ // Type's interface
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+ virtual void accept0(TypeVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT BaseClass: public Symbol
+{
+public:
+ BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~BaseClass();
+
+ bool isVirtual() const;
+ void setVirtual(bool isVirtual);
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+ bool _isVirtual;
+};
+
+class CPLUSPLUS_EXPORT Class: public ScopedSymbol, public Type
+{
+public:
+ Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+ virtual ~Class();
+
+ enum Key {
+ ClassKey,
+ StructKey,
+ UnionKey
+ };
+
+ bool isClass() const;
+ bool isStruct() const;
+ bool isUnion() const;
+ Key classKey() const;
+ void setClassKey(Key key);
+
+ unsigned templateParameterCount() const;
+ Symbol *templateParameterAt(unsigned index) const;
+
+ Scope *templateParameters() const;
+ void setTemplateParameters(Scope *templateParameters);
+
+ unsigned baseClassCount() const;
+ BaseClass *baseClassAt(unsigned index) const;
+ void addBaseClass(BaseClass *baseClass);
+
+ // Symbol's interface
+ virtual FullySpecifiedType type() const;
+
+ // Type's interface
+ virtual bool isEqualTo(const Type *other) const;
+
+protected:
+ virtual void visitSymbol0(SymbolVisitor *visitor);
+ virtual void accept0(TypeVisitor *visitor);
+
+private:
+ Key _key;
+ Scope *_templateParameters;
+ Array<BaseClass *> _baseClasses;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_SYMBOLS_H
diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp
new file mode 100644
index 0000000000..eb672958cd
--- /dev/null
+++ b/src/shared/cplusplus/Token.cpp
@@ -0,0 +1,140 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Token.h"
+#include "Literals.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+static const char *token_names[] = {
+ (""), ("<error>"),
+
+ ("<comment>"),
+
+ ("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"),
+ ("<wide char literal>"), ("<string literal>"), ("<wide char literal>"),
+ ("<@string literal>"), ("<angle string literal>"),
+
+ ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"),
+ (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"),
+ ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="),
+ ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"),
+ ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"),
+ ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="),
+
+ ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"),
+ ("class"), ("const"), ("const_cast"), ("continue"), ("default"),
+ ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"),
+ ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"),
+ ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"),
+ ("mutable"), ("namespace"), ("new"), ("operator"), ("private"),
+ ("protected"), ("public"), ("register"), ("reinterpret_cast"),
+ ("return"), ("short"), ("signed"), ("sizeof"), ("static"),
+ ("static_cast"), ("struct"), ("switch"), ("template"), ("this"),
+ ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"),
+ ("union"), ("unsigned"), ("using"), ("virtual"), ("void"),
+ ("volatile"), ("wchar_t"), ("while"),
+
+ // gnu
+ ("__attribute__"), ("__typeof__"),
+
+ // objc @keywords
+ ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"),
+ ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"),
+ ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"),
+ ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"),
+ ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"),
+
+ ("SIGNAL"), ("SLOT"), ("Q_SIGNALS"), ("Q_SLOTS")
+};
+
+Token::Token() :
+ flags(0), offset(0), ptr(0)
+{
+}
+
+Token::~Token()
+{
+}
+
+void Token::reset()
+{
+ flags = 0;
+ offset = 0;
+ ptr = 0;
+}
+
+const char *Token::name(int kind)
+{ return token_names[kind]; }
+
+const char *Token::spell() const
+{
+ switch (kind) {
+ case T_IDENTIFIER:
+ return identifier->chars();
+
+ case T_INT_LITERAL:
+ case T_FLOAT_LITERAL:
+ case T_CHAR_LITERAL:
+ case T_STRING_LITERAL:
+ case T_AT_STRING_LITERAL:
+ case T_ANGLE_STRING_LITERAL:
+ case T_WIDE_CHAR_LITERAL:
+ case T_WIDE_STRING_LITERAL:
+ return literal->chars();
+
+ default:
+ return token_names[kind];
+ } // switch
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h
new file mode 100644
index 0000000000..f48654aa77
--- /dev/null
+++ b/src/shared/cplusplus/Token.h
@@ -0,0 +1,336 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TOKEN_H
+#define CPLUSPLUS_TOKEN_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include <cstddef>
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+enum Kind {
+ T_EOF_SYMBOL = 0,
+ T_ERROR,
+
+ T_COMMENT,
+ T_IDENTIFIER,
+
+ T_FIRST_LITERAL,
+ T_INT_LITERAL = T_FIRST_LITERAL,
+ T_FLOAT_LITERAL,
+ T_CHAR_LITERAL,
+ T_WIDE_CHAR_LITERAL,
+ T_STRING_LITERAL,
+ T_WIDE_STRING_LITERAL,
+ T_AT_STRING_LITERAL,
+ T_ANGLE_STRING_LITERAL,
+ T_LAST_LITERAL = T_ANGLE_STRING_LITERAL,
+
+ T_FIRST_OPERATOR,
+ T_AMPER = T_FIRST_OPERATOR,
+ T_AMPER_AMPER,
+ T_AMPER_EQUAL,
+ T_ARROW,
+ T_ARROW_STAR,
+ T_CARET,
+ T_CARET_EQUAL,
+ T_COLON,
+ T_COLON_COLON,
+ T_COMMA,
+ T_SLASH,
+ T_SLASH_EQUAL,
+ T_DOT,
+ T_DOT_DOT_DOT,
+ T_DOT_STAR,
+ T_EQUAL,
+ T_EQUAL_EQUAL,
+ T_EXCLAIM,
+ T_EXCLAIM_EQUAL,
+ T_GREATER,
+ T_GREATER_EQUAL,
+ T_GREATER_GREATER,
+ T_GREATER_GREATER_EQUAL,
+ T_LBRACE,
+ T_LBRACKET,
+ T_LESS,
+ T_LESS_EQUAL,
+ T_LESS_LESS,
+ T_LESS_LESS_EQUAL,
+ T_LPAREN,
+ T_MINUS,
+ T_MINUS_EQUAL,
+ T_MINUS_MINUS,
+ T_PERCENT,
+ T_PERCENT_EQUAL,
+ T_PIPE,
+ T_PIPE_EQUAL,
+ T_PIPE_PIPE,
+ T_PLUS,
+ T_PLUS_EQUAL,
+ T_PLUS_PLUS,
+ T_POUND,
+ T_POUND_POUND,
+ T_QUESTION,
+ T_RBRACE,
+ T_RBRACKET,
+ T_RPAREN,
+ T_SEMICOLON,
+ T_STAR,
+ T_STAR_EQUAL,
+ T_TILDE,
+ T_TILDE_EQUAL,
+ T_LAST_OPERATOR = T_TILDE_EQUAL,
+
+ T_FIRST_KEYWORD,
+ T_ASM = T_FIRST_KEYWORD,
+ T_AUTO,
+ T_BOOL,
+ T_BREAK,
+ T_CASE,
+ T_CATCH,
+ T_CHAR,
+ T_CLASS,
+ T_CONST,
+ T_CONST_CAST,
+ T_CONTINUE,
+ T_DEFAULT,
+ T_DELETE,
+ T_DO,
+ T_DOUBLE,
+ T_DYNAMIC_CAST,
+ T_ELSE,
+ T_ENUM,
+ T_EXPLICIT,
+ T_EXPORT,
+ T_EXTERN,
+ T_FALSE,
+ T_FLOAT,
+ T_FOR,
+ T_FRIEND,
+ T_GOTO,
+ T_IF,
+ T_INLINE,
+ T_INT,
+ T_LONG,
+ T_MUTABLE,
+ T_NAMESPACE,
+ T_NEW,
+ T_OPERATOR,
+ T_PRIVATE,
+ T_PROTECTED,
+ T_PUBLIC,
+ T_REGISTER,
+ T_REINTERPRET_CAST,
+ T_RETURN,
+ T_SHORT,
+ T_SIGNED,
+ T_SIZEOF,
+ T_STATIC,
+ T_STATIC_CAST,
+ T_STRUCT,
+ T_SWITCH,
+ T_TEMPLATE,
+ T_THIS,
+ T_THROW,
+ T_TRUE,
+ T_TRY,
+ T_TYPEDEF,
+ T_TYPEID,
+ T_TYPENAME,
+ T_UNION,
+ T_UNSIGNED,
+ T_USING,
+ T_VIRTUAL,
+ T_VOID,
+ T_VOLATILE,
+ T_WCHAR_T,
+ T_WHILE,
+
+ T___ATTRIBUTE__,
+ T___TYPEOF__,
+
+ // obj c++ @ keywords
+ T_FIRST_OBJC_AT_KEYWORD,
+
+ T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD,
+ T_AT_CLASS,
+ T_AT_COMPATIBILITY_ALIAS,
+ T_AT_DEFS,
+ T_AT_DYNAMIC,
+ T_AT_ENCODE,
+ T_AT_END,
+ T_AT_FINALLY,
+ T_AT_IMPLEMENTATION,
+ T_AT_INTERFACE,
+ T_AT_NOT_KEYWORD,
+ T_AT_OPTIONAL,
+ T_AT_PACKAGE,
+ T_AT_PRIVATE,
+ T_AT_PROPERTY,
+ T_AT_PROTECTED,
+ T_AT_PROTOCOL,
+ T_AT_PUBLIC,
+ T_AT_REQUIRED,
+ T_AT_SELECTOR,
+ T_AT_SYNCHRONIZED,
+ T_AT_SYNTHESIZE,
+ T_AT_THROW,
+ T_AT_TRY,
+
+ T_LAST_OBJC_AT_KEYWORD,
+
+ T_FIRST_QT_KEYWORD = T_LAST_OBJC_AT_KEYWORD,
+
+ // Qt keywords
+ T_SIGNAL = T_FIRST_QT_KEYWORD,
+ T_SLOT,
+ T_SIGNALS,
+ T_SLOTS,
+
+ T_LAST_KEYWORD = T_SLOTS,
+
+ // aliases
+ T_OR = T_PIPE_PIPE,
+ T_AND = T_AMPER_AMPER,
+ T_NOT = T_EXCLAIM,
+ T_XOR = T_CARET,
+ T_BITOR = T_PIPE,
+ T_COMPL = T_TILDE,
+ T_OR_EQ = T_PIPE_EQUAL,
+ T_AND_EQ = T_AMPER_EQUAL,
+ T_BITAND = T_AMPER,
+ T_NOT_EQ = T_EXCLAIM_EQUAL,
+ T_XOR_EQ = T_CARET_EQUAL,
+
+ T___ASM = T_ASM,
+ T___ASM__ = T_ASM,
+
+ T_TYPEOF = T___TYPEOF__,
+ T___TYPEOF = T___TYPEOF__,
+
+ T___INLINE = T_INLINE,
+ T___INLINE__ = T_INLINE,
+
+ T___CONST = T_CONST,
+ T___CONST__ = T_CONST,
+
+ T___VOLATILE = T_VOLATILE,
+ T___VOLATILE__ = T_VOLATILE,
+
+ T___ATTRIBUTE = T___ATTRIBUTE__
+};
+
+class CPLUSPLUS_EXPORT Token
+{
+public:
+ Token();
+ ~Token();
+
+ inline bool is(unsigned k) const { return kind == k; }
+ inline bool isNot(unsigned k) const { return kind != k; }
+ const char *spell() const;
+ void reset();
+
+ inline unsigned begin() const
+ { return offset; }
+
+ inline unsigned end() const
+ { return offset + length; }
+
+ inline bool isLiteral() const
+ { return kind >= T_FIRST_LITERAL && kind <= T_LAST_LITERAL; }
+
+ inline bool isOperator() const
+ { return kind >= T_FIRST_OPERATOR && kind <= T_LAST_OPERATOR; }
+
+ inline bool isKeyword() const
+ { return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; }
+
+ inline bool isObjCAtKeyword() const
+ { return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; }
+
+ static const char *name(int kind);
+
+public:
+ union {
+ unsigned flags;
+
+ struct {
+ unsigned kind : 8;
+ unsigned newline : 1;
+ unsigned whitespace : 1;
+ unsigned joined : 1;
+ unsigned expanded : 1;
+ unsigned pad : 4;
+ unsigned length : 16;
+ };
+ };
+
+ unsigned offset;
+
+ union {
+ void *ptr;
+ Literal *literal;
+ NumericLiteral *number;
+ StringLiteral *string;
+ Identifier *identifier;
+ unsigned close_brace;
+ unsigned lineno;
+ };
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_TOKEN_H
diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp
new file mode 100644
index 0000000000..40a95c0f05
--- /dev/null
+++ b/src/shared/cplusplus/TranslationUnit.cpp
@@ -0,0 +1,474 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "TranslationUnit.h"
+#include "Control.h"
+#include "Parser.h"
+#include "Lexer.h"
+#include "MemoryPool.h"
+#include "AST.h"
+#include "Literals.h"
+#include "DiagnosticClient.h"
+#include <stack>
+#include <cstdlib>
+#include <cstdarg>
+#include <algorithm>
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+TranslationUnit::TranslationUnit(Control *control, StringLiteral *fileId)
+ : _control(control),
+ _fileId(fileId),
+ _firstSourceChar(0),
+ _lastSourceChar(0),
+ _pool(0),
+ _ast(0),
+ _flags(0)
+{
+ _tokens = new Array<Token, 8>();
+ _previousTranslationUnit = control->switchTranslationUnit(this);
+ _pool = new MemoryPool();
+}
+
+TranslationUnit::~TranslationUnit()
+{
+ (void) _control->switchTranslationUnit(_previousTranslationUnit);
+ delete _tokens;
+ delete _pool;
+}
+
+bool TranslationUnit::qtMocRunEnabled() const
+{ return _qtMocRunEnabled; }
+
+void TranslationUnit::setQtMocRunEnabled(bool onoff)
+{ _qtMocRunEnabled = onoff; }
+
+bool TranslationUnit::objCEnabled() const
+{ return _objCEnabled; }
+
+void TranslationUnit::setObjCEnabled(bool onoff)
+{ _objCEnabled = onoff; }
+
+Control *TranslationUnit::control() const
+{ return _control; }
+
+StringLiteral *TranslationUnit::fileId() const
+{ return _fileId; }
+
+const char *TranslationUnit::fileName() const
+{ return _fileId->chars(); }
+
+unsigned TranslationUnit::fileNameLength() const
+{ return _fileId->size(); }
+
+const char *TranslationUnit::firstSourceChar() const
+{ return _firstSourceChar; }
+
+const char *TranslationUnit::lastSourceChar() const
+{ return _lastSourceChar; }
+
+unsigned TranslationUnit::sourceLength() const
+{ return _lastSourceChar - _firstSourceChar; }
+
+void TranslationUnit::setSource(const char *source, unsigned size)
+{
+ _firstSourceChar = source;
+ _lastSourceChar = source + size;
+}
+
+unsigned TranslationUnit::tokenCount() const
+{ return _tokens->size(); }
+
+const Token &TranslationUnit::tokenAt(unsigned index) const
+{ return _tokens->at(index); }
+
+int TranslationUnit::tokenKind(unsigned index) const
+{ return _tokens->at(index).kind; }
+
+Identifier *TranslationUnit::identifier(unsigned index) const
+{ return _tokens->at(index).identifier; }
+
+Literal *TranslationUnit::literal(unsigned index) const
+{ return _tokens->at(index).literal; }
+
+StringLiteral *TranslationUnit::stringLiteral(unsigned index) const
+{ return _tokens->at(index).string; }
+
+NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const
+{ return _tokens->at(index).number; }
+
+unsigned TranslationUnit::matchingBrace(unsigned index) const
+{ return _tokens->at(index).close_brace; }
+
+MemoryPool *TranslationUnit::memoryPool() const
+{ return _pool; }
+
+AST *TranslationUnit::ast() const
+{ return _ast; }
+
+bool TranslationUnit::isTokenized() const
+{ return _tokenized; }
+
+bool TranslationUnit::isParsed() const
+{ return _parsed; }
+
+void TranslationUnit::tokenize()
+{
+ if (isTokenized())
+ return;
+
+ _tokenized = true;
+
+ Lexer lex(this);
+ lex.setQtMocRunEnabled(_qtMocRunEnabled);
+ lex.setObjCEnabled(_objCEnabled);
+
+ std::stack<unsigned> braces;
+ _tokens->push_back(Token()); // the first token needs to be invalid!
+
+ pushLineOffset(0);
+ pushPreprocessorLine(0, 1, fileId());
+
+ Identifier *lineId = control()->findOrInsertIdentifier("line");
+
+ Token tk;
+ do {
+ lex(&tk);
+
+ _Lrecognize:
+ if (tk.is(T_POUND)) {
+ unsigned offset = tk.offset;
+ lex(&tk);
+ if (! tk.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId)
+ lex(&tk);
+ if (! tk.newline && tk.is(T_INT_LITERAL)) {
+ unsigned line = (unsigned) strtoul(tk.spell(), 0, 0);
+ lex(&tk);
+ if (! tk.newline && tk.is(T_STRING_LITERAL)) {
+ StringLiteral *fileName = control()->findOrInsertFileName(tk.string->chars(),
+ tk.string->size());
+ pushPreprocessorLine(offset, line, fileName);
+ lex(&tk);
+ }
+ }
+ while (tk.isNot(T_EOF_SYMBOL) && ! tk.newline)
+ lex(&tk);
+ goto _Lrecognize;
+ } else if (tk.kind == T_LBRACE) {
+ braces.push(_tokens->size());
+ } else if (tk.kind == T_RBRACE && ! braces.empty()) {
+ const unsigned open_brace_index = braces.top();
+ braces.pop();
+ (*_tokens)[open_brace_index].close_brace = _tokens->size();
+ }
+ _tokens->push_back(tk);
+ } while (tk.kind);
+
+ for (; ! braces.empty(); braces.pop()) {
+ unsigned open_brace_index = braces.top();
+ (*_tokens)[open_brace_index].close_brace = _tokens->size();
+ }
+}
+
+bool TranslationUnit::skipFunctionBody() const
+{ return _skipFunctionBody; }
+
+void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody)
+{ _skipFunctionBody = skipFunctionBody; }
+
+bool TranslationUnit::parse(ParseMode mode)
+{
+ if (isParsed())
+ return false;
+
+ if (! isTokenized())
+ tokenize();
+
+ Parser parser(this);
+ parser.setQtMocRunEnabled(_qtMocRunEnabled);
+ parser.setObjCEnabled(_objCEnabled);
+
+ bool parsed = false;
+
+ switch (mode) {
+ case ParseTranlationUnit: {
+ TranslationUnitAST *node = 0;
+ parsed = parser.parseTranslationUnit(node);
+ _ast = node;
+ } break;
+
+ case ParseDeclaration: {
+ DeclarationAST *node = 0;
+ parsed = parser.parseDeclaration(node);
+ _ast = node;
+ } break;
+
+ case ParseExpression: {
+ ExpressionAST *node = 0;
+ parsed = parser.parseExpression(node);
+ _ast = node;
+ } break;
+
+ case ParseStatement: {
+ StatementAST *node = 0;
+ parsed = parser.parseStatement(node);
+ _ast = node;
+ } break;
+
+ default:
+ break;
+ } // switch
+
+ return parsed;
+}
+
+void TranslationUnit::pushLineOffset(unsigned offset)
+{ _lineOffsets.push_back(offset); }
+
+void TranslationUnit::pushPreprocessorLine(unsigned offset,
+ unsigned line,
+ StringLiteral *fileName)
+{ _ppLines.push_back(PPLine(offset, line, fileName)); }
+
+unsigned TranslationUnit::findLineNumber(unsigned offset) const
+{
+ std::vector<unsigned>::const_iterator it =
+ std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), offset);
+
+ if (it != _lineOffsets.begin())
+ --it;
+
+ return it - _lineOffsets.begin();
+}
+
+TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const
+{
+ std::vector<PPLine>::const_iterator it =
+ std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset));
+
+ if (it != _ppLines.begin())
+ --it;
+
+ return *it;
+}
+
+unsigned TranslationUnit::findColumnNumber(unsigned offset, unsigned lineNumber) const
+{
+ if (! offset)
+ return 0;
+
+ return offset - _lineOffsets[lineNumber];
+}
+
+void TranslationUnit::getTokenPosition(unsigned index,
+ unsigned *line,
+ unsigned *column,
+ StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).offset, line, column, fileName); }
+
+void TranslationUnit::getPosition(unsigned tokenOffset,
+ unsigned *line,
+ unsigned *column,
+ StringLiteral **fileName) const
+{
+ unsigned lineNumber = findLineNumber(tokenOffset);
+ unsigned columnNumber = findColumnNumber(tokenOffset, lineNumber);
+ const PPLine ppLine = findPreprocessorLine(tokenOffset);
+
+ lineNumber -= findLineNumber(ppLine.offset) + 1;
+ lineNumber += ppLine.line;
+
+ if (line)
+ *line = lineNumber;
+
+ if (column)
+ *column = columnNumber;
+
+ if (fileName)
+ *fileName = ppLine.fileName;
+}
+
+bool TranslationUnit::blockErrors(bool block)
+{
+ bool previous = _blockErrors;
+ _blockErrors = block;
+ return previous;
+}
+
+void TranslationUnit::warning(unsigned index, const char *format, ...)
+{
+ if (_blockErrors)
+ return;
+
+ index = std::min(index, tokenCount() - 1);
+
+ unsigned line = 0, column = 0;
+ StringLiteral *fileName = 0;
+ getTokenPosition(index, &line, &column, &fileName);
+
+ if (DiagnosticClient *client = control()->diagnosticClient()) {
+ va_list args;
+ va_start(args, format);
+ client->report(DiagnosticClient::Warning, fileName, line, column,
+ format, args);
+ va_end(args);
+ } else {
+ fprintf(stderr, "%s:%d: ", fileName->chars(), line);
+ fprintf(stderr, "warning: ");
+
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+
+ showErrorLine(index, column, stderr);
+ }
+}
+
+void TranslationUnit::error(unsigned index, const char *format, ...)
+{
+ if (_blockErrors)
+ return;
+
+ index = std::min(index, tokenCount() - 1);
+
+ unsigned line = 0, column = 0;
+ StringLiteral *fileName = 0;
+ getTokenPosition(index, &line, &column, &fileName);
+
+ if (DiagnosticClient *client = control()->diagnosticClient()) {
+ va_list args;
+ va_start(args, format);
+ client->report(DiagnosticClient::Error, fileName, line, column,
+ format, args);
+ va_end(args);
+ } else {
+ fprintf(stderr, "%s:%d: ", fileName->chars(), line);
+ fprintf(stderr, "error: ");
+
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+
+ showErrorLine(index, column, stderr);
+ }
+}
+
+void TranslationUnit::fatal(unsigned index, const char *format, ...)
+{
+ if (_blockErrors)
+ return;
+
+ index = std::min(index, tokenCount() - 1);
+
+ unsigned line = 0, column = 0;
+ StringLiteral *fileName = 0;
+ getTokenPosition(index, &line, &column, &fileName);
+
+ if (DiagnosticClient *client = control()->diagnosticClient()) {
+ va_list args;
+ va_start(args, format);
+ client->report(DiagnosticClient::Fatal, fileName, line, column,
+ format, args);
+ va_end(args);
+ } else {
+ fprintf(stderr, "%s:%d: ", fileName->chars(), line);
+ fprintf(stderr, "fatal: ");
+
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+
+ showErrorLine(index, column, stderr);
+ }
+
+ exit(EXIT_FAILURE);
+}
+
+void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out)
+{
+ unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)];
+ for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) {
+ fputc(*cp, out);
+ }
+ fputc('\n', out);
+
+ const char *end = _firstSourceChar + lineOffset + 1 + column - 1;
+ for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) {
+ if (*cp != '\t')
+ fputc(' ', out);
+ else
+ fputc('\t', out);
+ }
+ fputc('^', out);
+ fputc('\n', out);
+}
+
+void TranslationUnit::resetAST()
+{
+ delete _pool;
+ _pool = 0;
+}
+
+void TranslationUnit::release()
+{
+ resetAST();
+ delete _tokens;
+ _tokens = 0;
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h
new file mode 100644
index 0000000000..aa490701ef
--- /dev/null
+++ b/src/shared/cplusplus/TranslationUnit.h
@@ -0,0 +1,201 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TRANSLATIONUNIT_H
+#define CPLUSPLUS_TRANSLATIONUNIT_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "ASTfwd.h"
+#include "Token.h"
+#include "Array.h"
+#include <cstdio>
+#include <vector> // ### remove me
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT TranslationUnit
+{
+ TranslationUnit(const TranslationUnit &other);
+ void operator =(const TranslationUnit &other);
+
+public:
+ TranslationUnit(Control *control, StringLiteral *fileId);
+ ~TranslationUnit();
+
+ Control *control() const;
+
+ StringLiteral *fileId() const;
+ const char *fileName() const;
+ unsigned fileNameLength() const;
+
+ const char *firstSourceChar() const;
+ const char *lastSourceChar() const;
+ unsigned sourceLength() const;
+
+ void setSource(const char *source, unsigned size);
+
+ unsigned tokenCount() const;
+ const Token &tokenAt(unsigned index) const;
+ int tokenKind(unsigned index) const;
+
+ unsigned matchingBrace(unsigned index) const;
+ Identifier *identifier(unsigned index) const;
+ Literal *literal(unsigned index) const;
+ StringLiteral *stringLiteral(unsigned index) const;
+ NumericLiteral *numericLiteral(unsigned index) const;
+
+ MemoryPool *memoryPool() const;
+ AST *ast() const;
+
+ bool blockErrors(bool block);
+
+ bool qtMocRunEnabled() const;
+ void setQtMocRunEnabled(bool onoff);
+
+ bool objCEnabled() const;
+ void setObjCEnabled(bool onoff);
+
+ void warning(unsigned index, const char *fmt, ...);
+ void error(unsigned index, const char *fmt, ...);
+ void fatal(unsigned index, const char *fmt, ...);
+
+ bool isTokenized() const;
+ void tokenize();
+
+ bool skipFunctionBody() const;
+ void setSkipFunctionBody(bool skipFunctionBody);
+
+ bool isParsed() const;
+
+ enum ParseMode {
+ ParseTranlationUnit,
+ ParseDeclaration,
+ ParseExpression,
+ ParseStatement
+ };
+
+ bool parse(ParseMode mode = ParseTranlationUnit);
+
+ void resetAST();
+ void release();
+
+ void getPosition(unsigned offset,
+ unsigned *line,
+ unsigned *column = 0,
+ StringLiteral **fileName = 0) const;
+
+ void getTokenPosition(unsigned index,
+ unsigned *line,
+ unsigned *column = 0,
+ StringLiteral **fileName = 0) const;
+
+ void pushLineOffset(unsigned offset);
+ void pushPreprocessorLine(unsigned offset,
+ unsigned line,
+ StringLiteral *fileName);
+
+public:
+ struct PPLine {
+ unsigned offset;
+ unsigned line;
+ StringLiteral *fileName;
+
+ PPLine(unsigned offset = 0,
+ unsigned line = 0,
+ StringLiteral *fileName = 0)
+ : offset(offset), line(line), fileName(fileName)
+ { }
+
+ bool operator == (const PPLine &other) const
+ { return offset == other.offset; }
+
+ bool operator != (const PPLine &other) const
+ { return offset != other.offset; }
+
+ bool operator < (const PPLine &other) const
+ { return offset < other.offset; }
+ };
+
+private:
+ unsigned findLineNumber(unsigned offset) const;
+ unsigned findColumnNumber(unsigned offset, unsigned lineNumber) const;
+ PPLine findPreprocessorLine(unsigned offset) const;
+ void showErrorLine(unsigned index, unsigned column, FILE *out);
+
+ Control *_control;
+ StringLiteral *_fileId;
+ const char *_firstSourceChar;
+ const char *_lastSourceChar;
+ Array<Token, 8> *_tokens;
+ std::vector<unsigned> _lineOffsets;
+ std::vector<PPLine> _ppLines;
+ MemoryPool *_pool;
+ AST *_ast;
+ TranslationUnit *_previousTranslationUnit;
+ union {
+ unsigned _flags;
+ struct {
+ unsigned _tokenized: 1;
+ unsigned _parsed: 1;
+ unsigned _blockErrors: 1;
+ unsigned _skipFunctionBody: 1;
+ unsigned _qtMocRunEnabled: 1;
+ unsigned _objCEnabled: 1;
+ };
+ };
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_TRANSLATIONUNIT_H
diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp
new file mode 100644
index 0000000000..98ccd3c893
--- /dev/null
+++ b/src/shared/cplusplus/Type.cpp
@@ -0,0 +1,198 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "Type.h"
+#include "TypeVisitor.h"
+#include "CoreTypes.h"
+#include "Symbols.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+Type::Type()
+{ }
+
+Type::~Type()
+{ }
+
+bool Type::isVoidType() const
+{ return dynamic_cast<const VoidType *>(this) != 0; }
+
+bool Type::isIntegerType() const
+{ return dynamic_cast<const IntegerType *>(this) != 0; }
+
+bool Type::isFloatType() const
+{ return dynamic_cast<const FloatType *>(this) != 0; }
+
+bool Type::isPointerType() const
+{ return dynamic_cast<const PointerType *>(this) != 0; }
+
+bool Type::isPointerToMemberType() const
+{ return dynamic_cast<const PointerToMemberType *>(this) != 0; }
+
+bool Type::isReferenceType() const
+{ return dynamic_cast<const ReferenceType *>(this) != 0; }
+
+bool Type::isArrayType() const
+{ return dynamic_cast<const ArrayType *>(this) != 0; }
+
+bool Type::isNamedType() const
+{ return dynamic_cast<const NamedType *>(this) != 0; }
+
+bool Type::isFunction() const
+{ return dynamic_cast<const Function *>(this) != 0; }
+
+bool Type::isNamespace() const
+{ return dynamic_cast<const Namespace *>(this) != 0; }
+
+bool Type::isClass() const
+{ return dynamic_cast<const Class *>(this) != 0; }
+
+bool Type::isEnum() const
+{ return dynamic_cast<const Enum *>(this) != 0; }
+
+bool Type::isScopedSymbol() const
+{ return dynamic_cast<const ScopedSymbol *>(this) != 0; }
+
+const VoidType *Type::asVoidType() const
+{ return dynamic_cast<const VoidType *>(this); }
+
+const IntegerType *Type::asIntegerType() const
+{ return dynamic_cast<const IntegerType *>(this); }
+
+const FloatType *Type::asFloatType() const
+{ return dynamic_cast<const FloatType *>(this); }
+
+const PointerType *Type::asPointerType() const
+{ return dynamic_cast<const PointerType *>(this); }
+
+const PointerToMemberType *Type::asPointerToMemberType() const
+{ return dynamic_cast<const PointerToMemberType *>(this); }
+
+const ReferenceType *Type::asReferenceType() const
+{ return dynamic_cast<const ReferenceType *>(this); }
+
+const ArrayType *Type::asArrayType() const
+{ return dynamic_cast<const ArrayType *>(this); }
+
+const NamedType *Type::asNamedType() const
+{ return dynamic_cast<const NamedType *>(this); }
+
+const Function *Type::asFunction() const
+{ return dynamic_cast<const Function *>(this); }
+
+const Namespace *Type::asNamespace() const
+{ return dynamic_cast<const Namespace *>(this); }
+
+const Class *Type::asClass() const
+{ return dynamic_cast<const Class *>(this); }
+
+const Enum *Type::asEnum() const
+{ return dynamic_cast<const Enum *>(this); }
+
+const ScopedSymbol *Type::asScopedSymbol() const
+{ return dynamic_cast<const ScopedSymbol *>(this); }
+
+VoidType *Type::asVoidType()
+{ return dynamic_cast<VoidType *>(this); }
+
+IntegerType *Type::asIntegerType()
+{ return dynamic_cast<IntegerType *>(this); }
+
+FloatType *Type::asFloatType()
+{ return dynamic_cast<FloatType *>(this); }
+
+PointerType *Type::asPointerType()
+{ return dynamic_cast<PointerType *>(this); }
+
+PointerToMemberType *Type::asPointerToMemberType()
+{ return dynamic_cast<PointerToMemberType *>(this); }
+
+ReferenceType *Type::asReferenceType()
+{ return dynamic_cast<ReferenceType *>(this); }
+
+ArrayType *Type::asArrayType()
+{ return dynamic_cast<ArrayType *>(this); }
+
+NamedType *Type::asNamedType()
+{ return dynamic_cast<NamedType *>(this); }
+
+Function *Type::asFunction()
+{ return dynamic_cast<Function *>(this); }
+
+Namespace *Type::asNamespace()
+{ return dynamic_cast<Namespace *>(this); }
+
+Class *Type::asClass()
+{ return dynamic_cast<Class *>(this); }
+
+Enum *Type::asEnum()
+{ return dynamic_cast<Enum *>(this); }
+
+ScopedSymbol *Type::asScopedSymbol()
+{ return dynamic_cast<ScopedSymbol *>(this); }
+
+void Type::accept(TypeVisitor *visitor)
+{
+ if (visitor->preVisit(this))
+ accept0(visitor);
+ visitor->postVisit(this);
+}
+
+void Type::accept(Type *type, TypeVisitor *visitor)
+{
+ if (! type)
+ return;
+
+ type->accept(visitor);
+}
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h
new file mode 100644
index 0000000000..7cc347d553
--- /dev/null
+++ b/src/shared/cplusplus/Type.h
@@ -0,0 +1,124 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TYPE_H
+#define CPLUSPLUS_TYPE_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT Type
+{
+ Type(const Type &other);
+ void operator =(const Type &other);
+
+public:
+ Type();
+ virtual ~Type();
+
+ bool isVoidType() const;
+ bool isIntegerType() const;
+ bool isFloatType() const;
+ bool isPointerType() const;
+ bool isPointerToMemberType() const;
+ bool isReferenceType() const;
+ bool isArrayType() const;
+ bool isNamedType() const;
+ bool isFunction() const;
+ bool isNamespace() const;
+ bool isClass() const;
+ bool isEnum() const;
+ bool isScopedSymbol() const;
+
+ const VoidType *asVoidType() const;
+ const IntegerType *asIntegerType() const;
+ const FloatType *asFloatType() const;
+ const PointerType *asPointerType() const;
+ const PointerToMemberType *asPointerToMemberType() const;
+ const ReferenceType *asReferenceType() const;
+ const ArrayType *asArrayType() const;
+ const NamedType *asNamedType() const;
+ const Function *asFunction() const;
+ const Namespace *asNamespace() const;
+ const Class *asClass() const;
+ const Enum *asEnum() const;
+ const ScopedSymbol *asScopedSymbol() const;
+
+ VoidType *asVoidType();
+ IntegerType *asIntegerType();
+ FloatType *asFloatType();
+ PointerType *asPointerType();
+ PointerToMemberType *asPointerToMemberType();
+ ReferenceType *asReferenceType();
+ ArrayType *asArrayType();
+ NamedType *asNamedType();
+ Function *asFunction();
+ Namespace *asNamespace();
+ Class *asClass();
+ Enum *asEnum();
+ ScopedSymbol *asScopedSymbol();
+
+ void accept(TypeVisitor *visitor);
+ static void accept(Type *type, TypeVisitor *visitor);
+
+ virtual bool isEqualTo(const Type *other) const = 0;
+
+protected:
+ virtual void accept0(TypeVisitor *visitor) = 0;
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_TYPE_H
diff --git a/src/shared/cplusplus/TypeVisitor.cpp b/src/shared/cplusplus/TypeVisitor.cpp
new file mode 100644
index 0000000000..937080e5a5
--- /dev/null
+++ b/src/shared/cplusplus/TypeVisitor.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "TypeVisitor.h"
+#include "Type.h"
+
+CPLUSPLUS_BEGIN_NAMESPACE
+
+TypeVisitor::TypeVisitor()
+{ }
+
+TypeVisitor::~TypeVisitor()
+{ }
+
+void TypeVisitor::accept(Type *type)
+{ Type::accept(type, this); }
+
+CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h
new file mode 100644
index 0000000000..16fb37c4ad
--- /dev/null
+++ b/src/shared/cplusplus/TypeVisitor.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef CPLUSPLUS_TYPEVISITOR_H
+#define CPLUSPLUS_TYPEVISITOR_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+CPLUSPLUS_BEGIN_HEADER
+CPLUSPLUS_BEGIN_NAMESPACE
+
+class CPLUSPLUS_EXPORT TypeVisitor
+{
+ TypeVisitor(const TypeVisitor &other);
+ void operator =(const TypeVisitor &other);
+
+public:
+ TypeVisitor();
+ virtual ~TypeVisitor();
+
+ void accept(Type *type);
+
+ virtual bool preVisit(Type *) { return true; }
+ virtual void postVisit(Type *) {}
+
+ virtual void visit(VoidType *) {}
+ virtual void visit(IntegerType *) {}
+ virtual void visit(FloatType *) {}
+ virtual void visit(PointerToMemberType *) {}
+ virtual void visit(PointerType *) {}
+ virtual void visit(ReferenceType *) {}
+ virtual void visit(ArrayType *) {}
+ virtual void visit(NamedType *) {}
+ virtual void visit(Function *) {}
+ virtual void visit(Namespace *) {}
+ virtual void visit(Class *) {}
+ virtual void visit(Enum *) {}
+};
+
+CPLUSPLUS_END_NAMESPACE
+CPLUSPLUS_END_HEADER
+
+#endif // CPLUSPLUS_TYPEVISITOR_H
diff --git a/src/shared/cplusplus/cplusplus.pri b/src/shared/cplusplus/cplusplus.pri
new file mode 100644
index 0000000000..041aff67be
--- /dev/null
+++ b/src/shared/cplusplus/cplusplus.pri
@@ -0,0 +1,77 @@
+
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/AST.h \
+ $$PWD/ASTVisitor.h \
+ $$PWD/ASTfwd.h \
+ $$PWD/Array.h \
+ $$PWD/CPlusPlusForwardDeclarations.h \
+ $$PWD/CheckDeclaration.h \
+ $$PWD/CheckDeclarator.h \
+ $$PWD/CheckExpression.h \
+ $$PWD/CheckName.h \
+ $$PWD/CheckSpecifier.h \
+ $$PWD/CheckStatement.h \
+ $$PWD/Control.h \
+ $$PWD/CoreTypes.h \
+ $$PWD/DiagnosticClient.h \
+ $$PWD/FullySpecifiedType.h \
+ $$PWD/Lexer.h \
+ $$PWD/LiteralTable.h \
+ $$PWD/Literals.h \
+ $$PWD/MemoryPool.h \
+ $$PWD/Name.h \
+ $$PWD/NameVisitor.h \
+ $$PWD/Names.h \
+ $$PWD/Parser.h \
+ $$PWD/Scope.h \
+ $$PWD/Semantic.h \
+ $$PWD/SemanticCheck.h \
+ $$PWD/Symbol.h \
+ $$PWD/Symbols.h \
+ $$PWD/SymbolVisitor.h \
+ $$PWD/Token.h \
+ $$PWD/TranslationUnit.h \
+ $$PWD/Type.h \
+ $$PWD/TypeVisitor.h \
+ $$PWD/PrettyPrinter.h
+
+
+SOURCES += \
+ $$PWD/AST.cpp \
+ $$PWD/ASTVisitor.cpp \
+ $$PWD/Array.cpp \
+ $$PWD/CheckDeclaration.cpp \
+ $$PWD/CheckDeclarator.cpp \
+ $$PWD/CheckExpression.cpp \
+ $$PWD/CheckName.cpp \
+ $$PWD/CheckSpecifier.cpp \
+ $$PWD/CheckStatement.cpp \
+ $$PWD/Control.cpp \
+ $$PWD/CoreTypes.cpp \
+ $$PWD/DiagnosticClient.cpp \
+ $$PWD/FullySpecifiedType.cpp \
+ $$PWD/Keywords.cpp \
+ $$PWD/ObjectiveCAtKeywords.cpp \
+ $$PWD/Lexer.cpp \
+ $$PWD/LiteralTable.cpp \
+ $$PWD/Literals.cpp \
+ $$PWD/MemoryPool.cpp \
+ $$PWD/Name.cpp \
+ $$PWD/NameVisitor.cpp \
+ $$PWD/Names.cpp \
+ $$PWD/Parser.cpp \
+ $$PWD/Scope.cpp \
+ $$PWD/Semantic.cpp \
+ $$PWD/SemanticCheck.cpp \
+ $$PWD/Symbol.cpp \
+ $$PWD/Symbols.cpp \
+ $$PWD/SymbolVisitor.cpp \
+ $$PWD/Token.cpp \
+ $$PWD/TranslationUnit.cpp \
+ $$PWD/Type.cpp \
+ $$PWD/TypeVisitor.cpp \
+ $$PWD/PrettyPrinter.cpp
+