forked from qt-creator/qt-creator
		
	Deprecate the old template instantiation.
This commit is contained in:
		
							
								
								
									
										405
									
								
								src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,405 @@
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** This file is part of Qt Creator
 | 
			
		||||
**
 | 
			
		||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
 | 
			
		||||
**
 | 
			
		||||
** Contact: Nokia Corporation (qt-info@nokia.com)
 | 
			
		||||
**
 | 
			
		||||
** Commercial Usage
 | 
			
		||||
**
 | 
			
		||||
** Licensees holding valid Qt Commercial licenses may use this file in
 | 
			
		||||
** accordance with the Qt Commercial License Agreement provided with the
 | 
			
		||||
** Software or, alternatively, in accordance with the terms contained in
 | 
			
		||||
** a written agreement between you and Nokia.
 | 
			
		||||
**
 | 
			
		||||
** GNU Lesser General Public License Usage
 | 
			
		||||
**
 | 
			
		||||
** Alternatively, this file may be used under the terms of the GNU Lesser
 | 
			
		||||
** General Public License version 2.1 as published by the Free Software
 | 
			
		||||
** Foundation and appearing in the file LICENSE.LGPL included in the
 | 
			
		||||
** packaging of this file.  Please review the following information to
 | 
			
		||||
** ensure the GNU Lesser General Public License version 2.1 requirements
 | 
			
		||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
			
		||||
**
 | 
			
		||||
** If you are unsure which license is appropriate for your use, please
 | 
			
		||||
** contact the sales department at http://qt.nokia.com/contact.
 | 
			
		||||
**
 | 
			
		||||
**************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "DeprecatedGenTemplateInstance.h"
 | 
			
		||||
#include "Overview.h"
 | 
			
		||||
 | 
			
		||||
#include <Control.h>
 | 
			
		||||
#include <Scope.h>
 | 
			
		||||
#include <Names.h>
 | 
			
		||||
#include <Symbols.h>
 | 
			
		||||
#include <CoreTypes.h>
 | 
			
		||||
#include <Literals.h>
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QVarLengthArray>
 | 
			
		||||
#include <QtCore/QDebug>
 | 
			
		||||
 | 
			
		||||
