diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index cc591f01a88..009e1e8504e 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -11,11 +11,6 @@ #include #include -// TODO: fix this warning once we no longer support VS2013 and earlier -#if defined(_MSC_VER) -# pragma warning(disable : 4589) // Constructor of abstract class 'Slice::Type' ignores initializer... -#endif - using namespace std; using namespace Slice; @@ -693,35 +688,10 @@ Slice::DocComment::exceptions() const return _exceptions; } -// ---------------------------------------------------------------------- -// SyntaxTreeBase -// ---------------------------------------------------------------------- - -void -Slice::SyntaxTreeBase::destroy() -{ - _unit = nullptr; -} - -UnitPtr -Slice::SyntaxTreeBase::unit() const -{ - return _unit; -} - -void -Slice::SyntaxTreeBase::visit(ParserVisitor* /*visitor*/) -{ -} - -Slice::SyntaxTreeBase::SyntaxTreeBase(UnitPtr unit) : _unit(std::move(unit)) {} - // ---------------------------------------------------------------------- // Type // ---------------------------------------------------------------------- -Slice::Type::Type(const UnitPtr& unit) : SyntaxTreeBase(unit) {} - bool Slice::Type::isClassType() const { @@ -738,6 +708,20 @@ Slice::Type::usesClasses() const // Builtin // ---------------------------------------------------------------------- +void +Slice::Builtin::destroy() +{ + // We keep a pointer to the Unit that created this builtin. + // And that Unit has a pointer to this builtin in its `contents`. + _unit = nullptr; +} + +UnitPtr +Slice::Builtin::unit() const +{ + return _unit; +} + bool Slice::Builtin::isClassType() const { @@ -878,7 +862,7 @@ Slice::Builtin::kindFromString(string_view str) return nullopt; } -Slice::Builtin::Builtin(const UnitPtr& unit, Kind kind) : SyntaxTreeBase(unit), Type(unit), _kind(kind) {} +Slice::Builtin::Builtin(UnitPtr unit, Kind kind) : _kind(kind), _unit(std::move(unit)) {} // ---------------------------------------------------------------------- // Contained @@ -916,7 +900,7 @@ Slice::Contained::scope() const string Slice::Contained::mappedName() const { - const string languageName = _unit->languageName(); + const string languageName = unit()->languageName(); assert(!languageName.empty()); // First check if any 'xxx:identifier' has been applied to this element. @@ -977,6 +961,12 @@ Slice::Contained::definitionContext() const return _definitionContext; } +UnitPtr +Slice::Contained::unit() const +{ + return _container->unit(); +} + MetadataList Slice::Contained::getMetadata() const { @@ -1066,17 +1056,14 @@ Slice::Contained::getDeprecationReason() const return (reasonMessage.empty()) ? nullopt : optional{reasonMessage}; } -Slice::Contained::Contained(const ContainerPtr& container, string name) - : SyntaxTreeBase(container->unit()), - _container(container), - _name(std::move(name)) +Slice::Contained::Contained(const ContainerPtr& container, string name) : _container(container), _name(std::move(name)) { - assert(_unit); - _file = _unit->currentFile(); - _line = _unit->currentLine(); - _docComment = _unit->currentDocComment(); - _includeLevel = _unit->currentIncludeLevel(); - _definitionContext = _unit->currentDefinitionContext(); + UnitPtr unit = container->unit(); + _file = unit->currentFile(); + _line = unit->currentLine(); + _docComment = unit->currentDocComment(); + _includeLevel = unit->currentIncludeLevel(); + _definitionContext = unit->currentDefinitionContext(); } // ---------------------------------------------------------------------- @@ -1084,27 +1071,29 @@ Slice::Contained::Contained(const ContainerPtr& container, string name) // ---------------------------------------------------------------------- void -Slice::Container::destroy() +Slice::Container::destroyContents() { + // Container has pointers to all it's contents (since it logically owns them). + // But each Contained also keeps a pointer to it's parent, creating a cycle. + // We need to break this cycle. for (const auto& i : _contents) { i->destroy(); } _contents.clear(); _introducedMap.clear(); - SyntaxTreeBase::destroy(); } ModulePtr Slice::Container::createModule(const string& name) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); matches.sort(containedCompare); // Modules can occur many times... matches.unique(containedEqual); // ... but we only want one instance of each. if (thisScope() == "::") { - _unit->addTopLevelModule(_unit->currentFile(), name); + unit()->addTopLevelModule(unit()->currentFile(), name); } for (const auto& p : matches) @@ -1118,7 +1107,7 @@ Slice::Container::createModule(const string& name) ostringstream os; os << "module '" << name << "' is capitalized inconsistently with its previous name: '" << module->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -1126,7 +1115,7 @@ Slice::Container::createModule(const string& name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << matches.front()->name() << "' as module"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } else @@ -1134,7 +1123,7 @@ Slice::Container::createModule(const string& name) ostringstream os; os << "module '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " name '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -1145,7 +1134,7 @@ Slice::Container::createModule(const string& name) } ModulePtr q = make_shared(shared_from_this(), name); - _unit->addContent(q); + unit()->addContent(q); _contents.push_back(q); return q; } @@ -1153,7 +1142,7 @@ Slice::Container::createModule(const string& name) ClassDefPtr Slice::Container::createClassDef(const string& name, int id, const ClassDefPtr& base) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); for (const auto& p : matches) { ClassDeclPtr decl = dynamic_pointer_cast(p); @@ -1171,13 +1160,13 @@ Slice::Container::createClassDef(const string& name, int id, const ClassDefPtr& ostringstream os; os << "class definition '" << name << "' is capitalized inconsistently with its previous name: '" << def->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of class '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } } else if (differsOnlyInCase) @@ -1185,13 +1174,13 @@ Slice::Container::createClassDef(const string& name, int id, const ClassDefPtr& ostringstream os; os << "class definition '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " name '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "class '" << name << "' was previously defined as " << prependA(matches.front()->kindOf()); - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1214,7 +1203,7 @@ Slice::Container::createClassDef(const string& name, int id, const ClassDefPtr& dynamic_pointer_cast(q)->_definition = def; } - _unit->addContent(def); + unit()->addContent(def); _contents.push_back(def); return def; } @@ -1222,7 +1211,7 @@ Slice::Container::createClassDef(const string& name, int id, const ClassDefPtr& ClassDeclPtr Slice::Container::createClassDecl(const string& name) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); for (const auto& p : matches) { ClassDefPtr clDef = dynamic_pointer_cast(p); @@ -1243,13 +1232,13 @@ Slice::Container::createClassDecl(const string& name) ostringstream os; os << "class declaration '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " name '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "class '" << name << "' was previously defined as " << prependA(matches.front()->kindOf()); - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1277,7 +1266,7 @@ Slice::Container::createClassDecl(const string& name) } ClassDeclPtr decl = make_shared(shared_from_this(), name); - _unit->addContent(decl); + unit()->addContent(decl); _contents.push_back(decl); return decl; } @@ -1285,7 +1274,7 @@ Slice::Container::createClassDecl(const string& name) InterfaceDefPtr Slice::Container::createInterfaceDef(const string& name, const InterfaceList& bases) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); for (const auto& p : matches) { InterfaceDeclPtr decl = dynamic_pointer_cast(p); @@ -1303,13 +1292,13 @@ Slice::Container::createInterfaceDef(const string& name, const InterfaceList& ba ostringstream os; os << "interface definition '" << name << "' is capitalized inconsistently with its previous name: '" << def->name() + "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of interface '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } } else if (differsOnlyInCase) @@ -1317,13 +1306,13 @@ Slice::Container::createInterfaceDef(const string& name, const InterfaceList& ba ostringstream os; os << "interface definition '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " name '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "interface '" << name << "' was previously defined as " << prependA(matches.front()->kindOf()); - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1333,7 +1322,7 @@ Slice::Container::createInterfaceDef(const string& name, const InterfaceList& ba return nullptr; } - InterfaceDecl::checkBasesAreLegal(name, bases, _unit); + InterfaceDecl::checkBasesAreLegal(name, bases, unit()); // Implicitly create an interface declaration for each interface definition. // This way the code generator can rely on always having an interface declaration available for lookup. @@ -1348,7 +1337,7 @@ Slice::Container::createInterfaceDef(const string& name, const InterfaceList& ba dynamic_pointer_cast(q)->_definition = def; } - _unit->addContent(def); + unit()->addContent(def); _contents.push_back(def); return def; } @@ -1356,7 +1345,7 @@ Slice::Container::createInterfaceDef(const string& name, const InterfaceList& ba InterfaceDeclPtr Slice::Container::createInterfaceDecl(const string& name) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); for (const auto& p : matches) { InterfaceDefPtr interfaceDef = dynamic_pointer_cast(p); @@ -1377,13 +1366,13 @@ Slice::Container::createInterfaceDecl(const string& name) ostringstream os; os << "interface declaration '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " name '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "interface '" << name << "' was previously defined as " << prependA(matches.front()->kindOf()); - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1408,7 +1397,7 @@ Slice::Container::createInterfaceDecl(const string& name) } InterfaceDeclPtr decl = make_shared(shared_from_this(), name); - _unit->addContent(decl); + unit()->addContent(decl); _contents.push_back(decl); return decl; } @@ -1416,21 +1405,21 @@ Slice::Container::createInterfaceDecl(const string& name) ExceptionPtr Slice::Container::createException(const string& name, const ExceptionPtr& base, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as exception"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "exception '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1443,7 +1432,7 @@ Slice::Container::createException(const string& name, const ExceptionPtr& base, } ExceptionPtr p = make_shared(shared_from_this(), name, base); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1451,21 +1440,21 @@ Slice::Container::createException(const string& name, const ExceptionPtr& base, StructPtr Slice::Container::createStruct(const string& name, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as struct"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "struct '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1478,7 +1467,7 @@ Slice::Container::createStruct(const string& name, NodeType nodeType) } StructPtr p = make_shared(shared_from_this(), name); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1486,21 +1475,21 @@ Slice::Container::createStruct(const string& name, NodeType nodeType) SequencePtr Slice::Container::createSequence(const string& name, const TypePtr& type, MetadataList metadata, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as sequence"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "sequence '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1513,7 +1502,7 @@ Slice::Container::createSequence(const string& name, const TypePtr& type, Metada } SequencePtr p = make_shared(shared_from_this(), name, type, std::move(metadata)); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1527,21 +1516,21 @@ Slice::Container::createDictionary( MetadataList valueMetadata, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as dictionary"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "dictionary '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1556,7 +1545,7 @@ Slice::Container::createDictionary( { ostringstream os; os << "dictionary '" << name << "' uses an illegal key type"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -1568,7 +1557,7 @@ Slice::Container::createDictionary( std::move(keyMetadata), valueType, std::move(valueMetadata)); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1576,21 +1565,21 @@ Slice::Container::createDictionary( EnumPtr Slice::Container::createEnum(const string& name, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as enumeration"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "enumeration '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1603,7 +1592,7 @@ Slice::Container::createEnum(const string& name, NodeType nodeType) } EnumPtr p = make_shared(shared_from_this(), name); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1617,21 +1606,21 @@ Slice::Container::createConst( const string& valueString, NodeType nodeType) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() == name) { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as constant"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "constant '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1653,7 +1642,7 @@ Slice::Container::createConst( ConstPtr p = make_shared(shared_from_this(), name, type, std::move(metadata), resolvedValueType, valueString); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -1673,10 +1662,10 @@ Slice::Container::lookupType(const string& identifier) auto kind = Builtin::kindFromString(sc); if (kind) { - return {_unit->createBuiltin(*kind)}; + return {unit()->createBuiltin(*kind)}; } - // Not a builtin type, try to look up a constructed type. + // Not a builtin type, try to look up a user-defined type. return lookupTypeNoBuiltin(identifier, true); } @@ -1694,14 +1683,14 @@ Slice::Container::lookupTypeNoBuiltin(const string& identifier, bool emitErrors, // Absolute scoped name? if (sc.size() >= 2 && sc[0] == ':') { - return _unit->lookupTypeNoBuiltin(sc.substr(2), emitErrors); + return unit()->lookupTypeNoBuiltin(sc.substr(2), emitErrors); } TypeList results; bool typeError = false; vector errors; - ContainedList matches = _unit->findContents(thisScope() + sc); + ContainedList matches = unit()->findContents(thisScope() + sc); for (const auto& p : matches) { if (dynamic_pointer_cast(p) || dynamic_pointer_cast(p)) @@ -1724,7 +1713,7 @@ Slice::Container::lookupTypeNoBuiltin(const string& identifier, bool emitErrors, { ostringstream os; os << "'" << sc << "' is an exception, which cannot be used as a type"; - _unit->error(os.str()); + unit()->error(os.str()); } return {}; } @@ -1757,7 +1746,7 @@ Slice::Container::lookupTypeNoBuiltin(const string& identifier, bool emitErrors, { ostringstream os; os << "'" << sc << "' is not defined"; - _unit->error(os.str()); + unit()->error(os.str()); } return {}; } @@ -1768,7 +1757,7 @@ Slice::Container::lookupTypeNoBuiltin(const string& identifier, bool emitErrors, { for (const auto& error : errors) { - _unit->error(error); + unit()->error(error); } } return results; @@ -1788,10 +1777,10 @@ Slice::Container::lookupContained(const string& identifier, bool emitErrors) // Absolute scoped name? if (sc.size() >= 2 && sc[0] == ':') { - return _unit->lookupContained(sc.substr(2), emitErrors); + return unit()->lookupContained(sc.substr(2), emitErrors); } - ContainedList matches = _unit->findContents(thisScope() + sc); + ContainedList matches = unit()->findContents(thisScope() + sc); ContainedList results; for (const auto& p : matches) { @@ -1807,7 +1796,7 @@ Slice::Container::lookupContained(const string& identifier, bool emitErrors) ostringstream os; os << p->kindOf() << " name '" << identifier << "' is capitalized inconsistently with its previous name: '" << p->scoped() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } } @@ -1820,7 +1809,7 @@ Slice::Container::lookupContained(const string& identifier, bool emitErrors) { ostringstream os; os << "'" << sc << "' is not defined"; - _unit->error(os.str()); + unit()->error(os.str()); } return {}; } @@ -1851,7 +1840,7 @@ Slice::Container::lookupException(const string& identifier, bool emitErrors) { ostringstream os; os << "'" << identifier << "' is not an exception"; - _unit->error(os.str()); + unit()->error(os.str()); } return nullptr; } @@ -1861,12 +1850,6 @@ Slice::Container::lookupException(const string& identifier, bool emitErrors) return exceptions.front(); } -UnitPtr -Slice::Container::unit() const -{ - return SyntaxTreeBase::unit(); -} - ModuleList Slice::Container::modules() const { @@ -2002,7 +1985,7 @@ Slice::Container::thisScope() const } void -Slice::Container::visit(ParserVisitor* visitor) +Slice::Container::visitContents(ParserVisitor* visitor) { for (const auto& p : _contents) { @@ -2094,7 +2077,7 @@ Slice::Container::checkIntroduced(const string& scopedName, ContainedPtr namedTh return true; } - _unit->error("'" + firstComponent + "' has changed meaning"); + unit()->error("'" + firstComponent + "' has changed meaning"); return false; } @@ -2109,14 +2092,12 @@ Slice::Container::checkForGlobalDefinition(const char* definitionKindPlural) { ostringstream os; os << definitionKindPlural << " can only be defined within a module"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } return true; } -Slice::Container::Container(const UnitPtr& unit) : SyntaxTreeBase(unit) {} - bool Slice::Container::validateConstant( const string& name, @@ -2144,14 +2125,14 @@ Slice::Container::validateConstant( { ostringstream os; os << "constant '" << name << "' has illegal type: '" << b->kindAsString() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "default value not allowed for data member '" << name << "' of type '" << b->kindAsString() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return false; } @@ -2162,13 +2143,13 @@ Slice::Container::validateConstant( { ostringstream os; os << "constant '" << name << "' has illegal type"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "default value not allowed for data member '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } return false; } @@ -2208,7 +2189,7 @@ Slice::Container::validateConstant( ostringstream os; os << "initializer of type '" << lt->kindAsString() << "' is incompatible with the type '" << b->kindAsString() << "' of " << desc << " '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } } @@ -2217,7 +2198,7 @@ Slice::Container::validateConstant( ostringstream os; os << "type of initializer is incompatible with the type '" << b->kindAsString() << "' of " << desc << " '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } @@ -2231,7 +2212,7 @@ Slice::Container::validateConstant( ostringstream os; os << "initializer '" << valueString << "' for " << desc << " '" << name << "' out of range for type byte"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } break; @@ -2244,7 +2225,7 @@ Slice::Container::validateConstant( ostringstream os; os << "initializer '" << valueString << "' for " << desc << " '" << name << "' out of range for type short"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } break; @@ -2257,7 +2238,7 @@ Slice::Container::validateConstant( ostringstream os; os << "initializer '" << valueString << "' for " + desc << " '" << name << "' out of range for type int"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } break; @@ -2279,7 +2260,7 @@ Slice::Container::validateConstant( { ostringstream os; os << "type of initializer is incompatible with the type of " << desc << " '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } } @@ -2293,7 +2274,7 @@ Slice::Container::validateConstant( { ostringstream os; os << "type of initializer is incompatible with the type of " << desc << " '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } EnumeratorList elist = e->enumerators(); @@ -2301,7 +2282,7 @@ Slice::Container::validateConstant( { ostringstream os; os << "enumerator '" << valueString << "' is not defined in enumeration '" << e->scoped() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } } @@ -2321,7 +2302,7 @@ Slice::Container::validateConstant( { ostringstream os; os << "'" << valueString << "' does not designate an enumerator of '" << e->scoped() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } @@ -2334,7 +2315,7 @@ Slice::Container::validateConstant( { ostringstream os; os << "type of initializer is incompatible with the type of " << desc << " '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return false; } } @@ -2360,28 +2341,18 @@ Slice::Module::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitModuleStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitModuleEnd(self); } } -Slice::Module::Module(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Contained(container, name) +void +Slice::Module::destroy() { + destroyContents(); } -// ---------------------------------------------------------------------- -// Constructed -// ---------------------------------------------------------------------- - -Slice::Constructed::Constructed(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Type(container->unit()), - Contained(container, name) -{ -} +Slice::Module::Module(const ContainerPtr& container, const string& name) : Contained(container, name) {} // ---------------------------------------------------------------------- // ClassDecl @@ -2391,7 +2362,6 @@ void Slice::ClassDecl::destroy() { _definition = nullptr; - SyntaxTreeBase::destroy(); } ClassDefPtr @@ -2436,13 +2406,7 @@ Slice::ClassDecl::visit(ParserVisitor* visitor) visitor->visitClassDecl(shared_from_this()); } -Slice::ClassDecl::ClassDecl(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name) -{ -} +Slice::ClassDecl::ClassDecl(const ContainerPtr& container, const string& name) : Contained(container, name) {} // ---------------------------------------------------------------------- // ClassDef @@ -2453,7 +2417,7 @@ Slice::ClassDef::destroy() { _declaration = nullptr; _base = nullptr; - Container::destroy(); + destroyContents(); } DataMemberPtr @@ -2465,7 +2429,7 @@ Slice::ClassDef::createDataMember( const SyntaxTreeBasePtr& defaultValueType, const string& defaultValueString) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() != name) @@ -2473,14 +2437,14 @@ Slice::ClassDef::createDataMember( ostringstream os; os << "data member '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << name << "' as data member '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -2498,7 +2462,7 @@ Slice::ClassDef::createDataMember( { ostringstream os; os << "data member '" << name << "' is already defined as a data member in a base class"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -2509,7 +2473,7 @@ Slice::ClassDef::createDataMember( ostringstream os; os << "data member '" << name << "' differs only in capitalization from data member '" << dataMember->name() << "', which is defined in a base class"; - _unit->error(os.str()); + unit()->error(os.str()); } } } @@ -2537,14 +2501,14 @@ Slice::ClassDef::createDataMember( { ostringstream os; os << "tag for optional data member '" << name << "' is already in use"; - _unit->error(os.str()); + unit()->error(os.str()); break; } } } DataMemberPtr member = make_shared(shared_from_this(), name, type, isOptional, tag, dlt, dv); - _unit->addContent(member); + unit()->addContent(member); _contents.push_back(member); return member; } @@ -2658,7 +2622,7 @@ Slice::ClassDef::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitClassDefStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitClassDefEnd(self); } } @@ -2688,15 +2652,13 @@ Slice::ClassDef::appendMetadata(MetadataList metadata) } Slice::ClassDef::ClassDef(const ContainerPtr& container, const string& name, int id, ClassDefPtr base) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Contained(container, name), + : Contained(container, name), _base(std::move(base)), _compactId(id) { if (_compactId >= 0) { - _unit->addTypeId(_compactId, scoped()); + unit()->addTypeId(_compactId, scoped()); } } @@ -2708,7 +2670,6 @@ void Slice::InterfaceDecl::destroy() { _definition = nullptr; - SyntaxTreeBase::destroy(); } InterfaceDefPtr @@ -2784,13 +2745,7 @@ Slice::InterfaceDecl::checkBasesAreLegal(const string& name, const InterfaceList } } -Slice::InterfaceDecl::InterfaceDecl(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name) -{ -} +Slice::InterfaceDecl::InterfaceDecl(const ContainerPtr& container, const string& name) : Contained(container, name) {} // Return true if the interface definition `idp` is on one of the interface lists in `gpl`, false otherwise. bool @@ -2926,7 +2881,7 @@ Slice::InterfaceDef::destroy() { _declaration = nullptr; _bases.clear(); - Container::destroy(); + destroyContents(); } OperationPtr @@ -2937,7 +2892,7 @@ Slice::InterfaceDef::createOperation( int tag, Operation::Mode mode) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() != name) @@ -2945,12 +2900,12 @@ Slice::InterfaceDef::createOperation( ostringstream os; os << "operation '" << name << "' differs only in capitalization from " << matches.front()->kindOf() << " '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } ostringstream os; os << "redefinition of " << matches.front()->kindOf() << " '" << matches.front()->name() << "' as operation '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -2959,7 +2914,7 @@ Slice::InterfaceDef::createOperation( { ostringstream os; os << "interface name '" << name << "' cannot be used as operation name"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -2970,7 +2925,7 @@ Slice::InterfaceDef::createOperation( ostringstream os; os << "operation '" << name << "' differs only in capitalization from enclosing interface name '" << this->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -2995,7 +2950,7 @@ Slice::InterfaceDef::createOperation( } OperationPtr op = make_shared(shared_from_this(), name, returnType, isOptional, tag, mode); - _unit->addContent(op); + unit()->addContent(op); _contents.push_back(op); return op; } @@ -3011,7 +2966,7 @@ Slice::InterfaceDef::checkBaseOperationNames(const string& name, const vectorerror(os.str()); + unit()->error(os.str()); return false; } @@ -3022,7 +2977,7 @@ Slice::InterfaceDef::checkBaseOperationNames(const string& name, const vectorerror(os.str()); + unit()->error(os.str()); return false; } } @@ -3112,7 +3067,7 @@ Slice::InterfaceDef::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitInterfaceDefStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitInterfaceDefEnd(self); } } @@ -3149,9 +3104,7 @@ Slice::InterfaceDef::appendMetadata(MetadataList metadata) } Slice::InterfaceDef::InterfaceDef(const ContainerPtr& container, const string& name, InterfaceList bases) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Contained(container, name), + : Contained(container, name), _bases(std::move(bases)) { } @@ -3217,7 +3170,7 @@ Slice::Operation::hasMarshaledResult() const ParameterPtr Slice::Operation::createParameter(const string& name, const TypePtr& type, bool isOutParam, bool isOptional, int tag) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() != name) @@ -3225,13 +3178,13 @@ Slice::Operation::createParameter(const string& name, const TypePtr& type, bool ostringstream os; os << "parameter '" << name << "' differs only in capitalization from parameter '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of parameter '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -3249,7 +3202,7 @@ Slice::Operation::createParameter(const string& name, const TypePtr& type, bool { ostringstream os; os << "'" << name << "': in parameters cannot follow out parameters"; - _unit->error(os.str()); + unit()->error(os.str()); } } @@ -3260,7 +3213,7 @@ Slice::Operation::createParameter(const string& name, const TypePtr& type, bool os << "tag for optional parameter '" << name << "' is already in use"; if (_returnIsOptional && tag == _returnTag) { - _unit->error(os.str()); + unit()->error(os.str()); } else { @@ -3268,7 +3221,7 @@ Slice::Operation::createParameter(const string& name, const TypePtr& type, bool { if (p->optional() && p->tag() == tag) { - _unit->error(os.str()); + unit()->error(os.str()); break; } } @@ -3276,7 +3229,7 @@ Slice::Operation::createParameter(const string& name, const TypePtr& type, bool } ParameterPtr p = make_shared(shared_from_this(), name, type, isOutParam, isOptional, tag); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -3406,7 +3359,7 @@ Slice::Operation::setExceptionList(const ExceptionList& exceptions) { os << ", '" << (*i)->name() << "'"; } - _unit->error(os.str()); + unit()->error(os.str()); } } @@ -3517,6 +3470,12 @@ Slice::Operation::visit(ParserVisitor* visitor) visitor->visitOperation(dynamic_pointer_cast(shared_from_this())); } +void +Slice::Operation::destroy() +{ + destroyContents(); +} + Slice::Operation::Operation( const ContainerPtr& container, const string& name, @@ -3524,9 +3483,7 @@ Slice::Operation::Operation( bool returnIsOptional, int returnTag, Mode mode) - : SyntaxTreeBase(container->unit()), - Contained(container, name), - Container(container->unit()), + : Contained(container, name), _returnType(std::move(returnType)), _returnIsOptional(returnIsOptional), _returnTag(returnTag), @@ -3542,7 +3499,7 @@ void Slice::Exception::destroy() { _base = nullptr; - Container::destroy(); + destroyContents(); } DataMemberPtr @@ -3554,7 +3511,7 @@ Slice::Exception::createDataMember( const SyntaxTreeBasePtr& defaultValueType, const string& defaultValueString) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() != name) @@ -3562,13 +3519,13 @@ Slice::Exception::createDataMember( ostringstream os; os << "exception member '" << name << "' differs only in capitalization from exception member '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of exception member '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -3584,7 +3541,7 @@ Slice::Exception::createDataMember( { ostringstream os; os << "exception member '" << name << "' is already defined in a base exception"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -3595,7 +3552,7 @@ Slice::Exception::createDataMember( ostringstream os; os << "exception member '" << name << "' differs only in capitalization from exception member '" << member->name() << "', which is defined in a base exception"; - _unit->error(os.str()); + unit()->error(os.str()); } } } @@ -3623,14 +3580,14 @@ Slice::Exception::createDataMember( { ostringstream os; os << "tag for optional data member '" << name << "' is already in use"; - _unit->error(os.str()); + unit()->error(os.str()); break; } } } DataMemberPtr p = make_shared(shared_from_this(), name, type, isOptional, tag, dlt, dv); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -3756,15 +3713,13 @@ Slice::Exception::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitExceptionStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitExceptionEnd(self); } } Slice::Exception::Exception(const ContainerPtr& container, const string& name, ExceptionPtr base) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Contained(container, name), + : Contained(container, name), _base(std::move(base)) { } @@ -3782,7 +3737,7 @@ Slice::Struct::createDataMember( const SyntaxTreeBasePtr& defaultValueType, const string& defaultValueString) { - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { if (matches.front()->name() != name) @@ -3790,13 +3745,13 @@ Slice::Struct::createDataMember( ostringstream os; os << "member '" << name << "' differs only in capitalization from member '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "redefinition of struct member '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } } @@ -3808,7 +3763,7 @@ Slice::Struct::createDataMember( { ostringstream os; os << "struct '" << this->name() << "' cannot contain itself"; - _unit->error(os.str()); + unit()->error(os.str()); return nullptr; } @@ -3827,7 +3782,7 @@ Slice::Struct::createDataMember( } DataMemberPtr p = make_shared(shared_from_this(), name, type, isOptional, tag, dlt, dv); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); return p; } @@ -3922,20 +3877,19 @@ Slice::Struct::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitStructStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitStructEnd(self); } } -Slice::Struct::Struct(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name) +void +Slice::Struct::destroy() { + destroyContents(); } +Slice::Struct::Struct(const ContainerPtr& container, const string& name) : Contained(container, name) {} + // ---------------------------------------------------------------------- // Sequence // ---------------------------------------------------------------------- @@ -3995,10 +3949,7 @@ Slice::Sequence::visit(ParserVisitor* visitor) } Slice::Sequence::Sequence(const ContainerPtr& container, const string& name, TypePtr type, MetadataList typeMetadata) - : SyntaxTreeBase(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name), + : Contained(container, name), _type(std::move(type)), _typeMetadata(std::move(typeMetadata)) { @@ -4139,10 +4090,7 @@ Slice::Dictionary::Dictionary( MetadataList keyMetadata, TypePtr valueType, MetadataList valueMetadata) - : SyntaxTreeBase(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name), + : Contained(container, name), _keyType(std::move(keyType)), _valueType(std::move(valueType)), _keyMetadata(std::move(keyMetadata)), @@ -4154,17 +4102,11 @@ Slice::Dictionary::Dictionary( // Enum // ---------------------------------------------------------------------- -void -Slice::Enum::destroy() -{ - SyntaxTreeBase::destroy(); -} - EnumeratorPtr Slice::Enum::createEnumerator(const string& name, optional explicitValue) { // Validate the enumerator's name. - ContainedList matches = _unit->findContents(thisScope() + name); + ContainedList matches = unit()->findContents(thisScope() + name); if (!matches.empty()) { EnumeratorPtr p = dynamic_pointer_cast(matches.front()); @@ -4172,13 +4114,13 @@ Slice::Enum::createEnumerator(const string& name, optional explicitValue) { ostringstream os; os << "redefinition of enumerator '" << name << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } else { ostringstream os; os << "enumerator '" << name << "' differs only in capitalization from '" << matches.front()->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } } checkIdentifier(name); // Ignore return value. @@ -4197,7 +4139,7 @@ Slice::Enum::createEnumerator(const string& name, optional explicitValue) { ostringstream os; os << "value for enumerator '" << name << "' is out of range"; - _unit->error(os.str()); + unit()->error(os.str()); } // If the enumerator was not assigned an explicit value, // we automatically assign it one more than the previous enumerator. @@ -4224,7 +4166,7 @@ Slice::Enum::createEnumerator(const string& name, optional explicitValue) { ostringstream os; os << "enumerator '" << name << "' has the same value as enumerator '" << r->name() << "'"; - _unit->error(os.str()); + unit()->error(os.str()); } } } @@ -4232,7 +4174,7 @@ Slice::Enum::createEnumerator(const string& name, optional explicitValue) // Create the enumerator. ContainerPtr cont = shared_from_this(); EnumeratorPtr p = make_shared(cont, name, nextValue, explicitValue.has_value()); - _unit->addContent(p); + unit()->addContent(p); _contents.push_back(p); _lastValue = nextValue; return p; @@ -4286,12 +4228,14 @@ Slice::Enum::visit(ParserVisitor* visitor) visitor->visitEnum(dynamic_pointer_cast(shared_from_this())); } +void +Slice::Enum::destroy() +{ + destroyContents(); +} + Slice::Enum::Enum(const ContainerPtr& container, const string& name) - : SyntaxTreeBase(container->unit()), - Container(container->unit()), - Type(container->unit()), - Contained(container, name), - Constructed(container, name), + : Contained(container, name), _minValue(numeric_limits::max()) { } @@ -4324,9 +4268,14 @@ Slice::Enumerator::value() const return _value; } +void +Slice::Enumerator::visit(ParserVisitor*) +{ + // TODO we should probably visit enumerators, even if only for validation purposes. +} + Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name, int value, bool hasExplicitValue) - : SyntaxTreeBase(container->unit()), - Contained(container, name), + : Contained(container, name), _hasExplicitValue(hasExplicitValue), _value(value) { @@ -4385,8 +4334,7 @@ Slice::Const::Const( MetadataList typeMetadata, SyntaxTreeBasePtr valueType, string valueString) - : SyntaxTreeBase(container->unit()), - Contained(container, name), + : Contained(container, name), _type(std::move(type)), _typeMetadata(std::move(typeMetadata)), _valueType(std::move(valueType)), @@ -4441,8 +4389,7 @@ Slice::Parameter::Parameter( bool isOutParam, bool isOptional, int tag) - : SyntaxTreeBase(container->unit()), - Contained(container, name), + : Contained(container, name), _type(std::move(type)), _isOutParam(isOutParam), _optional(isOptional), @@ -4504,8 +4451,7 @@ Slice::DataMember::DataMember( int tag, SyntaxTreeBasePtr defaultValueType, string defaultValueString) - : SyntaxTreeBase(container->unit()), - Contained(container, name), + : Contained(container, name), _type(std::move(type)), _optional(isOptional), _tag(tag), @@ -4527,9 +4473,7 @@ Slice::Unit::createUnit(string languageName, bool all, const StringList& default defaultMetadata.push_back(make_shared(metadataString, "", 0)); } - UnitPtr unit{new Unit{std::move(languageName), all, std::move(defaultMetadata)}}; - unit->_unit = unit; - return unit; + return make_shared(std::move(languageName), all, std::move(defaultMetadata)); } string @@ -4928,9 +4872,17 @@ Slice::Unit::parse(const string& filename, FILE* file, bool debugMode) void Slice::Unit::destroy() { + // Unit has a pointer to each of the builtin types (since it logically owns them). + // But each builtin also keeps a pointer to the builtin that created them. + // We need to break this cycle. + for (auto& builtin : _builtins) + { + builtin.second->destroy(); + } + destroyContents(); + _contentMap.clear(); _builtins.clear(); - Container::destroy(); } void @@ -4939,11 +4891,18 @@ Slice::Unit::visit(ParserVisitor* visitor) auto self = dynamic_pointer_cast(shared_from_this()); if (visitor->visitUnitStart(self)) { - Container::visit(visitor); + visitContents(visitor); visitor->visitUnitEnd(self); } } +UnitPtr +Slice::Unit::unit() const +{ + ContainerPtr self = const_cast(this)->shared_from_this(); + return dynamic_pointer_cast(self); +} + BuiltinPtr Slice::Unit::createBuiltin(Builtin::Kind kind) { @@ -4988,9 +4947,7 @@ Slice::Unit::getTopLevelModules(const string& file) const } Slice::Unit::Unit(string languageName, bool all, MetadataList defaultFileMetadata) - : SyntaxTreeBase(nullptr), - Container(nullptr), - _languageName(std::move(languageName)), + : _languageName(std::move(languageName)), _all(all), _defaultFileMetadata(std::move(defaultFileMetadata)) { diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h index 650c240b602..174130e7b55 100644 --- a/cpp/src/Slice/Parser.h +++ b/cpp/src/Slice/Parser.h @@ -50,7 +50,6 @@ namespace Slice class Contained; class Container; class Module; - class Constructed; class ClassDecl; class ClassDef; class InterfaceDecl; @@ -75,7 +74,6 @@ namespace Slice using ContainedPtr = std::shared_ptr; using ContainerPtr = std::shared_ptr; using ModulePtr = std::shared_ptr; - using ConstructedPtr = std::shared_ptr; using ClassDeclPtr = std::shared_ptr; using ClassDefPtr = std::shared_ptr; using InterfaceDeclPtr = std::shared_ptr; @@ -310,13 +308,7 @@ namespace Slice class SyntaxTreeBase : public GrammarBase { public: - SyntaxTreeBase(UnitPtr unit); - virtual void destroy(); - [[nodiscard]] UnitPtr unit() const; - virtual void visit(ParserVisitor* visitor); - - protected: - UnitPtr _unit; + [[nodiscard]] virtual UnitPtr unit() const = 0; }; // ---------------------------------------------------------------------- @@ -326,7 +318,6 @@ namespace Slice class Type : public virtual SyntaxTreeBase { public: - Type(const UnitPtr& unit); [[nodiscard]] virtual bool isClassType() const; [[nodiscard]] virtual bool usesClasses() const; [[nodiscard]] virtual size_t minWireSize() const = 0; @@ -338,7 +329,7 @@ namespace Slice // Builtin // ---------------------------------------------------------------------- - class Builtin final : public virtual Type + class Builtin final : public Type { public: enum Kind @@ -356,7 +347,9 @@ namespace Slice KindValue }; - Builtin(const UnitPtr& unit, Kind kind); + Builtin(UnitPtr unit, Kind kind); + void destroy(); + [[nodiscard]] UnitPtr unit() const final; [[nodiscard]] bool isClassType() const final; [[nodiscard]] size_t minWireSize() const final; @@ -376,6 +369,7 @@ namespace Slice private: const Kind _kind; + UnitPtr _unit; }; // ---------------------------------------------------------------------- @@ -385,6 +379,7 @@ namespace Slice class Contained : public virtual SyntaxTreeBase { public: + virtual void destroy() {} [[nodiscard]] ContainerPtr container() const; /// Returns the Slice identifier of this element. @@ -409,6 +404,7 @@ namespace Slice [[nodiscard]] int includeLevel() const; [[nodiscard]] DefinitionContextPtr definitionContext() const; + [[nodiscard]] UnitPtr unit() const final; [[nodiscard]] virtual MetadataList getMetadata() const; virtual void setMetadata(MetadataList metadata); @@ -427,6 +423,7 @@ namespace Slice /// @return The message provided to the 'deprecated' metadata, if present. [[nodiscard]] std::optional getDeprecationReason() const; + virtual void visit(ParserVisitor* visitor) = 0; [[nodiscard]] virtual std::string kindOf() const = 0; protected: @@ -449,8 +446,7 @@ namespace Slice class Container : public virtual SyntaxTreeBase, public std::enable_shared_from_this { public: - Container(const UnitPtr& unit); - void destroy() override; + void destroyContents(); ModulePtr createModule(const std::string& name); [[nodiscard]] ClassDefPtr createClassDef(const std::string& name, int id, const ClassDefPtr& base); [[nodiscard]] ClassDeclPtr createClassDecl(const std::string& name); @@ -481,14 +477,13 @@ namespace Slice lookupTypeNoBuiltin(const std::string& identifier, bool emitErrors, bool ignoreUndefined = false); [[nodiscard]] ContainedList lookupContained(const std::string& identifier, bool emitErrors); [[nodiscard]] ExceptionPtr lookupException(const std::string& identifier, bool emitErrors); - [[nodiscard]] UnitPtr unit() const; [[nodiscard]] ModuleList modules() const; [[nodiscard]] InterfaceList interfaces() const; [[nodiscard]] EnumList enums() const; [[nodiscard]] EnumeratorList enumerators() const; [[nodiscard]] EnumeratorList enumerators(const std::string& identifier) const; [[nodiscard]] ContainedList contents() const; - void visit(ParserVisitor* visitor) override; + void visitContents(ParserVisitor* visitor); bool checkIntroduced(const std::string& scopedName, ContainedPtr namedThing = nullptr); @@ -534,29 +529,20 @@ namespace Slice // Module // ---------------------------------------------------------------------- - class Module final : public virtual Container, public virtual Contained + class Module final : public Container, public Contained { public: Module(const ContainerPtr& container, const std::string& name); [[nodiscard]] std::string kindOf() const final; void visit(ParserVisitor* visitor) final; - }; - - // ---------------------------------------------------------------------- - // Constructed - // ---------------------------------------------------------------------- - - class Constructed : public virtual Type, public virtual Contained - { - public: - Constructed(const ContainerPtr& container, const std::string& name); + void destroy() final; }; // ---------------------------------------------------------------------- // ClassDecl // ---------------------------------------------------------------------- - class ClassDecl final : public virtual Constructed, public std::enable_shared_from_this + class ClassDecl final : public Contained, public Type, public std::enable_shared_from_this { public: ClassDecl(const ContainerPtr& container, const std::string& name); @@ -583,10 +569,10 @@ namespace Slice // Note: For the purpose of this parser, a class definition is not // considered to be a type, but a class declaration is. And each class // definition has at least one class declaration (but not vice versa), - // so if you need the class as a "constructed type", use the + // so if you need the class as a "type", use the // declaration() operation to navigate to the class declaration. // - class ClassDef final : public virtual Container, public virtual Contained + class ClassDef final : public Container, public Contained { public: ClassDef(const ContainerPtr& container, const std::string& name, int id, ClassDefPtr base); @@ -628,7 +614,7 @@ namespace Slice // InterfaceDecl // ---------------------------------------------------------------------- - class InterfaceDecl final : public virtual Constructed, public std::enable_shared_from_this + class InterfaceDecl final : public Contained, public Type, public std::enable_shared_from_this { public: InterfaceDecl(const ContainerPtr& container, const std::string& name); @@ -667,7 +653,7 @@ namespace Slice // Operation // ---------------------------------------------------------------------- - class Operation final : public virtual Contained, public virtual Container + class Operation final : public Container, public Contained { public: // @@ -706,6 +692,7 @@ namespace Slice [[nodiscard]] std::optional format() const; [[nodiscard]] std::string kindOf() const final; void visit(ParserVisitor* visitor) final; + void destroy() final; private: TypePtr _returnType; @@ -723,10 +710,10 @@ namespace Slice // Note: For the purpose of this parser, an interface definition is not // considered to be a type, but an interface declaration is. And each interface // definition has at least one interface declaration (but not vice versa), - // so if you need the interface as a "constructed type", use the + // so if you need the interface as a "type", use the // declaration() function to navigate to the interface declaration. // - class InterfaceDef final : public virtual Container, public virtual Contained + class InterfaceDef final : public Container, public Contained { public: InterfaceDef(const ContainerPtr& container, const std::string& name, InterfaceList bases); @@ -768,9 +755,7 @@ namespace Slice // ---------------------------------------------------------------------- // Exception // ---------------------------------------------------------------------- - - // No inheritance from Constructed, as this is not a Type - class Exception final : public virtual Container, public virtual Contained + class Exception final : public Container, public Contained { public: Exception(const ContainerPtr& container, const std::string& name, ExceptionPtr base); @@ -801,7 +786,7 @@ namespace Slice // Struct // ---------------------------------------------------------------------- - class Struct final : public virtual Container, public virtual Constructed + class Struct final : public Container, public Contained, public Type { public: Struct(const ContainerPtr& container, const std::string& name); @@ -820,13 +805,14 @@ namespace Slice [[nodiscard]] bool isVariableLength() const final; [[nodiscard]] std::string kindOf() const final; void visit(ParserVisitor* visitor) final; + void destroy() final; }; // ---------------------------------------------------------------------- // Sequence // ---------------------------------------------------------------------- - class Sequence final : public virtual Constructed, public std::enable_shared_from_this + class Sequence final : public Contained, public Type, public std::enable_shared_from_this { public: Sequence(const ContainerPtr& container, const std::string& name, TypePtr type, MetadataList typeMetadata); @@ -849,7 +835,7 @@ namespace Slice // Dictionary // ---------------------------------------------------------------------- - class Dictionary final : public virtual Constructed, public std::enable_shared_from_this + class Dictionary final : public Contained, public Type, public std::enable_shared_from_this { public: Dictionary( @@ -885,11 +871,10 @@ namespace Slice // Enum // ---------------------------------------------------------------------- - class Enum final : public virtual Container, public virtual Constructed + class Enum final : public Container, public Contained, public Type { public: Enum(const ContainerPtr& container, const std::string& name); - void destroy() final; EnumeratorPtr createEnumerator(const std::string& name, std::optional explicitValue); [[nodiscard]] bool hasExplicitValues() const; [[nodiscard]] int minValue() const; @@ -899,6 +884,7 @@ namespace Slice [[nodiscard]] bool isVariableLength() const final; [[nodiscard]] std::string kindOf() const final; void visit(ParserVisitor* visitor) final; + void destroy() final; private: bool _hasExplicitValues{false}; @@ -911,7 +897,7 @@ namespace Slice // Enumerator // ---------------------------------------------------------------------- - class Enumerator final : public virtual Contained + class Enumerator final : public Contained { public: Enumerator(const ContainerPtr& container, const std::string& name, int value, bool hasExplicitValue); @@ -921,6 +907,8 @@ namespace Slice [[nodiscard]] bool hasExplicitValue() const; [[nodiscard]] int value() const; + void visit(ParserVisitor* visitor) final; + private: bool _hasExplicitValue; int _value; @@ -930,7 +918,7 @@ namespace Slice // Const // ---------------------------------------------------------------------- - class Const final : public virtual Contained, public std::enable_shared_from_this + class Const final : public Contained, public std::enable_shared_from_this { public: Const( @@ -959,7 +947,7 @@ namespace Slice // Parameter // ---------------------------------------------------------------------- - class Parameter final : public virtual Contained, public std::enable_shared_from_this + class Parameter final : public Contained, public std::enable_shared_from_this { public: Parameter( @@ -987,7 +975,7 @@ namespace Slice // DataMember // ---------------------------------------------------------------------- - class DataMember final : public virtual Contained, public std::enable_shared_from_this + class DataMember final : public Contained, public std::enable_shared_from_this { public: DataMember( @@ -1018,11 +1006,12 @@ namespace Slice // Unit // ---------------------------------------------------------------------- - class Unit final : public virtual Container + class Unit final : public Container { public: static UnitPtr createUnit(std::string languageName, bool all, const StringList& defaultFileMetadata = StringList()); + Unit(std::string languageName, bool all, MetadataList defaultFileMetadata); [[nodiscard]] std::string languageName() const; @@ -1066,8 +1055,9 @@ namespace Slice int parse(const std::string& filename, FILE* file, bool debugMode); - void destroy() final; - void visit(ParserVisitor* visitor) final; + void destroy(); + void visit(ParserVisitor* visitor); + [[nodiscard]] UnitPtr unit() const final; // Not const, as builtins are created on the fly. (Lazy initialization.) BuiltinPtr createBuiltin(Builtin::Kind kind); @@ -1076,8 +1066,6 @@ namespace Slice [[nodiscard]] std::set getTopLevelModules(const std::string& file) const; private: - Unit(std::string languageName, bool all, MetadataList defaultFileMetadata); - void pushDefinitionContext(); void popDefinitionContext(); diff --git a/cpp/src/ice2slice/Gen.cpp b/cpp/src/ice2slice/Gen.cpp index 32efca21b7a..9bcf67243d2 100644 --- a/cpp/src/ice2slice/Gen.cpp +++ b/cpp/src/ice2slice/Gen.cpp @@ -734,9 +734,9 @@ Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) } else { - auto constructed = dynamic_pointer_cast(p->type()); - assert(constructed); - typeString = constructed->scoped(); + auto contained = dynamic_pointer_cast(p->type()); + assert(contained); + typeString = contained->scoped(); } Output& out = getOutput(p); diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 5f2ce485309..e8b384d9213 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -423,10 +423,9 @@ namespace if (dynamic_pointer_cast(p) || dynamic_pointer_cast(p) || dynamic_pointer_cast(p) || dynamic_pointer_cast(p)) { - UnitPtr unt = p->container()->unit(); string file = p->file(); assert(!file.empty()); - DefinitionContextPtr dc = unt->findDefinitionContext(file); + DefinitionContextPtr dc = p->unit()->findDefinitionContext(file); assert(dc); // TODO: why do we ignore all instances of this metadata except the first? diff --git a/cpp/src/slice2cs/CsUtil.cpp b/cpp/src/slice2cs/CsUtil.cpp index 65fb24e54c5..dcacbabc001 100644 --- a/cpp/src/slice2cs/CsUtil.cpp +++ b/cpp/src/slice2cs/CsUtil.cpp @@ -551,7 +551,7 @@ Slice::CsGenerator::writeMarshalUnmarshalCode( return; } - assert(dynamic_pointer_cast(type)); + assert(dynamic_pointer_cast(type)); string helperName; DictionaryPtr d = dynamic_pointer_cast(type); if (d) diff --git a/cpp/src/slice2java/JavaUtil.cpp b/cpp/src/slice2java/JavaUtil.cpp index 2748952526a..80272e0c909 100644 --- a/cpp/src/slice2java/JavaUtil.cpp +++ b/cpp/src/slice2java/JavaUtil.cpp @@ -1133,9 +1133,8 @@ Slice::JavaGenerator::writeMarshalUnmarshalCode( return; } - ConstructedPtr constructed = dynamic_pointer_cast(type); + assert(dynamic_pointer_cast(type)); StructPtr st = dynamic_pointer_cast(type); - assert(constructed); if (marshal) { if (optionalParam) diff --git a/cpp/src/slice2php/Main.cpp b/cpp/src/slice2php/Main.cpp index 70e6efb5ffb..e79c6a927b0 100644 --- a/cpp/src/slice2php/Main.cpp +++ b/cpp/src/slice2php/Main.cpp @@ -297,7 +297,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // ('MemberName', MemberType, Optional, Tag) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. if (!members.empty()) { _out << "array("; @@ -635,7 +635,7 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // ('MemberName', MemberType, Optional, Tag) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. if (!members.empty()) { _out << "array("; @@ -739,7 +739,7 @@ CodeVisitor::visitStructStart(const StructPtr& p) // // ('MemberName', MemberType) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. for (auto r = memberList.begin(); r != memberList.end(); ++r) { if (r != memberList.begin()) diff --git a/cpp/src/slice2py/PythonUtil.cpp b/cpp/src/slice2py/PythonUtil.cpp index 20fe502109a..2aedd203dbe 100644 --- a/cpp/src/slice2py/PythonUtil.cpp +++ b/cpp/src/slice2py/PythonUtil.cpp @@ -667,7 +667,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // ('MemberName', MemberMetadata, MemberType, Optional, Tag) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // if (members.size() > 1) { @@ -1215,7 +1215,7 @@ Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // ('MemberName', MemberMetadata, MemberType, Optional, Tag) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // for (auto dmli = members.begin(); dmli != members.end(); ++dmli) { @@ -1485,7 +1485,7 @@ Slice::Python::CodeVisitor::visitStructStart(const StructPtr& p) // // ('MemberName', MemberMetadata, MemberType) // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // if (memberList.size() > 1) { diff --git a/cpp/src/slice2rb/RubyUtil.cpp b/cpp/src/slice2rb/RubyUtil.cpp index 1b74ea08b13..d3516773999 100644 --- a/cpp/src/slice2rb/RubyUtil.cpp +++ b/cpp/src/slice2rb/RubyUtil.cpp @@ -367,7 +367,7 @@ Slice::Ruby::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // ['MemberName', MemberType, Optional, Tag] // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // _out << "["; if (members.size() > 1) @@ -696,7 +696,7 @@ Slice::Ruby::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // ['MemberName', MemberType, Optional, Tag] // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // for (auto dmli = members.begin(); dmli != members.end(); ++dmli) { @@ -832,7 +832,7 @@ Slice::Ruby::CodeVisitor::visitStructStart(const StructPtr& p) // // ['MemberName', MemberType] // - // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. + // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a user-defined type. // if (memberList.size() > 1) {