tools/porting/src/semantic.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/porting/src/semantic.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1227 @@
+/****************************************************************************
+**
+** Copyright (C) 2001-2004 Roberto Raggi
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "smallobject.h"
+#include "tokenengine.h"
+#include "semantic.h"
+#include <QtDebug>
+#include <QString>
+#include <QRegExp>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenStreamAdapter;
+using namespace TokenEngine;
+using namespace CodeModel;
+
+Semantic::Semantic(CodeModel::NamespaceScope *globalScope,
+                   TokenStreamAdapter::TokenStream *tokenStream,
+                   TypedPool<CodeModel::Item> *storage)
+{
+    m_storage = storage;
+    m_tokenStream = tokenStream;
+
+    m_currentAccess = CodeModel::Member::Public;
+    m_inSlots = false;
+    m_inSignals = false;
+    m_inStorageSpec = false;
+    m_inTypedef = false;
+
+    globalScope->setName("::");
+    currentScope.push(globalScope);
+
+    //create global UnknownType and UnknownTypeMember
+    UnknownType *type = Create<UnknownType>(m_storage);
+    type->setName("__UnknownType");
+    globalScope->addType(type);
+    type->setParent(globalScope);
+
+    m_sharedUnknownMember = Create<TypeMember>(m_storage);
+    m_sharedUnknownMember->setNameToken(TokenRef());
+    m_sharedUnknownMember->setName("Unknown");
+    m_sharedUnknownMember->setType(type);
+    globalScope->addMember(m_sharedUnknownMember);
+    m_sharedUnknownMember->setParent(globalScope);
+
+}
+
+void Semantic::parseAST(TranslationUnitAST *node)
+{
+    TreeWalker::parseTranslationUnit(node);
+}
+
+
+void Semantic::parseLinkageSpecification(LinkageSpecificationAST *ast)
+{
+    if(!ast)
+        return;
+    int inStorageSpec = m_inStorageSpec;
+    m_inStorageSpec = true;
+    TreeWalker::parseLinkageSpecification(ast);
+    m_inStorageSpec = inStorageSpec;
+}
+
+void Semantic::parseNamespace(NamespaceAST *ast)
+{
+    CodeModel::NamespaceScope *parent = currentScope.top()->toNamespaceScope();
+    if(!parent->toNamespaceScope()) {
+        emit error("Error in Semantic::parseNamespace: parent scope was not a namespace");
+        return;
+    }
+
+    QByteArray nsName;
+    if (!ast->namespaceName() || textOf(ast->namespaceName()).isEmpty()){
+        nsName = "(__QT_ANON_NAMESPACE)";
+    } else {
+        nsName = textOf(ast->namespaceName());
+    }
+
+    CodeModel::NamespaceScope *namespaceScope = 0;
+
+    // Look up namespace scope in case it is already defined.
+    // (Unlike classes, C++ namespaces are "open" and can be added to.)
+    CodeModel::Scope *scope = parent->scopes().value(nsName);
+    if (scope)
+        namespaceScope = scope->toNamespaceScope();
+
+    // Create new namespace if not found.
+    if (!namespaceScope) {
+        namespaceScope = CodeModel::Create<CodeModel::NamespaceScope>(m_storage);
+        namespaceScope->setName(nsName);
+        parent->addScope(namespaceScope);
+
+        NamespaceMember *namespaceMember = Create<NamespaceMember>(m_storage);
+        namespaceMember->setNameToken(tokenRefFromAST(ast->namespaceName()));
+        namespaceMember->setName(nsName);
+        namespaceMember->setNamespaceScope(namespaceScope);
+        currentScope.top()->addMember(namespaceMember);
+        namespaceMember->setParent(currentScope.top());
+    }
+
+    currentScope.push(namespaceScope);
+    TreeWalker::parseNamespace(ast);
+    currentScope.pop();
+}
+
+void Semantic::parseClassSpecifier(ClassSpecifierAST *ast)
+{
+    if (!ast->name()){
+        return;
+    }
+
+    QByteArray kind = textOf(ast->classKey());
+    if (kind == "class")
+        m_currentAccess = CodeModel::Member::Private;
+    else // kind =="struct"
+        m_currentAccess = CodeModel::Member::Public;
+
+    QByteArray className = textOf(ast->name()->unqualifiedName());
+
+    //create ClassScope
+    CodeModel::ClassScope *klass = CodeModel::Create<CodeModel::ClassScope>(m_storage);
+    klass->setName(className);
+    currentScope.top()->addScope(klass);
+
+    //create ClassType
+    CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
+    type->setScope(klass);
+    currentScope.top()->addType(type);
+    type->setParent(currentScope.top());
+
+    //create TypeMember
+    CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+    typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
+    typeMember->setName(className);
+    typeMember->setType(type);
+    currentScope.top()->addMember(typeMember);
+    typeMember->setParent(currentScope.top());
+
+    currentScope.push(klass);
+    if (ast->baseClause())
+        parseBaseClause(ast->baseClause(), klass);
+
+    //TreeWalker::parseClassSpecifier(ast);
+    parseNode(ast->winDeclSpec());
+    parseNode(ast->classKey());
+    parseNode(ast->baseClause());
+
+    // Here's the trick for parsing c++ classes:
+    // All inline function definitions must be interpreted as if they were
+    // written after any other declarations in the class.
+    QList<DeclarationAST *> functionDefinitions;
+    if (ast->declarationList())
+        foreach(DeclarationAST *decl, *ast->declarationList()) {
+            if(decl->nodeType() == NodeType_FunctionDefinition)
+                functionDefinitions.append(decl);
+            else
+            parseNode(decl);
+        }
+    foreach(DeclarationAST *decl, functionDefinitions)
+        parseNode(decl);
+
+    currentScope.pop();
+}
+/*
+    Parse a class, struct or enum forward decalration.
+*/
+void Semantic::parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+    if (!node)
+        return;
+    AST *kind = node->kind();
+    if (!kind)
+        return;
+
+    const QByteArray kindText = textOf(kind);
+    const QByteArray nameText = textOf(node->name());
+
+    // Don't do anything if the class, struct or enum has already been declared or defined.
+    if (lookupNameInScope(currentScope.top(), node->name()).count() > 0)
+        return;
+
+    if (kindText == "class" || kindText == "struct") {
+        // Create ClassType.
+        CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
+        type->setScope(0);
+        currentScope.top()->addType(type);
+        type->setParent(currentScope.top());
+
+        // Create TypeMember.
+        CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+        typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
+        typeMember->setName(nameText);
+        typeMember->setType(type);
+        currentScope.top()->addMember(typeMember);
+        typeMember->setParent(currentScope.top());
+    } else if (kindText == "enum") {
+        //create a Type
+        CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
+        enumType->setName(nameText);
+        currentScope.top()->addType(enumType);
+        enumType->setParent(currentScope.top());
+
+        //create a TypeMember
+        CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+        if(node->name())
+            typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
+        typeMember->setName(nameText);
+        typeMember->setType(enumType);
+        currentScope.top()->addMember(typeMember);
+        typeMember->setParent(currentScope.top());
+    }
+}
+
+void Semantic::parseSimpleDeclaration(SimpleDeclarationAST *ast)
+{
+    TypeSpecifierAST *typeSpec = ast->typeSpec();
+    InitDeclaratorListAST *declarators = ast->initDeclaratorList();
+
+    if (typeSpec)
+        parseTypeSpecifier(typeSpec);
+
+    if (declarators){
+        List<InitDeclaratorAST*> l = *declarators->initDeclaratorList();
+
+        foreach (InitDeclaratorAST *current, l) {
+            parseDeclaration(ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, current);
+        }
+    }
+}
+
+void Semantic::parseDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl)
+{
+    if (m_inStorageSpec)
+            return;
+
+    if(!decl)
+        return;
+
+    DeclaratorAST *d = decl->declarator();
+    if (!d)
+        return;
+
+    if (!d->subDeclarator() && d->parameterDeclarationClause()) {
+        parseFunctionDeclaration(funSpec, storageSpec, typeSpec, decl);
+		return;
+	}
+    if(!typeSpec || !typeSpec->name())
+        return;
+
+    DeclaratorAST *t = d;
+    while (t && t->subDeclarator())
+        t = t->subDeclarator();
+
+    QByteArray id;
+    if (t && t->declaratorId() && t->declaratorId()->unqualifiedName())
+        id = textOf(t->declaratorId()->unqualifiedName());
+
+    if (!t || !t->declaratorId() || !t->declaratorId()->unqualifiedName())
+        return;
+    AST *nameAST = t->declaratorId()->unqualifiedName();
+    QByteArray name = textOf(nameAST);
+
+
+    if (!scopeOfDeclarator(d, QList<QByteArray>()).isEmpty()){
+        return;
+    }
+
+    //Check if this is possibly a function call by searching for '(' and ')'
+    const QByteArray declText = textOf(decl);
+    if (declText.contains("(") && declText.contains(")")) {
+	if (decl->declarator() && decl->declarator()->subDeclarator()) {
+
+        NameAST * name = decl->declarator()->subDeclarator()->declaratorId();
+	if (name)
+            parseNameUse(name);
+	    return;	
+        } 
+    }
+
+    //create VariableMember
+    CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+    variableMember->setNameToken(tokenRefFromAST(nameAST));
+    variableMember->setName(name);
+    variableMember->setAccess(m_currentAccess);
+    variableMember->setParent(currentScope.top());
+    currentScope.top()->addMember(variableMember);
+
+    //look up type of variableMember,
+
+    TypeMember *typeMember = typeLookup(currentScope.top(), typeSpec->name());
+    if(typeMember) {
+        variableMember->setType(typeMember->type());
+    } else {
+        QByteArray text = typeOfDeclaration(typeSpec, d);
+        CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+        type->setName(text);
+        variableMember->setType(type);
+    }
+
+    if (decl)
+        parseNode(decl->initializer());
+
+}
+
+void Semantic::parseFunctionDeclaration(AST *funSpec, AST *storageSpec,
+                                        TypeSpecifierAST * typeSpec, InitDeclaratorAST * initDeclarator)
+{
+    bool isFriend = false;
+    bool isVirtual = false;
+    bool isStatic = false;
+    bool isInline = false;
+    bool isPure = initDeclarator->initializer() != 0;
+
+    if (funSpec){
+        List<AST*> l = *funSpec->children();
+        foreach (AST *current, l) {
+            QByteArray text = textOf(current);
+            if (text == "virtual") isVirtual = true;
+            else if (text == "inline") isInline = true;
+        }
+    }
+
+    if (storageSpec){
+        List<AST*> l = *storageSpec->children();
+        foreach (AST *current, l) {
+            QByteArray text = textOf(current);
+            if (text == "friend") isFriend = true;
+            else if (text == "static") isStatic = true;
+        }
+    }
+    DeclaratorAST *declarator = initDeclarator->declarator();
+    if(!declarator || !declarator->declaratorId())
+        return;
+    AST *nameAST = declarator->declaratorId()->unqualifiedName();
+    QByteArray name = textOf(nameAST);
+
+    CodeModel::FunctionMember *method = CodeModel::Create<CodeModel::FunctionMember>(m_storage);
+    method->setNameToken(tokenRefFromAST(nameAST));
+    method->setName(name);
+    method->setAccess(m_currentAccess);
+    method->setStatic(isStatic);
+    method->setVirtual(isVirtual);
+    method->setAbstract(isPure);
+
+    parseFunctionArguments(declarator, method);
+
+    if (m_inSignals)
+        method->setSignal(true);
+
+    if (m_inSlots)
+        method->setSlot(true);
+
+    method->setConstant(declarator->constant() != 0);
+
+    QByteArray text = typeOfDeclaration(typeSpec, declarator);
+    if (!text.isEmpty()) {
+        CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+        type->setName(text);
+        method->setReturnType(type);
+    }
+
+    method->setParent(currentScope.top());
+    currentScope.top()->addMember(method);
+}
+
+
+void Semantic::parseBaseClause(BaseClauseAST * baseClause, CodeModel::ClassScope *klass)
+{
+    if(!baseClause)
+        return;
+    if(!klass)
+        return;
+    List<BaseSpecifierAST*> *l = baseClause->baseSpecifierList();
+    if (!l)
+        return;
+    foreach (BaseSpecifierAST *baseSpecifier, *l) {
+        QByteArray baseName;
+        if (!baseSpecifier->name())
+            continue;
+
+        // Look up a class with the correct name.
+        QList<Member *> candidates = nameLookup(klass, baseSpecifier->name());
+        if (candidates.count() == 1 ) {
+            Member *member = candidates.at(0);
+            Q_ASSERT(member);
+            TypeMember *typeMember = member->toTypeMember();
+            if (typeMember) {
+                Q_ASSERT(typeMember->type());
+                ClassType *classType = typeMember->type()->toClassType();
+                if (classType) {
+                    klass->addBaseClass(classType);
+                }
+            }
+        }
+    }
+}
+void Semantic::parseFunctionArguments(const DeclaratorAST *declarator, CodeModel::FunctionMember *method)
+{
+    if(!declarator || !method)
+        return;
+
+    ParameterDeclarationClauseAST *clause = declarator->parameterDeclarationClause();
+
+    if (clause && clause->parameterDeclarationList()){
+        ParameterDeclarationListAST *params = clause->parameterDeclarationList();
+        List<ParameterDeclarationAST*> *l = params->parameterList();
+        if (!l)
+            return;
+        foreach (ParameterDeclarationAST *param, *l) {
+            CodeModel::Argument *arg = CodeModel::Create<CodeModel::Argument>(m_storage);
+            arg->setParent(method);
+
+            if (param->declarator()){
+                QByteArray text = declaratorToString(param->declarator(), QByteArray(), true);
+                if(param->declarator()->declaratorId())
+                    arg->setNameToken(tokenRefFromAST(param->declarator()->declaratorId()->unqualifiedName()));
+                if (!text.isEmpty())
+                    arg->setName(text);
+            }
+
+            QByteArray tp = typeOfDeclaration(param->typeSpec(), param->declarator());
+            if (!tp.isEmpty()) {
+                CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+                type->setName(tp);
+                arg->setType(type);
+            }
+
+            method->addArgument(arg);
+        }
+    }
+}
+
+// using directive (using namespace A)
+void Semantic::parseUsingDirective(UsingDirectiveAST *ast)
+{
+    QByteArray qualifiedname = textOf(ast->name());
+    QByteArray name = textOf(ast->name()->unqualifiedName());
+
+    //look up target namespace name
+    QList<Member *> memberList = nameLookup(currentScope.top(), ast->name());
+
+    NamespaceScope *targetNamespace = 0;
+
+    // search for namespace in member list.
+    QList<Member *>::ConstIterator it = memberList.constBegin();
+    while(it != memberList.constEnd()) {
+        if (NamespaceMember *namespaceMember = (*it)->toNamespaceMember()) {
+            targetNamespace = namespaceMember->namespaceScope();
+            break;
+        }
+        ++it;
+    }
+
+    if (targetNamespace == 0)
+        return;
+
+    // Find the insertion namespace, which is the first common
+    // ancesotor namespace for the current scope and the target namespace
+
+    // currentScope might be a block scope, find its first namespace parent
+    CodeModel::Scope *currentParent = currentScope.top();
+    while (currentParent->toNamespaceScope() == 0) {
+        currentParent = currentParent->parent();
+    }
+
+    CodeModel::Scope *namespaceA = currentParent;
+    while (namespaceA != 0) {
+        CodeModel::Scope *namespaceB = targetNamespace;
+        while (namespaceB != 0) {
+            if (namespaceB == namespaceA)
+                break;
+            namespaceB = namespaceB->parent();
+        }
+        if (namespaceB == namespaceA)
+            break;
+        namespaceA = namespaceA->parent();
+    }
+
+    if (namespaceA == 0 || namespaceA->toNamespaceScope() == 0)
+        return;
+
+    NamespaceScope *insertionNamespace = namespaceA->toNamespaceScope();
+
+    // Create using directive link
+    UsingDirectiveLink *usingDirectiveLink = Create<UsingDirectiveLink>(m_storage);
+    usingDirectiveLink->setParent(currentScope.top());
+    usingDirectiveLink->setTargetNamespace(targetNamespace);
+    usingDirectiveLink->setInsertionNamespace(insertionNamespace);
+
+    // add it to current namespace
+    if (NamespaceScope *namespaceScope = currentScope.top()->toNamespaceScope())
+        namespaceScope->addUsingDirectiveLink(usingDirectiveLink);
+    else if (BlockScope *blockScope = currentScope.top()->toBlockScope())
+        blockScope->addUsingDirectiveLink(usingDirectiveLink);
+}
+
+void Semantic::parseFunctionDefinition(FunctionDefinitionAST *ast)
+{
+    AST *funSpec = ast->functionSpecifier();
+    AST *storageSpec = ast->storageSpecifier();
+    TypeSpecifierAST *typeSpec = ast->typeSpec();
+    InitDeclaratorAST *initDeclarator = ast->initDeclarator();
+    if (!ast->initDeclarator())
+        return;
+
+    DeclaratorAST *d = initDeclarator->declarator();
+
+    if (!d->declaratorId())
+        return;
+
+    parseFunctionDeclaration(funSpec, storageSpec, typeSpec, initDeclarator);
+    CodeModel::FunctionMember *method = functionLookup(currentScope.top(), d);
+
+    if(!method) {
+        emit error("Error in Semantic::parseFunctionDefinition: Could not find declaration for function definition");
+        return;
+    }
+
+    CodeModel::Scope *parent = method->parent();
+
+    if(!ast->functionBody()) {
+        emit error("Error in Semantic::parseFunctionDefinition: no function body in function definition");
+        return;
+    }
+
+    //create child function scope
+    QByteArray id = textOf(d->declaratorId()->unqualifiedName());
+    CodeModel::BlockScope *functionScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
+    functionScope->setName(QByteArray("__QT_ANON_BLOCK_SCOPE(Function: ") + id + QByteArray(")"));
+    functionScope->setParent(parent);
+    method->setFunctionBodyScope(functionScope);
+
+    //add arguments to child scope
+     ArgumentCollection arguments = method->arguments();
+     ArgumentCollection::ConstIterator it = arguments.constBegin();
+     while(it != arguments.constEnd()) {
+         CodeModel::Argument *argument = *it;
+         CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+         variableMember->setNameToken(argument->nameToken());
+         variableMember->setType(argument->type());
+         variableMember->setName(argument->name());
+         variableMember->setParent(functionScope);
+         functionScope->addMember(variableMember);
+         ++it;
+     }
+
+    //push function scope and parse function body
+    currentScope.push(functionScope);
+    parseStatementList(ast->functionBody());
+    currentScope.pop();
+}
+
+void Semantic::parseStatementList(StatementListAST *statemenList)
+{
+    if(!statemenList)
+        return;
+    CodeModel::BlockScope *blockScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
+    blockScope->setName("__QT_ANON_BLOCK_SCOPE");
+    blockScope->setParent(currentScope.top());
+    currentScope.top()->addScope(blockScope);
+
+    currentScope.push(blockScope);
+    TreeWalker::parseStatementList(statemenList);
+    currentScope.pop();
+}
+
+void Semantic::parseExpression(AbstractExpressionAST* node)
+{
+    if(!node)
+        return;
+    if(node->nodeType() == NodeType_ClassMemberAccess)
+        parseClassMemberAccess(static_cast<ClassMemberAccessAST *>(node));
+    else
+        TreeWalker::parseExpression(node);
+}
+
+/*
+    Pretty hardwired code for handling class member access of the types:
+    object.member and objectPtr->member.
+
+    This function creates a name use for object to its declaration, and a
+    name use from member to its declaration in the class.
+*/
+void Semantic::parseClassMemberAccess(ClassMemberAccessAST *node)
+{
+    if(!node)
+        return;
+    parseExpression(node->expression());
+    // Get a name use for the 'object' name.
+    NameUse *nameUse = findNameUse(node->expression());
+    // Since the NameUse refers to an object, its decalaration must be
+    // a ClassType. Get the scope of this class type.
+    if(    nameUse
+        && nameUse->declaration()
+        && nameUse->declaration()->toVariableMember()
+        && nameUse->declaration()->toVariableMember()->type()
+        && nameUse->declaration()->toVariableMember()->type()->toClassType()
+        && nameUse->declaration()->toVariableMember()->type()->toClassType()->scope())   {
+
+        CodeModel::Scope *scope = nameUse->declaration()->toVariableMember()->type()->toClassType()->scope();
+        QList<CodeModel::Member *> members = lookupNameInScope(scope, node->name());
+            if(members.count() != 0) {
+                createNameUse(members.at(0), node->name());
+                return;
+            }
+    }
+    // Create a NameUse that refers to the global shared unknown type.
+    createNameUse(m_sharedUnknownMember, node->name());
+}
+
+void Semantic::parseExpressionStatement(ExpressionStatementAST *node)
+{
+    TreeWalker::parseExpressionStatement(node);
+}
+
+// using declaration (using A::b)
+void Semantic::parseUsing(UsingAST *ast)
+{
+    //CodeModel::Scope *s = lookUpScope(currentScope.top(), ast->name());
+    QList<CodeModel::Member *> members = nameLookup(currentScope.top(), ast->name());
+    if(members.isEmpty()) {
+        emit error("Error in Semantic::parseUsing: could not look up using target");
+        return;
+    }
+    //TODO: handle multiple members (when nameLookup returns a set of overloded functions)
+    CodeModel::Member *member = members[0];
+    CodeModel::Scope *targetScope = member->parent();
+    if(!targetScope) {
+        emit error("Error in Semantic::parseUsing: target has no parent scope");
+        return;
+    }
+
+    if(!ast->name())
+        return;
+    AST *nameAST = ast->name()->unqualifiedName();
+    if(!nameAST)
+        return;
+    QByteArray name = textOf(nameAST);
+}
+
+void Semantic::parseEnumSpecifier(EnumSpecifierAST *ast)
+{
+    if (!ast->name())
+         return;
+
+    QByteArray name = textOf(ast->name());
+
+    //create a Type
+    CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
+    enumType->setName(name);
+    currentScope.top()->addType(enumType);
+    enumType->setParent(currentScope.top());
+
+    //create a TypeMember
+    CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+    if(ast->name())
+        typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
+    typeMember->setName(name);
+    typeMember->setType(enumType);
+    currentScope.top()->addMember(typeMember);
+    typeMember->setParent(currentScope.top());
+
+    //parse the eneumerators
+    List<EnumeratorAST*> *list = ast->enumeratorList();
+    if (!list)
+        return;
+    foreach (EnumeratorAST *current, *list) {
+        CodeModel::VariableMember *enumerator = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+        enumerator->setNameToken(tokenRefFromAST(current->id()));
+        enumerator->setName(textOf(current->id()));
+        enumerator->setAccess(m_currentAccess);
+        enumerator->setStatic(true);
+        enumerator->setType(enumType);
+        currentScope.top()->addMember(enumerator);
+        enumerator->setParent(currentScope.top());
+    }
+
+}
+
+void Semantic::parseTypedef(TypedefAST *ast)
+{
+    TypeSpecifierAST *typeSpec = ast->typeSpec();
+    InitDeclaratorListAST *declarators = ast->initDeclaratorList();
+
+    if (typeSpec && declarators){
+        QByteArray typeId;
+
+        if (typeSpec->name())
+            typeId = textOf(typeSpec->name());
+
+        List<InitDeclaratorAST*> *l = declarators->initDeclaratorList();
+        if (!l)
+            return;
+        foreach (InitDeclaratorAST *initDecl, *l) {
+            QByteArray type, id;
+            if (initDecl->declarator()){
+               type = typeOfDeclaration(typeSpec, initDecl->declarator());
+
+               DeclaratorAST *d = initDecl->declarator();
+               while (d->subDeclarator()){
+                   d = d->subDeclarator();
+               }
+
+               if (d->declaratorId())
+                  id = textOf(d->declaratorId());
+            }
+
+            //create a type
+            CodeModel::Scope *scope = currentScope.top();
+            CodeModel::AliasType *typeAlias = CodeModel::Create<CodeModel::AliasType>(m_storage);
+            //typeAlias->setName(id);
+            //typeAlias->setParent(scope);
+            scope->addType(typeAlias);
+
+            //create a TypeMember
+            CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+            if(typeSpec->name())
+                typeMember->setNameToken(tokenRefFromAST(typeSpec->name()->unqualifiedName()));
+            typeMember->setName(id);
+            typeMember->setType(typeAlias);
+            currentScope.top()->addMember(typeMember);
+            typeMember->setParent(currentScope.top());
+
+        }
+
+    }
+}
+
+void Semantic::parseTypeSpecifier(TypeSpecifierAST *ast)
+{
+    // If this is a classSpecifier or a EnumSpecifier we skip the name lookup,
+    // becuase looking up the name "E" in a class definition like
+    // "class E { ..." makes no sense. (There might be a variable named E
+    // already declared, but that variable is now shadowed by the class type.)
+    if(   ast->nodeType() != NodeType_EnumSpecifier
+       && ast->nodeType() != NodeType_ClassSpecifier
+       && ast->nodeType() != NodeType_ElaboratedTypeSpecifier )
+        parseNameUse(ast->name());
+    TreeWalker::parseTypeSpecifier(ast);
+}
+
+/*
+    Parses a name: looks up name, creates name use.
+*/
+void Semantic::parseNameUse(NameAST* name)
+{
+    if(!name)
+        return;
+
+    // Look up name
+    QList<CodeModel::Member *> members = nameLookup(currentScope.top(), name);
+    if(members.isEmpty()) {
+        //cout << "no declaration found for " << textOf(name).constData() << endl;
+        // Create NameUse that refer to a shared UnknownMember
+        createNameUse(m_sharedUnknownMember, name);
+        return;
+    }
+
+    //TODO: handle multiple members (when nameLookup returns a set of overloaded functions)
+    CodeModel::Member *member = members[0];
+    if(!member->parent()) {
+        emit error("Error in Semantic::parseUsing: target has no parent scope");
+        return;
+    }
+
+    createNameUse(member, name);
+}
+
+/*
+    looks up name used in basescope. If name->isGlobal() is true or if classOrNamespaceList()
+    returns a non-emty list, the C++ qualified name lookup rules are used. Otherwise the
+    unquialified name lookup rules are used.  Returns the a list of members that was found,
+    In most cases this list will contain zero or one element, exept in the case of overloaded functions.
+    TODO: Argument-dependent name lookup
+*/
+QList<CodeModel::Member *> Semantic::nameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+    if (name->isGlobal() || (name->classOrNamespaceNameList()
+                              && name->classOrNamespaceNameList()->size()>0 )) {
+        return qualifiedNameLookup(baseScope, name);
+    } else {
+        return unqualifiedNameLookup(baseScope, name);
+    }
+}
+
+//look up an unqualified name
+QList<CodeModel::Member *> Semantic::unqualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+    QList<UsingDirectiveLink *> usingDirectiveLinks;
+    CodeModel::Scope *currentScope = baseScope;
+    QList<CodeModel::Member *>  entities;
+
+    while (currentScope != 0) {
+        // Add any "using namespace" directive links for the current scope to
+        // usingDirectiveLinks
+        if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope())
+            usingDirectiveLinks += namespaceScope->usingDirectiveLinks();
+        if (BlockScope *blockScope = currentScope->toBlockScope())
+            usingDirectiveLinks += blockScope->usingDirectiveLinks();
+
+        // Search usingDirectiveLinks for a link where currentScope is the
+        // insertion namespace. If found look up name in the target namespace
+        // for that link.
+        if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope()) {
+            QList<UsingDirectiveLink *>::ConstIterator it = usingDirectiveLinks.constBegin();
+            while (it != usingDirectiveLinks.constEnd()) {
+                if ((*it)->insertionNamespace() == namespaceScope)
+                    entities = lookupNameInScope((*it)->targetNamespace(), name);
+                ++it;
+            }
+        }
+
+        // Look up names in this scope.
+        entities += lookupNameInScope(currentScope, name);
+        if (!entities.isEmpty())
+            break;
+        currentScope = currentScope->parent();
+    }
+    return entities;
+}
+
+//look up a qualified name
+QList<CodeModel::Member *> Semantic::qualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+    QList<CodeModel::Member *> entities;
+    CodeModel::Scope *currentScope = baseScope;
+
+    // Check if the global ("::") scope has been specified.
+    if(name->isGlobal()) {
+        while (currentScope->parent())
+            currentScope = currentScope->parent();
+    }
+
+    while (entities.isEmpty() && currentScope != 0) {
+        CodeModel::Scope *targetScope = scopeLookup(currentScope, name);
+        entities = lookupNameInScope(targetScope, name);
+        currentScope = currentScope->parent();
+    }
+
+    return entities;
+}
+
+//looks up a name in a scope, includes base classes if scope is a class scope
+QList<CodeModel::Member *> Semantic::lookupNameInScope(CodeModel::Scope *scope, const NameAST* name)
+{
+    QList<CodeModel::Member *> entities;
+
+    if(!scope || !name)
+        return entities;
+
+    QByteArray nameText = textOf(name->unqualifiedName()->name());
+    //look up name in members of current scope
+    const CodeModel::MemberCollection members = scope->members();
+    if (members.contains(nameText))
+        entities.append(members.value(nameText));
+
+    // if not found, look up name in  base classes (if any)
+    CodeModel::ClassScope *classScope = scope->toClassScope();
+    if (entities.isEmpty() && classScope) {
+        const TypeCollection baseClasses = classScope->baseClasses();
+        TypeCollection::ConstIterator it = baseClasses.constBegin();
+        while (it != baseClasses.constEnd()) {
+            CodeModel::Scope *baseClass = it.value()->toClassType()->scope();
+            if (scope != baseClass)
+                entities += lookupNameInScope(baseClass, name);
+            ++it;
+        }
+
+        if (entities.count() > 1)
+            emit error("Error in Semantic::lookupNameInScope: name "
+            + nameText + " is ambigous");
+    }
+    return entities;
+}
+
+/*
+    Resolves the classOrNamespaceNameList part of a NameAST against a base scope.
+*/
+CodeModel::Scope *Semantic::scopeLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+    CodeModel::Scope *currentScope = baseScope;
+    const List<ClassOrNamespaceNameAST *> *scopeList = name->classOrNamespaceNameList();
+    // if there is no scope list, then the scope we are looking for is baseScope
+    if (!scopeList)
+        return baseScope;
+
+    // Check if the global ("::") scope has been specified.
+    if(name->isGlobal()) {
+        while (currentScope->parent())
+            currentScope = currentScope->parent();
+    }
+
+    while(currentScope != 0) {
+        int nestingCounter = 0;
+        CodeModel::Scope *nestedScope = currentScope;
+        while (nestingCounter < scopeList->count()) {
+            const QByteArray nameText = textOf((*scopeList)[nestingCounter]->name());
+            nestedScope = nestedScope->scopes().value(nameText);
+            if (!nestedScope)
+                break;
+            ++nestingCounter;
+        }
+        if(nestedScope) // found target scope?
+            return nestedScope;
+
+        currentScope = currentScope->parent(); //look in parent scope
+    }
+
+    return 0;
+}
+
+TypeMember *Semantic::typeLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+    QList<CodeModel::Member *> memberList = nameLookup(baseScope, name);
+
+    foreach(Member *member, memberList) {
+        if(TypeMember *typeMember = member->toTypeMember())
+            return typeMember;
+    }
+    return 0;
+}
+
+FunctionMember *Semantic::functionLookup(CodeModel::Scope *baseScope,
+                                          const DeclaratorAST *functionDeclarator)
+{
+
+    QList<CodeModel::Member*> candidateList =
+                nameLookup(baseScope, functionDeclarator->declaratorId());
+    return selectFunction(candidateList, functionDeclarator);
+}
+
+/*
+    This is a simplified function lookup routine, for matching member function
+    definitions with member function declarations. It does not implement
+    the general C++ function overload resolution rules.
+*/
+FunctionMember *Semantic::selectFunction(QList<CodeModel::Member*> candidatateList, const DeclaratorAST *functionDeclarator)
+{
+    // get arguments for funciton we are looking for
+    FunctionMember testFunction;
+    parseFunctionArguments(functionDeclarator, &testFunction);
+    const ArgumentCollection testArgumentCollection = testFunction.arguments();
+
+    //test againts functions in overload list.
+    foreach(Member* member, candidatateList) {
+        FunctionMember *function = member->toFunctionMember();
+        if (!function)
+            continue;
+        const ArgumentCollection argumentCollection = function->arguments();
+
+        //test argument types and number of arguments
+        ArgumentCollection::ConstIterator arg1 = argumentCollection.constBegin();
+        ArgumentCollection::ConstIterator arg2 = testArgumentCollection.constBegin();
+        bool match = true;
+        while(arg1 != argumentCollection.constEnd() && arg2 != testArgumentCollection.constEnd()) {
+            if( arg1.value()->type()->name() != arg2.value()->type()->name() ) {
+                match = false;
+                break;
+            }
+            ++arg1;
+            ++arg2;
+        }
+        if(match)
+            return function;
+    }
+    return 0;
+}
+
+QByteArray Semantic::typeOfDeclaration(TypeSpecifierAST *typeSpec, DeclaratorAST *declarator)
+{
+    if (!typeSpec)
+        return QByteArray();
+
+    QByteArray text;
+
+    if (typeSpec->cvQualify()) {
+        List<AST*> cv = *typeSpec->cvQualify()->children();
+        foreach (AST *current, cv) {
+            text += " " + textOf(current);
+        }
+        text += " ";
+    }
+
+
+    text += textOf(typeSpec);
+
+    if (typeSpec->cv2Qualify()) {
+        List<AST*> cv = *typeSpec->cv2Qualify()->children();
+        foreach (AST *current, cv) {
+            text += textOf(current) + " ";
+        }
+    }
+
+    if (declarator && declarator->ptrOpList()) {
+        List<AST*> ptrOpList = *declarator->ptrOpList();
+        foreach (AST *current, ptrOpList) {
+            text += " " + textOf(current);
+        }
+        text += " ";
+    }
+
+    return text.trimmed().simplified();
+}
+
+
+
+QList<QByteArray> Semantic::scopeOfName(NameAST *id, const QList<QByteArray>& startScope)
+{
+    QList<QByteArray> scope = startScope;
+    if (id && id->classOrNamespaceNameList()){
+        if (id->isGlobal())
+            scope.clear();
+
+        List<ClassOrNamespaceNameAST*> l = *id->classOrNamespaceNameList();
+        foreach (ClassOrNamespaceNameAST *current, l) {
+            if (current->name())
+               scope << textOf(current->name());
+        }
+    }
+
+    return scope;
+}
+
+QList<QByteArray> Semantic::scopeOfDeclarator(DeclaratorAST *d, const QList<QByteArray>& startScope)
+{
+    if(!d)
+        return QList<QByteArray>();
+    return scopeOfName(d->declaratorId(), startScope);
+}
+
+QByteArray Semantic::typeSpecToString(TypeSpecifierAST* typeSpec)
+{
+    if (!typeSpec)
+        return QByteArray();
+
+    QByteArray tp;
+    if (typeSpec->cvQualify()) {
+        tp += "const ";
+    }
+
+    tp += (QString::fromLatin1(textOf(typeSpec)).replace(QRegExp(QLatin1String(" :: ")), QString::fromUtf8("::"))).toLatin1();
+    return tp;
+}
+
+QByteArray Semantic::declaratorToString(DeclaratorAST* declarator, const QByteArray& scope, bool skipPtrOp)
+{
+    if (!declarator)
+        return QByteArray();
+
+    QByteArray text;
+
+    if (!skipPtrOp && declarator->ptrOpList()){
+        List<AST*> ptrOpList = *declarator->ptrOpList();
+        foreach (AST *current, ptrOpList) {
+            text += textOf(current);
+        }
+        text += QByteArray(" ");
+    }
+
+    text += scope;
+
+    if (declarator->subDeclarator())
+        text += QByteArray("(") + declaratorToString(declarator->subDeclarator()) + QByteArray(")");
+
+    if (declarator->declaratorId())
+        text += textOf(declarator->declaratorId());
+
+    if (declarator->arrayDimensionList()) {
+        List<AST*> arrays = *declarator->arrayDimensionList();
+        foreach (AST *current, arrays) {
+            current=current;    //silence unused symbol warning
+            text += QByteArray("[]");
+        }
+    }
+
+    if (declarator->parameterDeclarationClause()){
+        text += QByteArray("(");
+
+        ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
+        if (l != 0){
+            List<ParameterDeclarationAST*> params = *l->parameterList();
+            foreach (ParameterDeclarationAST *current, params) {
+                QByteArray type = typeSpecToString(current->typeSpec());
+                text += type;
+                if (!type.isEmpty())
+                    text += QByteArray(" ");
+                text += declaratorToString(current->declarator());
+
+                // ### FIXME if (it.current())
+                    text += QByteArray(", ");
+            }
+        }
+
+        text += QByteArray(")");
+
+        if (declarator->constant() != 0)
+            text += QByteArray(" const");
+    }
+
+    return QString::fromLatin1(text).replace(QRegExp(QLatin1String(" :: ")), QLatin1String("::")).simplified().toLatin1();
+}
+
+QByteArray Semantic::textOf(const AST *node) const
+{
+    if (!node)
+        return QByteArray();
+    QByteArray text;
+    for (int i = node->startToken(); i < node->endToken(); ++i) {
+        if (!m_tokenStream->isHidden(i)) {
+            if (i != node->startToken())
+                text += QByteArray(" ");
+            text += m_tokenStream->tokenText(i);
+        }
+    }
+    return text;
+}
+
+void Semantic::createNameUse(Member *member, NameAST *name)
+{
+    if (!name)
+       return;
+
+    AST *unqualifedName = name->unqualifiedName()->name();
+
+    if(!unqualifedName || !member)
+        return;
+
+    CodeModel::NameUse *nameUse = CodeModel::Create<CodeModel::NameUse>(m_storage);
+    nameUse->setParent(currentScope.top());
+    nameUse->setNameToken(tokenRefFromAST(unqualifedName));
+    nameUse->setName(textOf(unqualifedName));
+    nameUse->setDeclaration(member);
+
+    currentScope.top()->addNameUse(nameUse);
+    addNameUse(unqualifedName, nameUse);
+}
+
+void Semantic::addNameUse(AST *node, NameUse *nameUse)
+{
+    const int tokenIndex = node->startToken();
+    m_nameUses.insert(tokenIndex, nameUse);
+}
+
+/*
+    Searches a AST node and all its children for a nameUse. The name use is
+    found by looking up each node's tokens in the m_nameUses map. A depth-first
+    search is used.
+*/
+NameUse *Semantic::findNameUse(AST *node)
+{
+    if(!node)
+        return 0;
+
+    List<AST*> *children = node->children();
+    if(children) {
+        NameUse *nameUse = 0;
+        foreach(AST* child , *children) {
+            nameUse = findNameUse(child);
+            if(nameUse)
+                break;
+        }
+        if (nameUse)
+            return nameUse;
+    }
+
+    for (int t = node->startToken(); t < node->endToken(); ++t) {
+ //       cout << t <<" |" <<m_tokenStream->tokenText(t).constData() << "|" << endl;
+        if (m_nameUses.contains(t))
+            return m_nameUses.value(t);
+    }
+    return 0;
+}
+
+/*
+    Gets a TokenRef from an AST node.
+    Assumes that the node only covers one token, which means that
+    node->statToken() == node->endToken(). If this is not the case
+    then the TokenRef will reference the token at startToken.
+*/
+TokenEngine::TokenRef Semantic::tokenRefFromAST(AST *node)
+{
+    const int startTokenIndex = node->startToken();
+    const TokenEngine::TokenContainer tokenContainer = m_tokenStream->tokenContainer(startTokenIndex);
+    const int containerIndex = m_tokenStream->containerIndex(startTokenIndex);
+    return TokenEngine::TokenRef(tokenContainer, containerIndex);
+}
+
+QT_END_NAMESPACE