using namespace CPlusPlus;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
class ApplySubstitution
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    ApplySubstitution(Control *control, Symbol *symbol, const DeprecatedGenTemplateInstance::Substitution &substitution);
 | 
			
		||||
    ~ApplySubstitution();
 | 
			
		||||
 | 
			
		||||
    inline Control *control() const { return _control; }
 | 
			
		||||
 | 
			
		||||
    FullySpecifiedType apply(const Name *name);
 | 
			
		||||
    FullySpecifiedType apply(const FullySpecifiedType &type);
 | 
			
		||||
 | 
			
		||||
    int findSubstitution(const Identifier *id) const;
 | 
			
		||||
    FullySpecifiedType applySubstitution(int index) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    class ApplyToType: protected TypeVisitor
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        ApplyToType(ApplySubstitution *q)
 | 
			
		||||
            : q(q) {}
 | 
			
		||||
 | 
			
		||||
        FullySpecifiedType operator()(const FullySpecifiedType &ty)
 | 
			
		||||
        {
 | 
			
		||||
            FullySpecifiedType previousType = switchType(ty);
 | 
			
		||||
            accept(ty.type());
 | 
			
		||||
            return switchType(previousType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        using TypeVisitor::visit;
 | 
			
		||||
 | 
			
		||||
        Control *control() const
 | 
			
		||||
        { return q->control(); }
 | 
			
		||||
 | 
			
		||||
        FullySpecifiedType switchType(const FullySpecifiedType &type)
 | 
			
		||||
        {
 | 
			
		||||
            FullySpecifiedType previousType = _type;
 | 
			
		||||
            _type = type;
 | 
			
		||||
            return previousType;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(VoidType *)
 | 
			
		||||
        {
 | 
			
		||||
            // nothing to do
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(IntegerType *)
 | 
			
		||||
        {
 | 
			
		||||
            // nothing to do
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(FloatType *)
 | 
			
		||||
        {
 | 
			
		||||
            // nothing to do
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(PointerToMemberType *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO; // ### TODO
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(PointerType *ptrTy)
 | 
			
		||||
        {
 | 
			
		||||
            _type.setType(control()->pointerType(q->apply(ptrTy->elementType())));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ReferenceType *refTy)
 | 
			
		||||
        {
 | 
			
		||||
            _type.setType(control()->referenceType(q->apply(refTy->elementType())));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ArrayType *arrayTy)
 | 
			
		||||
        {
 | 
			
		||||
            _type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(NamedType *ty)
 | 
			
		||||
        {
 | 
			
		||||
            FullySpecifiedType n = q->apply(ty->name());
 | 
			
		||||
            _type.setType(n.type());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(Function *funTy)
 | 
			
		||||
        {
 | 
			
		||||
            Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name());
 | 
			
		||||
            fun->setScope(funTy->scope());
 | 
			
		||||
            fun->setConst(funTy->isConst());
 | 
			
		||||
            fun->setVolatile(funTy->isVolatile());
 | 
			
		||||
            fun->setVirtual(funTy->isVirtual());
 | 
			
		||||
            fun->setAmbiguous(funTy->isAmbiguous());
 | 
			
		||||
            fun->setVariadic(funTy->isVariadic());
 | 
			
		||||
 | 
			
		||||
            fun->setReturnType(q->apply(funTy->returnType()));
 | 
			
		||||
 | 
			
		||||
            for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
 | 
			
		||||
                Argument *originalArgument = funTy->argumentAt(i)->asArgument();
 | 
			
		||||
                Argument *arg = control()->newArgument(/*sourceLocation*/ 0,
 | 
			
		||||
                                                       originalArgument->name());
 | 
			
		||||
 | 
			
		||||
                arg->setType(q->apply(originalArgument->type()));
 | 
			
		||||
                arg->setInitializer(originalArgument->initializer());
 | 
			
		||||
                fun->arguments()->enterSymbol(arg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _type.setType(fun);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(Namespace *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(Class *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(Enum *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ForwardClassDeclaration *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ObjCClass *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ObjCProtocol *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ObjCMethod *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ObjCForwardClassDeclaration *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(ObjCForwardProtocolDeclaration *)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << Q_FUNC_INFO;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        ApplySubstitution *q;
 | 
			
		||||
        FullySpecifiedType _type;
 | 
			
		||||
        QHash<Symbol *, FullySpecifiedType> _processed;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class ApplyToName: protected NameVisitor
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        ApplyToName(ApplySubstitution *q): q(q) {}
 | 
			
		||||
 | 
			
		||||
        FullySpecifiedType operator()(const Name *name)
 | 
			
		||||
        {
 | 
			
		||||
            FullySpecifiedType previousType = switchType(FullySpecifiedType());
 | 
			
		||||
            accept(name);
 | 
			
		||||
            return switchType(previousType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        Control *control() const
 | 
			
		||||
        { return q->control(); }
 | 
			
		||||
 | 
			
		||||
        int findSubstitution(const Identifier *id) const
 | 
			
		||||
        { return q->findSubstitution(id); }
 | 
			
		||||
 | 
			
		||||
        FullySpecifiedType applySubstitution(int index) const
 | 
			
		||||
        { return q->applySubstitution(index); }
 | 
			
		||||
 | 
			
		||||
        FullySpecifiedType switchType(const FullySpecifiedType &type)
 | 
			
		||||
        {
 | 
			
		||||
            FullySpecifiedType previousType = _type;
 | 
			
		||||
            _type = type;
 | 
			
		||||
            return previousType;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const NameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            int index = findSubstitution(name->identifier());
 | 
			
		||||
 | 
			
		||||
            if (index != -1)
 | 
			
		||||
                _type = applySubstitution(index);
 | 
			
		||||
 | 
			
		||||
            else
 | 
			
		||||
                _type = control()->namedType(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const TemplateNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
 | 
			
		||||
            for (unsigned i = 0; i < name->templateArgumentCount(); ++i) {
 | 
			
		||||
                FullySpecifiedType argTy = name->templateArgumentAt(i);
 | 
			
		||||
                arguments[i] = q->apply(argTy);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const TemplateNameId *templId = control()->templateNameId(name->identifier(),
 | 
			
		||||
                                                                      arguments.data(),
 | 
			
		||||
                                                                      arguments.size());
 | 
			
		||||
            _type = control()->namedType(templId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const QualifiedNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            QVarLengthArray<const Name *, 8> names(name->nameCount());
 | 
			
		||||
            for (unsigned i = 0; i < name->nameCount(); ++i) {
 | 
			
		||||
                const Name *n = name->nameAt(i);
 | 
			
		||||
 | 
			
		||||
                if (const TemplateNameId *templId = n->asTemplateNameId()) {
 | 
			
		||||
                    QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
 | 
			
		||||
                    for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
 | 
			
		||||
                        FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
 | 
			
		||||
                        arguments[templateArgIndex] = q->apply(argTy);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    n = control()->templateNameId(templId->identifier(), arguments.data(), arguments.size());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                names[i] = n;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const QualifiedNameId *q = control()->qualifiedNameId(names.data(), names.size(), name->isGlobal());
 | 
			
		||||
            _type = control()->namedType(q);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const DestructorNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            Overview oo;
 | 
			
		||||
            qWarning() << "ignored name:" << oo(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const OperatorNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            Overview oo;
 | 
			
		||||
            qWarning() << "ignored name:" << oo(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const ConversionNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            Overview oo;
 | 
			
		||||
            qWarning() << "ignored name:" << oo(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void visit(const SelectorNameId *name)
 | 
			
		||||
        {
 | 
			
		||||
            Overview oo;
 | 
			
		||||
            qWarning() << "ignored name:" << oo(name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        ApplySubstitution *q;
 | 
			
		||||
        FullySpecifiedType _type;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public: // attributes
 | 
			
		||||
    Control *_control;
 | 
			
		||||
    Symbol *symbol;
 | 
			
		||||
    DeprecatedGenTemplateInstance::Substitution substitution;
 | 
			
		||||
    ApplyToType applyToType;
 | 
			
		||||
    ApplyToName applyToName;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol,
 | 
			
		||||
                                     const DeprecatedGenTemplateInstance::Substitution &substitution)
 | 
			
		||||
    : _control(control), symbol(symbol),
 | 
			
		||||
      substitution(substitution),
 | 
			
		||||
      applyToType(this), applyToName(this)
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
ApplySubstitution::~ApplySubstitution()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FullySpecifiedType ApplySubstitution::apply(const Name *name)
 | 
			
		||||
{
 | 
			
		||||
    FullySpecifiedType ty = applyToName(name);
 | 
			
		||||
    return ty;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type)
 | 
			
		||||
{
 | 
			
		||||
    FullySpecifiedType ty = applyToType(type);
 | 
			
		||||
    return ty;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ApplySubstitution::findSubstitution(const Identifier *id) const
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(id != 0);
 | 
			
		||||
 | 
			
		||||
    for (int index = 0; index < substitution.size(); ++index) {
 | 
			
		||||
        QPair<const Identifier *, FullySpecifiedType> s = substitution.at(index);
 | 
			
		||||
 | 
			
		||||
        if (id->isEqualTo(s.first))
 | 
			
		||||
            return index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(index != -1);
 | 
			
		||||
    Q_ASSERT(index < substitution.size());
 | 
			
		||||
 | 
			
		||||
    return substitution.at(index).second;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // end of anonymous namespace
 | 
			
		||||
 | 
			
		||||
DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(Control *control, const Substitution &substitution)
 | 
			
		||||
    : _symbol(0),
 | 
			
		||||
      _control(control),
 | 
			
		||||
      _substitution(substitution)
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
FullySpecifiedType DeprecatedGenTemplateInstance::gen(Symbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    ApplySubstitution o(_control, symbol, _substitution);
 | 
			
		||||
    return o.apply(symbol->type());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *className, Symbol *candidate, Control *control)
 | 
			
		||||
{
 | 
			
		||||
    if (className) {
 | 
			
		||||
        if (const TemplateNameId *templId = className->asTemplateNameId()) {
 | 
			
		||||
            if (Class *klass = candidate->enclosingSymbol()->asClass()) {
 | 
			
		||||
                DeprecatedGenTemplateInstance::Substitution subst;
 | 
			
		||||
 | 
			
		||||
                for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
 | 
			
		||||
                    FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
 | 
			
		||||
 | 
			
		||||
                    if (i < klass->templateParameterCount()) {
 | 
			
		||||
                        const Name *templArgName = klass->templateParameterAt(i)->name();
 | 
			
		||||
 | 
			
		||||
                        if (templArgName && templArgName->identifier()) {
 | 
			
		||||
                            const Identifier *templArgId = templArgName->identifier();
 | 
			
		||||
                            subst.append(qMakePair(templArgId, templArgTy));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                DeprecatedGenTemplateInstance inst(control, subst);
 | 
			
		||||
                return inst.gen(candidate);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return candidate->type();
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user