/************************************************************************** ** ** 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. ** **************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // 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 "TypeMatcher.h" #include "Scope.h" using namespace CPlusPlus; UsingNamespaceDirective::UsingNamespaceDirective(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Symbol(translationUnit, sourceLocation, name) { } UsingNamespaceDirective::~UsingNamespaceDirective() { } FullySpecifiedType UsingNamespaceDirective::type() const { return FullySpecifiedType(); } void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } NamespaceAlias::NamespaceAlias(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Symbol(translationUnit, sourceLocation, name), _namespaceName(0) { } NamespaceAlias::~NamespaceAlias() { } const Name *NamespaceAlias::namespaceName() const { return _namespaceName; } void NamespaceAlias::setNamespaceName(const Name *namespaceName) { _namespaceName = namespaceName; } FullySpecifiedType NamespaceAlias::type() const { return FullySpecifiedType(); } void NamespaceAlias::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } UsingDeclaration::UsingDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const 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, const Name *name) : Symbol(translationUnit, sourceLocation, name) { } Declaration::~Declaration() { } void Declaration::setType(const FullySpecifiedType &type) { _type = type; } FullySpecifiedType Declaration::type() const { return _type; } void Declaration::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } Argument::Argument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Symbol(translationUnit, sourceLocation, name), _initializer(0) { } Argument::~Argument() { } bool Argument::hasInitializer() const { return _initializer != 0; } const StringLiteral *Argument::initializer() const { return _initializer; } void Argument::setInitializer(const StringLiteral *initializer) { _initializer = initializer; } void Argument::setType(const FullySpecifiedType &type) { _type = type; } FullySpecifiedType Argument::type() const { return _type; } void Argument::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } TypenameArgument::TypenameArgument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Symbol(translationUnit, sourceLocation, name) { } TypenameArgument::~TypenameArgument() { } void TypenameArgument::setType(const FullySpecifiedType &type) { _type = type; } FullySpecifiedType TypenameArgument::type() const { return _type; } void TypenameArgument::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } Function::Function(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name), _flags(0) { } Function::~Function() { } bool Function::isNormal() const { return f._methodKey == NormalMethod; } bool Function::isSignal() const { return f._methodKey == SignalMethod; } bool Function::isSlot() const { return f._methodKey == SlotMethod; } bool Function::isInvokable() const { return f._methodKey == InvokableMethod; } int Function::methodKey() const { return f._methodKey; } void Function::setMethodKey(int key) { f._methodKey = key; } bool Function::isEqualTo(const Type *other) const { const Function *o = other->asFunctionType(); if (! o) return false; else if (isConst() != o->isConst()) return false; else if (isVolatile() != o->isVolatile()) return false; #ifdef ICHECK_BUILD else if (isInvokable() != o->isInvokable()) return false; else if (isSignal() != o->isSignal()) return false; #endif const Name *l = identity(); const Name *r = o->identity(); if (l == r || (l && l->isEqualTo(r))) { if (argumentCount() != o->argumentCount()) return false; else if (! _returnType.isEqualTo(o->_returnType)) return false; for (unsigned i = 0; i < argumentCount(); ++i) { Symbol *l = argumentAt(i); Symbol *r = o->argumentAt(i); if (! l->type().isEqualTo(r->type())) return false; } return true; } return false; } #ifdef ICHECK_BUILD bool Function::isEqualTo(const Function* fct, bool ignoreName/* = false*/) const { if(!ignoreName) return isEqualTo((Type*)fct); if (! fct) return false; else if (isConst() != fct->isConst()) return false; else if (isVolatile() != fct->isVolatile()) return false; else if (isInvokable() != fct->isInvokable()) return false; else if (isSignal() != fct->isSignal()) return false; if (_arguments->symbolCount() != fct->_arguments->symbolCount()) return false; else if (! _returnType.isEqualTo(fct->_returnType)) return false; for (unsigned i = 0; i < _arguments->symbolCount(); ++i) { Symbol *l = _arguments->symbolAt(i); Symbol *r = fct->_arguments->symbolAt(i); if (! l->type().isEqualTo(r->type())) return false; } return true; } #endif void Function::accept0(TypeVisitor *visitor) { visitor->visit(this); } bool Function::matchType0(const Type *otherType, TypeMatcher *matcher) const { if (const Function *otherTy = otherType->asFunctionType()) return matcher->match(this, otherTy); return false; } FullySpecifiedType Function::type() const { FullySpecifiedType ty(const_cast(this)); ty.setConst(isConst()); ty.setVolatile(isVolatile()); return ty; } FullySpecifiedType Function::returnType() const { return _returnType; } void Function::setReturnType(const FullySpecifiedType &returnType) { _returnType = returnType; } bool Function::hasReturnType() const { const FullySpecifiedType ty = returnType(); return ty.isValid() || ty.isSigned() || ty.isUnsigned(); } unsigned Function::argumentCount() const { const unsigned c = memberCount(); if (c > 0 && memberAt(c - 1)->isBlock()) return c - 1; return c; } Symbol *Function::argumentAt(unsigned index) const { return memberAt(index); } bool Function::hasArguments() const { return ! (argumentCount() == 0 || (argumentCount() == 1 && argumentAt(0)->type()->isVoidType())); } unsigned Function::minimumArgumentCount() const { unsigned index = 0; for (; index < argumentCount(); ++index) { if (Argument *arg = argumentAt(index)->asArgument()) { if (arg->hasInitializer()) break; } } return index; } bool Function::isVirtual() const { return f._isVirtual; } void Function::setVirtual(bool isVirtual) { f._isVirtual = isVirtual; } bool Function::isVariadic() const { return f._isVariadic; } void Function::setVariadic(bool isVariadic) { f._isVariadic = isVariadic; } bool Function::isConst() const { return f._isConst; } void Function::setConst(bool isConst) { f._isConst = isConst; } bool Function::isVolatile() const { return f._isVolatile; } void Function::setVolatile(bool isVolatile) { f._isVolatile = isVolatile; } bool Function::isPureVirtual() const { return f._isPureVirtual; } void Function::setPureVirtual(bool isPureVirtual) { f._isPureVirtual = isPureVirtual; } bool Function::isAmbiguous() const { return f._isAmbiguous; } void Function::setAmbiguous(bool isAmbiguous) { f._isAmbiguous = isAmbiguous; } void Function::visitSymbol0(SymbolVisitor *visitor) { if (visitor->visit(this)) { for (unsigned i = 0; i < memberCount(); ++i) { visitSymbol(memberAt(i), visitor); } } } Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation) : Scope(translationUnit, sourceLocation, /*name = */ 0) { } Block::~Block() { } FullySpecifiedType Block::type() const { return FullySpecifiedType(); } void Block::visitSymbol0(SymbolVisitor *visitor) { if (visitor->visit(this)) { for (unsigned i = 0; i < memberCount(); ++i) { visitSymbol(memberAt(i), visitor); } } } Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name) { } Enum::~Enum() { } FullySpecifiedType Enum::type() const { return FullySpecifiedType(const_cast(this)); } bool Enum::isEqualTo(const Type *other) const { const Enum *o = other->asEnumType(); if (! o) return false; const Name *l = identity(); const 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); } bool Enum::matchType0(const Type *otherType, TypeMatcher *matcher) const { if (const Enum *otherTy = otherType->asEnumType()) return matcher->match(this, otherTy); return false; } void Enum::visitSymbol0(SymbolVisitor *visitor) { if (visitor->visit(this)) { for (unsigned i = 0; i < memberCount(); ++i) { visitSymbol(memberAt(i), visitor); } } } Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name) { } Template::~Template() { } unsigned Template::templateParameterCount() const { if (declaration() != 0) return memberCount() - 1; return 0; } Symbol *Template::templateParameterAt(unsigned index) const { return memberAt(index); } Symbol *Template::declaration() const { if (isEmpty()) return 0; if (Symbol *s = memberAt(memberCount() - 1)) { if (s->isClass() || s->isForwardClassDeclaration() || s->isTemplate() || s->isFunction() || s->isDeclaration()) return s; } return 0; } FullySpecifiedType Template::type() const { return FullySpecifiedType(const_cast