/*************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Qt Software Information (qt-info@nokia.com) ** ** ** Non-Open Source Usage ** ** Licensees may use this file in accordance with the Qt Beta Version ** License Agreement, Agreement version 2.2 provided with the Software or, ** alternatively, in accordance with the terms contained in a written ** agreement between you and Nokia. ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the packaging ** of this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt GPL Exception ** version 1.2, included in the file GPL_EXCEPTION.txt in this package. ** ***************************************************************************/ ***************************************************************************/ // 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 "MemoryPool.h" #include "Literals.h" #include "LiteralTable.h" #include "TranslationUnit.h" #include "CoreTypes.h" #include "Symbols.h" #include "Names.h" #include "Array.h" #include // ### replace me with LiteralTable #include CPLUSPLUS_BEGIN_NAMESPACE template static void delete_map_entries(_Iterator first, _Iterator last) { for (; first != last; ++first) delete first->second; } template static void delete_map_entries(const _Map &m) { delete_map_entries(m.begin(), m.end()); } 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()); } class Control::Data { public: Data(Control *control) : control(control), translationUnit(0), diagnosticClient(0) { } ~Data() { // names delete_map_entries(nameIds); delete_map_entries(destructorNameIds); delete_map_entries(operatorNameIds); delete_map_entries(conversionNameIds); delete_map_entries(qualifiedNameIds); delete_map_entries(templateNameIds); // types delete_map_entries(integerTypes); delete_map_entries(floatTypes); delete_map_entries(pointerToMemberTypes); delete_map_entries(pointerTypes); delete_map_entries(referenceTypes); delete_map_entries(arrayTypes); delete_map_entries(namedTypes); // symbols delete_array_entries(declarations); delete_array_entries(arguments); delete_array_entries(functions); delete_array_entries(baseClasses); delete_array_entries(blocks); delete_array_entries(classes); delete_array_entries(namespaces); delete_array_entries(usingNamespaceDirectives); delete_array_entries(enums); delete_array_entries(usingDeclarations); } NameId *findOrInsertNameId(Identifier *id) { if (! id) return 0; std::map::iterator it = nameIds.lower_bound(id); if (it == nameIds.end() || it->first != id) it = nameIds.insert(it, std::make_pair(id, new NameId(id))); return it->second; } TemplateNameId *findOrInsertTemplateNameId(Identifier *id, const std::vector &templateArguments) { if (! id) return 0; const TemplateNameIdKey key(id, templateArguments); std::map::iterator it = templateNameIds.lower_bound(key); if (it == templateNameIds.end() || it->first != key) { const FullySpecifiedType *args = 0; if (templateArguments.size()) args = &templateArguments[0]; TemplateNameId *templ = new TemplateNameId(id, args, templateArguments.size()); it = templateNameIds.insert(it, std::make_pair(key, templ)); } return it->second; } DestructorNameId *findOrInsertDestructorNameId(Identifier *id) { if (! id) return 0; std::map::iterator it = destructorNameIds.lower_bound(id); if (it == destructorNameIds.end() || it->first != id) it = destructorNameIds.insert(it, std::make_pair(id, new DestructorNameId(id))); return it->second; } OperatorNameId *findOrInsertOperatorNameId(int kind) { const int key(kind); std::map::iterator it = operatorNameIds.lower_bound(key); if (it == operatorNameIds.end() || it->first != key) it = operatorNameIds.insert(it, std::make_pair(key, new OperatorNameId(kind))); return it->second; } ConversionNameId *findOrInsertConversionNameId(FullySpecifiedType type) { std::map::iterator it = conversionNameIds.lower_bound(type); if (it == conversionNameIds.end() || it->first != type) it = conversionNameIds.insert(it, std::make_pair(type, new ConversionNameId(type))); return it->second; } QualifiedNameId *findOrInsertQualifiedNameId(const std::vector &names, bool isGlobal) { const QualifiedNameIdKey key(names, isGlobal); std::map::iterator it = qualifiedNameIds.lower_bound(key); if (it == qualifiedNameIds.end() || it->first != key) { QualifiedNameId *name = new QualifiedNameId(&names[0], names.size(), isGlobal); it = qualifiedNameIds.insert(it, std::make_pair(key, name)); } return it->second; } IntegerType *findOrInsertIntegerType(int kind) { const int key = int(kind); std::map::iterator it = integerTypes.lower_bound(key); if (it == integerTypes.end() || it->first != key) it = integerTypes.insert(it, std::make_pair(key, new IntegerType(kind))); return it->second; } FloatType *findOrInsertFloatType(int kind) { const int key = int(kind); std::map::iterator it = floatTypes.lower_bound(key); if (it == floatTypes.end() || it->first != key) it = floatTypes.insert(it, std::make_pair(key, new FloatType(kind))); return it->second; } PointerToMemberType *findOrInsertPointerToMemberType(Name *memberName, FullySpecifiedType elementType) { const PointerToMemberTypeKey key(memberName, elementType); std::map::iterator it = pointerToMemberTypes.lower_bound(key); if (it == pointerToMemberTypes.end() || it->first != key) it = pointerToMemberTypes.insert(it, std::make_pair(key, new PointerToMemberType(memberName, elementType))); return it->second; } PointerType *findOrInsertPointerType(FullySpecifiedType elementType) { std::map::iterator it = pointerTypes.lower_bound(elementType); if (it == pointerTypes.end() || it->first != elementType) it = pointerTypes.insert(it, std::make_pair(elementType, new PointerType(elementType))); return it->second; } ReferenceType *findOrInsertReferenceType(FullySpecifiedType elementType) { std::map::iterator it = referenceTypes.lower_bound(elementType); if (it == referenceTypes.end() || it->first != elementType) it = referenceTypes.insert(it, std::make_pair(elementType, new ReferenceType(elementType))); return it->second; } ArrayType *findOrInsertArrayType(FullySpecifiedType elementType, size_t size) { const ArrayKey key(elementType, size); std::map::iterator it = arrayTypes.lower_bound(key); if (it == arrayTypes.end() || it->first != key) it = arrayTypes.insert(it, std::make_pair(key, new ArrayType(elementType, size))); return it->second; } NamedType *findOrInsertNamedType(Name *name) { std::map::iterator it = namedTypes.lower_bound(name); if (it == namedTypes.end() || it->first != name) it = namedTypes.insert(it, std::make_pair(name, new NamedType(name))); return it->second; } Declaration *newDeclaration(unsigned sourceLocation, Name *name) { Declaration *declaration = new Declaration(translationUnit, sourceLocation, name); declarations.push_back(declaration); return declaration; } Argument *newArgument(unsigned sourceLocation, Name *name) { Argument *argument = new Argument(translationUnit, sourceLocation, name); arguments.push_back(argument); return argument; } Function *newFunction(unsigned sourceLocation, Name *name) { Function *function = new Function(translationUnit, sourceLocation, name); functions.push_back(function); return function; } BaseClass *newBaseClass(unsigned sourceLocation, Name *name) { BaseClass *baseClass = new BaseClass(translationUnit, sourceLocation, name); baseClasses.push_back(baseClass); return baseClass; } Block *newBlock(unsigned sourceLocation) { Block *block = new Block(translationUnit, sourceLocation); blocks.push_back(block); return block; } Class *newClass(unsigned sourceLocation, Name *name) { Class *klass = new Class(translationUnit, sourceLocation, name); classes.push_back(klass); return klass; } Namespace *newNamespace(unsigned sourceLocation, Name *name) { Namespace *ns = new Namespace(translationUnit, sourceLocation, name); namespaces.push_back(ns); return ns; } UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, Name *name) { UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit, sourceLocation, name); usingNamespaceDirectives.push_back(u); return u; } Enum *newEnum(unsigned sourceLocation, Name *name) { Enum *e = new Enum(translationUnit, sourceLocation, name); enums.push_back(e); return e; } UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name) { UsingDeclaration *u = new UsingDeclaration(translationUnit, sourceLocation, name); usingDeclarations.push_back(u); return u; } struct TemplateNameIdKey { Identifier *id; std::vector templateArguments; TemplateNameIdKey(Identifier *id, const std::vector &templateArguments) : id(id), templateArguments(templateArguments) { } bool operator == (const TemplateNameIdKey &other) const { return id == other.id && templateArguments == other.templateArguments; } bool operator != (const TemplateNameIdKey &other) const { return ! operator==(other); } bool operator < (const TemplateNameIdKey &other) const { if (id == other.id) return std::lexicographical_compare(templateArguments.begin(), templateArguments.end(), other.templateArguments.begin(), other.templateArguments.end()); return id < other.id; } }; struct QualifiedNameIdKey { std::vector names; bool isGlobal; QualifiedNameIdKey(const std::vector &names, bool isGlobal) : names(names), isGlobal(isGlobal) { } bool operator == (const QualifiedNameIdKey &other) const { return isGlobal == other.isGlobal && names == other.names; } bool operator != (const QualifiedNameIdKey &other) const { return ! operator==(other); } bool operator < (const QualifiedNameIdKey &other) const { if (isGlobal == other.isGlobal) return std::lexicographical_compare(names.begin(), names.end(), other.names.begin(), other.names.end()); return isGlobal < other.isGlobal; } }; struct ArrayKey { FullySpecifiedType type; size_t size; ArrayKey() : size(0) { } ArrayKey(FullySpecifiedType type, size_t size) : type(type), size(size) { } bool operator == (const ArrayKey &other) const { return type == other.type && size == other.size; } bool operator != (const ArrayKey &other) const { return ! operator==(other); } bool operator < (const ArrayKey &other) const { if (type == other.type) return size < other.size; return type < other.type; } }; struct PointerToMemberTypeKey { Name *memberName; FullySpecifiedType type; PointerToMemberTypeKey() : memberName(0) { } PointerToMemberTypeKey(Name *memberName, FullySpecifiedType type) : memberName(memberName), type(type) { } bool operator == (const PointerToMemberTypeKey &other) const { return memberName == other.memberName && type == other.type; } bool operator != (const PointerToMemberTypeKey &other) const { return ! operator==(other); } bool operator < (const PointerToMemberTypeKey &other) const { if (memberName == other.memberName) return type < other.type; return memberName < other.memberName; } }; Control *control; TranslationUnit *translationUnit; DiagnosticClient *diagnosticClient; LiteralTable identifiers; LiteralTable stringLiterals; LiteralTable numericLiterals; LiteralTable fileNames; // ### replace std::map with lookup tables. ASAP! // names std::map nameIds; std::map destructorNameIds; std::map operatorNameIds; std::map conversionNameIds; std::map templateNameIds; std::map qualifiedNameIds; // types VoidType voidType; std::map integerTypes; std::map floatTypes; std::map pointerToMemberTypes; std::map pointerTypes; std::map referenceTypes; std::map arrayTypes; std::map namedTypes; // symbols std::vector declarations; std::vector arguments; std::vector functions; std::vector baseClasses; std::vector blocks; std::vector classes; std::vector namespaces; std::vector usingNamespaceDirectives; std::vector enums; std::vector usingDeclarations; }; Control::Control() { d = new Data(this); } 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; } Identifier *Control::findOrInsertIdentifier(const char *chars, unsigned size) { return d->identifiers.findOrInsertLiteral(chars, size); } Identifier *Control::findOrInsertIdentifier(const char *chars) { unsigned length = std::char_traits::length(chars); return findOrInsertIdentifier(chars, length); } StringLiteral *Control::findOrInsertStringLiteral(const char *chars, unsigned size) { return d->stringLiterals.findOrInsertLiteral(chars, size); } StringLiteral *Control::findOrInsertStringLiteral(const char *chars) { unsigned length = std::char_traits::length(chars); return findOrInsertStringLiteral(chars, length); } NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars, unsigned size) { return d->numericLiterals.findOrInsertLiteral(chars, size); } NumericLiteral *Control::findOrInsertNumericLiteral(const char *chars) { unsigned length = std::char_traits::length(chars); return findOrInsertNumericLiteral(chars, length); } unsigned Control::fileNameCount() const { return d->fileNames.size(); } StringLiteral *Control::fileNameAt(unsigned index) const { return d->fileNames.at(index); } StringLiteral *Control::findOrInsertFileName(const char *chars, unsigned size) { return d->fileNames.findOrInsertLiteral(chars, size); } StringLiteral *Control::findOrInsertFileName(const char *chars) { unsigned length = std::char_traits::length(chars); return findOrInsertFileName(chars, length); } NameId *Control::nameId(Identifier *id) { return d->findOrInsertNameId(id); } TemplateNameId *Control::templateNameId(Identifier *id, FullySpecifiedType *const args, unsigned argv) { std::vector templateArguments(args, args + argv); return d->findOrInsertTemplateNameId(id, templateArguments); } DestructorNameId *Control::destructorNameId(Identifier *id) { return d->findOrInsertDestructorNameId(id); } OperatorNameId *Control::operatorNameId(int kind) { return d->findOrInsertOperatorNameId(kind); } ConversionNameId *Control::conversionNameId(FullySpecifiedType type) { return d->findOrInsertConversionNameId(type); } QualifiedNameId *Control::qualifiedNameId(Name *const *names, unsigned nameCount, bool isGlobal) { std::vector classOrNamespaceNames(names, names + nameCount); return d->findOrInsertQualifiedNameId(classOrNamespaceNames, isGlobal); } 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(Name *memberName, FullySpecifiedType elementType) { return d->findOrInsertPointerToMemberType(memberName, elementType); } PointerType *Control::pointerType(FullySpecifiedType elementType) { return d->findOrInsertPointerType(elementType); } ReferenceType *Control::referenceType(FullySpecifiedType elementType) { return d->findOrInsertReferenceType(elementType); } ArrayType *Control::arrayType(FullySpecifiedType elementType, size_t size) { return d->findOrInsertArrayType(elementType, size); } NamedType *Control::namedType(Name *name) { return d->findOrInsertNamedType(name); } Argument *Control::newArgument(unsigned sourceLocation, Name *name) { return d->newArgument(sourceLocation, name); } Function *Control::newFunction(unsigned sourceLocation, Name *name) { return d->newFunction(sourceLocation, name); } Namespace *Control::newNamespace(unsigned sourceLocation, Name *name) { return d->newNamespace(sourceLocation, name); } BaseClass *Control::newBaseClass(unsigned sourceLocation, Name *name) { return d->newBaseClass(sourceLocation, name); } Class *Control::newClass(unsigned sourceLocation, Name *name) { return d->newClass(sourceLocation, name); } Enum *Control::newEnum(unsigned sourceLocation, Name *name) { return d->newEnum(sourceLocation, name); } Block *Control::newBlock(unsigned sourceLocation) { return d->newBlock(sourceLocation); } Declaration *Control::newDeclaration(unsigned sourceLocation, Name *name) { return d->newDeclaration(sourceLocation, name); } UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLocation, Name *name) { return d->newUsingNamespaceDirective(sourceLocation, name); } UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name) { return d->newUsingDeclaration(sourceLocation, name); } CPLUSPLUS_END_NAMESPACE