-
Roberto Raggi authoredRoberto Raggi authored
DeprecatedGenTemplateInstance.cpp 12.04 KiB
/**************************************************************************
**
** 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();
}