diff -r 000000000000 -r 876b1a06bc25 tools/icheck/parser/src/shared/cplusplus/Control.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/icheck/parser/src/shared/cplusplus/Control.cpp Wed Aug 25 15:49:42 2010 +0300 @@ -0,0 +1,757 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +// 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 "Control.h" +#include "Literals.h" +#include "LiteralTable.h" +#include "TranslationUnit.h" +#include "CoreTypes.h" +#include "Symbols.h" +#include "Names.h" +#include "Array.h" +#include "TypeMatcher.h" +#include +#include + +using namespace CPlusPlus; + +namespace { + +template +struct Compare; + +template <> struct Compare +{ + bool operator()(const IntegerType &ty, const IntegerType &otherTy) const + { return ty.kind() < otherTy.kind(); } +}; + +template <> struct Compare +{ + bool operator()(const FloatType &ty, const FloatType &otherTy) const + { return ty.kind() < otherTy.kind(); } +}; + +template <> struct Compare +{ + bool operator()(const PointerToMemberType &ty, const PointerToMemberType &otherTy) const + { + if (ty.memberName() < otherTy.memberName()) + return true; + + else if (ty.memberName() == otherTy.memberName()) + return ty.elementType() < otherTy.elementType(); + + return false; + } +}; + +template <> struct Compare +{ + bool operator()(const PointerType &ty, const PointerType &otherTy) const + { + return ty.elementType() < otherTy.elementType(); + } +}; + +template <> struct Compare +{ + bool operator()(const ReferenceType &ty, const ReferenceType &otherTy) const + { + return ty.elementType() < otherTy.elementType(); + } +}; + +template <> struct Compare +{ + bool operator()(const NamedType &ty, const NamedType &otherTy) const + { + return ty.name() < otherTy.name(); + } +}; + +template <> struct Compare +{ + bool operator()(const ArrayType &ty, const ArrayType &otherTy) const + { + if (ty.size() < otherTy.size()) + return true; + + else if (ty.size() == otherTy.size()) + return ty.elementType() < otherTy.elementType(); + + return false; + } +}; + +template <> struct Compare +{ + bool operator()(const NameId &name, const NameId &otherName) const + { + return name.identifier() < otherName.identifier(); + } +}; + +template <> struct Compare +{ + bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const + { + return name.identifier() < otherName.identifier(); + } +}; + +template <> struct Compare +{ + bool operator()(const OperatorNameId &name, const OperatorNameId &otherName) const + { + return name.kind() < otherName.kind(); + } +}; + +template <> struct Compare +{ + bool operator()(const ConversionNameId &name, const ConversionNameId &otherName) const + { + return name.type() < otherName.type(); + } +}; +template <> struct Compare +{ + bool operator()(const TemplateNameId &name, const TemplateNameId &otherName) const + { + const Identifier *id = name.identifier(); + const Identifier *otherId = otherName.identifier(); + + if (id == otherId) + return std::lexicographical_compare(name.firstTemplateArgument(), name.lastTemplateArgument(), + otherName.firstTemplateArgument(), otherName.lastTemplateArgument()); + + return id < otherId; + } +}; +template <> struct Compare +{ + bool operator()(const QualifiedNameId &name, const QualifiedNameId &otherName) const + { + if (name.isGlobal() == otherName.isGlobal()) + return std::lexicographical_compare(name.firstName(), name.lastName(), + otherName.firstName(), otherName.lastName()); + + return name.isGlobal() < otherName.isGlobal(); + } +}; + +template <> struct Compare +{ + bool operator()(const SelectorNameId &name, const SelectorNameId &otherName) const + { + if (name.hasArguments() == otherName.hasArguments()) + return std::lexicographical_compare(name.firstName(), name.lastName(), + otherName.firstName(), otherName.lastName()); + + return name.hasArguments() < otherName.hasArguments(); + } +}; + + +template +class Table: public std::set<_Tp, Compare<_Tp> > +{ + typedef std::set<_Tp, Compare<_Tp> > _Base; +public: + _Tp *intern(const _Tp &element) + { return const_cast<_Tp *>(&*_Base::insert(element).first); } +}; + +} // end of anonymous namespace + +#ifdef ICHECK_BUILD +//Symbian compiler has some difficulties to understand the templates. +static void delete_array_entries(std::vector vt) +{ + std::vector::iterator it; + for (it = vt.begin(); it != vt.end(); ++it) { + delete *it; + } +} +#else +template +static void delete_array_entries(_Iterator first, _Iterator last) +{ + for (; first != last; ++first) + delete *first; +} + +template +static void delete_array_entries(const _Array &a) +{ delete_array_entries(a.begin(), a.end()); } +#endif + +class Control::Data +{ +public: + Data(Control *control) + : control(control), + translationUnit(0), + diagnosticClient(0) + {} + + ~Data() + { + // symbols + delete_array_entries(symbols); + } + + const NameId *findOrInsertNameId(const Identifier *id) + { + if (! id) + return 0; + + return nameIds.intern(NameId(id)); + } + + template + const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, _Iterator first, _Iterator last) + { + return templateNameIds.intern(TemplateNameId(id, first, last)); + } + + const DestructorNameId *findOrInsertDestructorNameId(const Identifier *id) + { + return destructorNameIds.intern(DestructorNameId(id)); + } + + const OperatorNameId *findOrInsertOperatorNameId(int kind) + { + return operatorNameIds.intern(OperatorNameId(kind)); + } + + const ConversionNameId *findOrInsertConversionNameId(const FullySpecifiedType &type) + { + return conversionNameIds.intern(ConversionNameId(type)); + } + + template + const QualifiedNameId *findOrInsertQualifiedNameId(_Iterator first, _Iterator last, bool isGlobal) + { + return qualifiedNameIds.intern(QualifiedNameId(first, last, isGlobal)); + } + + template + const SelectorNameId *findOrInsertSelectorNameId(_Iterator first, _Iterator last, bool hasArguments) + { + return selectorNameIds.intern(SelectorNameId(first, last, hasArguments)); + } + + IntegerType *findOrInsertIntegerType(int kind) + { + return integerTypes.intern(IntegerType(kind)); + } + + FloatType *findOrInsertFloatType(int kind) + { + return floatTypes.intern(FloatType(kind)); + } + + PointerToMemberType *findOrInsertPointerToMemberType(const Name *memberName, const FullySpecifiedType &elementType) + { + return pointerToMemberTypes.intern(PointerToMemberType(memberName, elementType)); + } + + PointerType *findOrInsertPointerType(const FullySpecifiedType &elementType) + { + return pointerTypes.intern(PointerType(elementType)); + } + + ReferenceType *findOrInsertReferenceType(const FullySpecifiedType &elementType) + { + return referenceTypes.intern(ReferenceType(elementType)); + } + + ArrayType *findOrInsertArrayType(const FullySpecifiedType &elementType, unsigned size) + { + return arrayTypes.intern(ArrayType(elementType, size)); + } + + NamedType *findOrInsertNamedType(const Name *name) + { + return namedTypes.intern(NamedType(name)); + } + + Declaration *newDeclaration(unsigned sourceLocation, const Name *name) + { + Declaration *declaration = new Declaration(translationUnit, + sourceLocation, name); + symbols.push_back(declaration); + return declaration; + } + + Argument *newArgument(unsigned sourceLocation, const Name *name) + { + Argument *argument = new Argument(translationUnit, + sourceLocation, name); + symbols.push_back(argument); + return argument; + } + + TypenameArgument *newTypenameArgument(unsigned sourceLocation, const Name *name) + { + TypenameArgument *argument = new TypenameArgument(translationUnit, + sourceLocation, name); + symbols.push_back(argument); + return argument; + } + + Function *newFunction(unsigned sourceLocation, const Name *name) + { + Function *function = new Function(translationUnit, + sourceLocation, name); + symbols.push_back(function); + return function; + } + + BaseClass *newBaseClass(unsigned sourceLocation, const Name *name) + { + BaseClass *baseClass = new BaseClass(translationUnit, + sourceLocation, name); + symbols.push_back(baseClass); + return baseClass; + } + + Block *newBlock(unsigned sourceLocation) + { + Block *block = new Block(translationUnit, sourceLocation); + symbols.push_back(block); + return block; + } + + Class *newClass(unsigned sourceLocation, const Name *name) + { + Class *klass = new Class(translationUnit, + sourceLocation, name); + symbols.push_back(klass); + return klass; + } + + Namespace *newNamespace(unsigned sourceLocation, const Name *name) + { + Namespace *ns = new Namespace(translationUnit, + sourceLocation, name); + symbols.push_back(ns); + return ns; + } + + UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, const Name *name) + { + UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit, + sourceLocation, name); + symbols.push_back(u); + return u; + } + + ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, const Name *name) + { + ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit, + sourceLocation, name); + symbols.push_back(c); + return c; + } + + ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, const Name *name) + { + ObjCBaseClass *c = new ObjCBaseClass(translationUnit, sourceLocation, name); + symbols.push_back(c); + return c; + } + + ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, const Name *name) + { + ObjCBaseProtocol *p = new ObjCBaseProtocol(translationUnit, sourceLocation, name); + symbols.push_back(p); + return p; + } + + ObjCClass *newObjCClass(unsigned sourceLocation, const Name *name) + { + ObjCClass *c = new ObjCClass(translationUnit, sourceLocation, name); + symbols.push_back(c); + return c; + } + + ObjCForwardClassDeclaration *newObjCForwardClassDeclaration(unsigned sourceLocation, const Name *name) + { + ObjCForwardClassDeclaration *fwd = new ObjCForwardClassDeclaration(translationUnit, sourceLocation, name); + symbols.push_back(fwd); + return fwd; + } + + ObjCProtocol *newObjCProtocol(unsigned sourceLocation, const Name *name) + { + ObjCProtocol *p = new ObjCProtocol(translationUnit, sourceLocation, name); + symbols.push_back(p); + return p; + } + + ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, const Name *name) + { + ObjCForwardProtocolDeclaration *fwd = new ObjCForwardProtocolDeclaration(translationUnit, sourceLocation, name); + symbols.push_back(fwd); + return fwd; + } + + ObjCMethod *newObjCMethod(unsigned sourceLocation, const Name *name) + { + ObjCMethod *method = new ObjCMethod(translationUnit, sourceLocation, name); + symbols.push_back(method); + return method; + } + + ObjCPropertyDeclaration *newObjCPropertyDeclaration(unsigned sourceLocation, const Name *name) + { + ObjCPropertyDeclaration *decl = new ObjCPropertyDeclaration(translationUnit, sourceLocation, name); + symbols.push_back(decl); + return decl; + } + + Enum *newEnum(unsigned sourceLocation, const Name *name) + { + Enum *e = new Enum(translationUnit, + sourceLocation, name); + symbols.push_back(e); + return e; + } + + UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, const Name *name) + { + UsingDeclaration *u = new UsingDeclaration(translationUnit, + sourceLocation, name); + symbols.push_back(u); + return u; + } + + Control *control; + TranslationUnit *translationUnit; + DiagnosticClient *diagnosticClient; + + TypeMatcher matcher; + + LiteralTable identifiers; + LiteralTable stringLiterals; + LiteralTable numericLiterals; + + // ### replace std::map with lookup tables. ASAP! + + // names + Table nameIds; + Table destructorNameIds; + Table operatorNameIds; + Table conversionNameIds; + Table templateNameIds; + Table qualifiedNameIds; + Table selectorNameIds; + + // types + VoidType voidType; + Table integerTypes; + Table floatTypes; + Table pointerToMemberTypes; + Table pointerTypes; + Table referenceTypes; + Table arrayTypes; + Table namedTypes; + + // symbols + std::vector symbols; + + // ObjC context keywords: + const Identifier *objcGetterId; + const Identifier *objcSetterId; + const Identifier *objcReadwriteId; + const Identifier *objcReadonlyId; + const Identifier *objcAssignId; + const Identifier *objcRetainId; + const Identifier *objcCopyId; + const Identifier *objcNonatomicId; +}; + +Control::Control() +{ + d = new Data(this); + + d->objcGetterId = findOrInsertIdentifier("getter"); + d->objcSetterId = findOrInsertIdentifier("setter"); + d->objcReadwriteId = findOrInsertIdentifier("readwrite"); + d->objcReadonlyId = findOrInsertIdentifier("readonly"); + d->objcAssignId = findOrInsertIdentifier("assign"); + d->objcRetainId = findOrInsertIdentifier("retain"); + d->objcCopyId = findOrInsertIdentifier("copy"); + d->objcNonatomicId = findOrInsertIdentifier("nonatomic"); +} + +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; } + +const Identifier *Control::findIdentifier(const char *chars, unsigned size) const +{ return d->identifiers.findLiteral(chars, size); } + +const Identifier *Control::findOrInsertIdentifier(const char *chars, unsigned size) +{ return d->identifiers.findOrInsertLiteral(chars, size); } + +const Identifier *Control::findOrInsertIdentifier(const char *chars) +{ + unsigned length = std::strlen(chars); + return findOrInsertIdentifier(chars, length); +} + +Control::IdentifierIterator Control::firstIdentifier() const +{ return d->identifiers.begin(); } + +Control::IdentifierIterator Control::lastIdentifier() const +{ return d->identifiers.end(); } + +Control::StringLiteralIterator Control::firstStringLiteral() const +{ return d->stringLiterals.begin(); } + +Control::StringLiteralIterator Control::lastStringLiteral() const +{ return d->stringLiterals.end(); } + +Control::NumericLiteralIterator Control::firstNumericLiteral() const +{ return d->numericLiterals.begin(); } + +Control::NumericLiteralIterator Control::lastNumericLiteral() const +{ return d->numericLiterals.end(); } + +const StringLiteral *Control::findOrInsertStringLiteral(const char *chars, unsigned size) +{ return d->stringLiterals.findOrInsertLiteral(chars, size); } + +const StringLiteral *Control::findOrInsertStringLiteral(const char *chars) +{ + unsigned length = std::strlen(chars); + return findOrInsertStringLiteral(chars, length); +} + +const NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars, unsigned size) +{ return d->numericLiterals.findOrInsertLiteral(chars, size); } + +const NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars) +{ + unsigned length = std::strlen(chars); + return findOrInsertNumericLiteral(chars, length); +} + +const NameId *Control::nameId(const Identifier *id) +{ return d->findOrInsertNameId(id); } + +const TemplateNameId *Control::templateNameId(const Identifier *id, + const FullySpecifiedType *const args, + unsigned argv) +{ + return d->findOrInsertTemplateNameId(id, args, args + argv); +} + +const DestructorNameId *Control::destructorNameId(const Identifier *id) +{ return d->findOrInsertDestructorNameId(id); } + +const OperatorNameId *Control::operatorNameId(int kind) +{ return d->findOrInsertOperatorNameId(kind); } + +const ConversionNameId *Control::conversionNameId(const FullySpecifiedType &type) +{ return d->findOrInsertConversionNameId(type); } + +const QualifiedNameId *Control::qualifiedNameId(const Name *const *names, + unsigned nameCount, + bool isGlobal) +{ + return d->findOrInsertQualifiedNameId(names, names + nameCount, isGlobal); +} + +const SelectorNameId *Control::selectorNameId(const Name *const *names, + unsigned nameCount, + bool hasArguments) +{ + return d->findOrInsertSelectorNameId(names, names + nameCount, hasArguments); +} + + +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(const Name *memberName, const FullySpecifiedType &elementType) +{ return d->findOrInsertPointerToMemberType(memberName, elementType); } + +PointerType *Control::pointerType(const FullySpecifiedType &elementType) +{ return d->findOrInsertPointerType(elementType); } + +ReferenceType *Control::referenceType(const FullySpecifiedType &elementType) +{ return d->findOrInsertReferenceType(elementType); } + +ArrayType *Control::arrayType(const FullySpecifiedType &elementType, unsigned size) +{ return d->findOrInsertArrayType(elementType, size); } + +NamedType *Control::namedType(const Name *name) +{ return d->findOrInsertNamedType(name); } + +Argument *Control::newArgument(unsigned sourceLocation, const Name *name) +{ return d->newArgument(sourceLocation, name); } + +TypenameArgument *Control::newTypenameArgument(unsigned sourceLocation, const Name *name) +{ return d->newTypenameArgument(sourceLocation, name); } + +Function *Control::newFunction(unsigned sourceLocation, const Name *name) +{ return d->newFunction(sourceLocation, name); } + +Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name) +{ return d->newNamespace(sourceLocation, name); } + +BaseClass *Control::newBaseClass(unsigned sourceLocation, const Name *name) +{ return d->newBaseClass(sourceLocation, name); } + +Class *Control::newClass(unsigned sourceLocation, const Name *name) +{ return d->newClass(sourceLocation, name); } + +Enum *Control::newEnum(unsigned sourceLocation, const Name *name) +{ return d->newEnum(sourceLocation, name); } + +Block *Control::newBlock(unsigned sourceLocation) +{ return d->newBlock(sourceLocation); } + +Declaration *Control::newDeclaration(unsigned sourceLocation, const Name *name) +{ return d->newDeclaration(sourceLocation, name); } + +UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLocation, + const Name *name) +{ return d->newUsingNamespaceDirective(sourceLocation, name); } + +UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, const Name *name) +{ return d->newUsingDeclaration(sourceLocation, name); } + +ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLocation, + const Name *name) +{ return d->newForwardClassDeclaration(sourceLocation, name); } + +ObjCBaseClass *Control::newObjCBaseClass(unsigned sourceLocation, const Name *name) +{ return d->newObjCBaseClass(sourceLocation, name); } + +ObjCBaseProtocol *Control::newObjCBaseProtocol(unsigned sourceLocation, const Name *name) +{ return d->newObjCBaseProtocol(sourceLocation, name); } + +ObjCClass *Control::newObjCClass(unsigned sourceLocation, const Name *name) +{ return d->newObjCClass(sourceLocation, name); } + +ObjCForwardClassDeclaration *Control::newObjCForwardClassDeclaration(unsigned sourceLocation, const Name *name) +{ return d->newObjCForwardClassDeclaration(sourceLocation, name); } + +ObjCProtocol *Control::newObjCProtocol(unsigned sourceLocation, const Name *name) +{ return d->newObjCProtocol(sourceLocation, name); } + +ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsigned sourceLocation, const Name *name) +{ return d->newObjCForwardProtocolDeclaration(sourceLocation, name); } + +ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, const Name *name) +{ return d->newObjCMethod(sourceLocation, name); } + +ObjCPropertyDeclaration *Control::newObjCPropertyDeclaration(unsigned sourceLocation, const Name *name) +{ return d->newObjCPropertyDeclaration(sourceLocation, name); } + +const Identifier *Control::objcGetterId() const +{ return d->objcGetterId; } + +const Identifier *Control::objcSetterId() const +{ return d->objcSetterId; } + +const Identifier *Control::objcReadwriteId() const +{ return d->objcReadwriteId; } + +const Identifier *Control::objcReadonlyId() const +{ return d->objcReadonlyId; } + +const Identifier *Control::objcAssignId() const +{ return d->objcAssignId; } + +const Identifier *Control::objcRetainId() const +{ return d->objcRetainId; } + +const Identifier *Control::objcCopyId() const +{ return d->objcCopyId; } + +const Identifier *Control::objcNonatomicId() const +{ return d->objcNonatomicId; }