diff options
Diffstat (limited to 'cpp/src/Slice/Parser.cpp')
-rw-r--r-- | cpp/src/Slice/Parser.cpp | 579 |
1 files changed, 418 insertions, 161 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 8ee39d6e8bb..e1a88c3f559 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -63,6 +63,56 @@ filterOrderedOptionalDataMembers(const DataMemberList& members) return result; } +void +sortOptionalParameters(ParamDeclList& params) +{ + // + // Sort optional parameters by tag. + // + class SortFn + { + public: + static bool compare(const ParamDeclPtr& lhs, const ParamDeclPtr& rhs) + { + return lhs->tag() < rhs->tag(); + } + }; + params.sort(SortFn::compare); +} + +bool +isMutableAfterReturnType(const TypePtr& type) +{ + // + // Returns true if the type contains data types which can be referenced by user code + // and mutated after a dispatch returns. + // + + if(ClassDeclPtr::dynamicCast(type)) + { + return true; + } + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin && (builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindValue)) + { + return true; + } + + if(SequencePtr::dynamicCast(type) || DictionaryPtr::dynamicCast(type)) + { + return true; + } + + StructPtr s = StructPtr::dynamicCast(type); + if(s) + { + return true; + } + + return false; +} + } namespace Slice @@ -258,6 +308,11 @@ Slice::Builtin::typeId() const return "::Ice::LocalObject"; break; } + case KindValue: + { + return "::Ice::Value"; + break; + } } assert(false); return ""; // Keep the compiler happy. @@ -266,7 +321,7 @@ Slice::Builtin::typeId() const bool Slice::Builtin::usesClasses() const { - return _kind == KindObject; + return _kind == KindObject || _kind == KindValue; } size_t @@ -283,7 +338,8 @@ Slice::Builtin::minWireSize() const 8, // KindDouble 1, // KindString: at least one byte for an empty string. 1, // KindObject: at least one byte (to marshal an index instead of an instance). - 2 // KindObjectProxy: at least an empty identity for a nil proxy, that is, 2 bytes. + 2, // KindObjectProxy: at least an empty identity for a nil proxy, that is, 2 bytes. + 1 // KindValue: at least one byte (to marshal an index instead of an instance). }; assert(_kind != KindLocalObject); @@ -293,7 +349,7 @@ Slice::Builtin::minWireSize() const bool Slice::Builtin::isVariableLength() const { - return _kind == KindString || _kind == KindObject || _kind == KindObjectProxy; + return _kind == KindString || _kind == KindObject || _kind == KindObjectProxy || _kind == KindValue; } Builtin::Kind @@ -320,7 +376,8 @@ const char* Slice::Builtin::builtinTable[] = "string", "Object", "Object*", - "LocalObject" + "LocalObject", + "Value" }; Slice::Builtin::Builtin(const UnitPtr& unit, Kind kind) : @@ -496,12 +553,6 @@ Slice::Contained::operator==(const Contained& rhs) const return _scoped == rhs._scoped; } -bool -Slice::Contained::operator!=(const Contained& rhs) const -{ - return _scoped != rhs._scoped; -} - Slice::Contained::Contained(const ContainerPtr& container, const string& name) : SyntaxTreeBase(container->unit()), _container(container), @@ -876,17 +927,6 @@ Slice::Container::createSequence(const string& name, const TypePtr& type, const { checkIdentifier(name); - if(_unit->profile() == IceE && !local) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(type)) - { - string msg = "Sequence `" + name + "' cannot contain object values."; - _unit->error(msg); - return 0; - } - } - ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { @@ -942,17 +982,6 @@ Slice::Container::createDictionary(const string& name, const TypePtr& keyType, c { checkIdentifier(name); - if(_unit->profile() == IceE && !local) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(valueType); - if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(valueType)) - { - string msg = "Dictionary `" + name + "' cannot contain object values."; - _unit->error(msg); - return 0; - } - } - ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { @@ -1178,16 +1207,8 @@ Slice::Container::lookupType(const string& scoped, bool printError) return lookupTypeNoBuiltin(scoped, printError); } -// -// TODO: Hack to keep binary compatibility with Ice 3.6.0, fix properly in Ice 3.7 -// -namespace -{ -bool ignoreUndefined = false; -} - TypeList -Slice::Container::lookupTypeNoBuiltin(const string& scoped, bool printError) +Slice::Container::lookupTypeNoBuiltin(const string& scoped, bool printError, bool ignoreUndefined) { // // Remove whitespace. @@ -1304,12 +1325,7 @@ Slice::Container::lookupTypeNoBuiltin(const string& scoped, bool printError) ContainedPtr contained = ContainedPtr::dynamicCast(this); if(contained) { - if(typeError) - { - ignoreUndefined = true; - } - results = contained->container()->lookupTypeNoBuiltin(sc, printError); - ignoreUndefined = false; + results = contained->container()->lookupTypeNoBuiltin(sc, printError, typeError || ignoreUndefined); } else if(!typeError) { @@ -1610,7 +1626,7 @@ Slice::Container::hasLocalClassDefsWithAsync() const ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); if(cl && cl->isLocal()) { - if(cl->hasMetaData("async")) + if(cl->hasMetaData("async-oneway")) { return true; } @@ -1618,7 +1634,7 @@ Slice::Container::hasLocalClassDefsWithAsync() const OperationList ol = cl->operations(); for(OperationList::const_iterator q = ol.begin(); q != ol.end(); ++q) { - if((*q)->hasMetaData("async")) + if((*q)->hasMetaData("async-oneway")) { return true; } @@ -1677,7 +1693,47 @@ Slice::Container::hasNonLocalExceptions() const return false; } +bool +Slice::Container::hasStructs() const +{ + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + StructPtr q = StructPtr::dynamicCast(*p); + if(q) + { + return true; + } + + ContainerPtr container = ContainerPtr::dynamicCast(*p); + if(container && container->hasStructs()) + { + return true; + } + } + return false; +} + +bool +Slice::Container::hasExceptions() const +{ + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ExceptionPtr q = ExceptionPtr::dynamicCast(*p); + if(q) + { + return true; + } + + ContainerPtr container = ContainerPtr::dynamicCast(*p); + if(container && container->hasExceptions()) + { + return true; + } + } + + return false; +} bool Slice::Container::hasClassDecls() const @@ -1775,6 +1831,66 @@ Slice::Container::hasClassDefs() const } bool +Slice::Container::hasLocalClassDefs() const +{ + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); + if(cl && cl->isLocal()) + { + return true; + } + + ContainerPtr container = ContainerPtr::dynamicCast(*p); + if(container && container->hasLocalClassDefs()) + { + return true; + } + } + return false; +} + +bool +Slice::Container::hasNonLocalInterfaceDefs() const +{ + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); + if(cl && !cl->isLocal() && (cl->isInterface() || !cl->allOperations().empty())) + { + return true; + } + + ContainerPtr container = ContainerPtr::dynamicCast(*p); + if(container && container->hasNonLocalInterfaceDefs()) + { + return true; + } + } + return false; +} + +bool +Slice::Container::hasValueDefs() const +{ + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ClassDefPtr cl = ClassDefPtr::dynamicCast(*p); + if(cl && !cl->isLocal() && !cl->isInterface()) + { + return true; + } + + ContainerPtr container = ContainerPtr::dynamicCast(*p); + if(container && container->hasValueDefs()) + { + return true; + } + } + return false; +} + +bool Slice::Container::hasOnlyClassDecls() const { for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) @@ -2575,6 +2691,7 @@ Slice::Container::validateConstant(const string& name, const TypePtr& type, cons case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: + case Builtin::KindValue: { assert(false); break; @@ -3199,28 +3316,6 @@ Slice::ClassDef::createDataMember(const string& name, const TypePtr& type, bool { checkIdentifier(name); - if(_unit->profile() == IceE) - { - if(!isLocal()) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if((builtin && builtin->kind() == Builtin::KindObject)) - { - string msg = "Class data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - - ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); - if(classDecl != 0 && !classDecl->isLocal()) - { - string msg = "Class data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - } - } - assert(!isInterface()); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) @@ -3456,7 +3551,9 @@ Slice::ClassDef::classDataMembers() const if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); - if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) + if((builtin && builtin->kind() == Builtin::KindObject) || + (builtin && builtin->kind() == Builtin::KindValue) || + ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } @@ -3603,6 +3700,17 @@ Slice::ClassDef::inheritsMetaData(const string& meta) const return false; } +bool +Slice::ClassDef::hasBaseDataMembers() const +{ + if(!_bases.empty() && !_bases.front()->isInterface()) + { + return !_bases.front()->allDataMembers().empty(); + } + + return false; +} + Contained::ContainedType Slice::ClassDef::containedType() const { @@ -3645,6 +3753,11 @@ Slice::ClassDef::compactId() const return _compactId; } +bool +Slice::ClassDef::isDelegate() const +{ + return isLocal() && isInterface() && hasMetaData("delegate") && allOperations().size() == 1; +} Slice::ClassDef::ClassDef(const ContainerPtr& container, const string& name, int id, bool intf, const ClassList& bases, bool local) : SyntaxTreeBase(container->unit()), @@ -3739,28 +3852,6 @@ Slice::Exception::createDataMember(const string& name, const TypePtr& type, bool { checkIdentifier(name); - if(_unit->profile() == IceE) - { - if(!isLocal()) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if((builtin && builtin->kind() == Builtin::KindObject)) - { - string msg = "Exception data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - - ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); - if(classDecl != 0 && !classDecl->isLocal()) - { - string msg = "Exception data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - } - } - ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { @@ -3925,7 +4016,9 @@ Slice::Exception::classDataMembers() const if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); - if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) + if((builtin && builtin->kind() == Builtin::KindObject) || + (builtin && builtin->kind() == Builtin::KindValue) || + ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } @@ -4059,6 +4152,12 @@ Slice::Exception::inheritsMetaData(const string& meta) const return false; } +bool +Slice::Exception::hasBaseDataMembers() const +{ + return _base && !_base->allDataMembers().empty(); +} + string Slice::Exception::kindOf() const { @@ -4093,29 +4192,6 @@ Slice::Struct::createDataMember(const string& name, const TypePtr& type, bool op const SyntaxTreeBasePtr& defaultValueType, const string& defaultValue, const string& defaultLiteral) { - checkIdentifier(name); - - if(_unit->profile() == IceE) - { - if(!isLocal()) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if((builtin && builtin->kind() == Builtin::KindObject)) - { - string msg = "Struct data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); - if(classDecl != 0 && !classDecl->isLocal()) - { - string msg = "Struct data member `" + name + "' cannot be a value object."; - _unit->error(msg); - return 0; - } - } - } - ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { @@ -4230,7 +4306,9 @@ Slice::Struct::classDataMembers() const if(q) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(q->type()); - if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(q->type())) + if((builtin && builtin->kind() == Builtin::KindObject) || + (builtin && builtin->kind() == Builtin::KindValue) || + ClassDeclPtr::dynamicCast(q->type())) { result.push_back(q); } @@ -4569,6 +4647,7 @@ Slice::Dictionary::legalKeyType(const TypePtr& type, bool& containsSequence) case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: + case Builtin::KindValue: { return false; break; @@ -4941,33 +5020,33 @@ Slice::Operation::sendMode() const } } -ParamDeclPtr -Slice::Operation::createParamDecl(const string& name, const TypePtr& type, bool isOutParam, bool optional, int tag) +bool +Slice::Operation::hasMarshaledResult() const { - checkIdentifier(name); - - if(_unit->profile() == IceE) + ClassDefPtr cl = ClassDefPtr::dynamicCast(container()); + assert(cl); + if(cl->hasMetaData("marshaled-result") || hasMetaData("marshaled-result")) { - ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container()); - assert(cl); - if(!cl->isLocal()) + if(returnType() && isMutableAfterReturnType(returnType())) { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if((builtin && builtin->kind() == Builtin::KindObject)) - { - string msg = "Object `" + name + "' cannot be passed by value."; - _unit->error(msg); - return 0; - } - ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(type); - if(classDecl != 0 && !classDecl->isLocal()) + return true; + } + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ParamDeclPtr q = ParamDeclPtr::dynamicCast(*p); + if(q->isOutParam() && isMutableAfterReturnType(q->type())) { - string msg = "Object `" + name + "' cannot be passed by value."; - _unit->error(msg); - return 0; + return true; } } } + return false; +} + +ParamDeclPtr +Slice::Operation::createParamDecl(const string& name, const TypePtr& type, bool isOutParam, bool optional, int tag) +{ + checkIdentifier(name); ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) @@ -5067,6 +5146,74 @@ Slice::Operation::parameters() const return result; } +ParamDeclList +Slice::Operation::inParameters() const +{ + ParamDeclList result; + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ParamDeclPtr q = ParamDeclPtr::dynamicCast(*p); + if(q && !q->isOutParam()) + { + result.push_back(q); + } + } + return result; +} + +void +Slice::Operation::inParameters(ParamDeclList& required, ParamDeclList& optional) const +{ + const ParamDeclList params = inParameters(); + for(ParamDeclList::const_iterator pli = params.begin(); pli != params.end(); ++pli) + { + if((*pli)->optional()) + { + optional.push_back(*pli); + } + else + { + required.push_back(*pli); + } + } + + sortOptionalParameters(optional); +} + +ParamDeclList +Slice::Operation::outParameters() const +{ + ParamDeclList result; + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ParamDeclPtr q = ParamDeclPtr::dynamicCast(*p); + if(q && q->isOutParam()) + { + result.push_back(q); + } + } + return result; +} + +void +Slice::Operation::outParameters(ParamDeclList& required, ParamDeclList& optional) const +{ + const ParamDeclList params = outParameters(); + for(ParamDeclList::const_iterator pli = params.begin(); pli != params.end(); ++pli) + { + if((*pli)->optional()) + { + optional.push_back(*pli); + } + else + { + required.push_back(*pli); + } + } + + sortOptionalParameters(optional); +} + ExceptionList Slice::Operation::throws() const { @@ -5219,12 +5366,25 @@ Slice::Operation::returnsData() const } bool +Slice::Operation::returnsMultipleValues() const +{ + size_t count = outParameters().size(); + + if(returnType()) + { + ++count; + } + + return count > 1; +} + +bool Slice::Operation::sendsOptionals() const { - ParamDeclList pdl = parameters(); + ParamDeclList pdl = inParameters(); for(ParamDeclList::const_iterator i = pdl.begin(); i != pdl.end(); ++i) { - if(!(*i)->isOutParam() && (*i)->optional()) + if((*i)->optional()) { return true; } @@ -5356,26 +5516,6 @@ Slice::Operation::Operation(const ContainerPtr& container, _returnTag(returnTag), _mode(mode) { - if(_unit->profile() == IceE) - { - ClassDefPtr cl = ClassDefPtr::dynamicCast(this->container()); - assert(cl); - if(!cl->isLocal()) - { - BuiltinPtr builtin = BuiltinPtr::dynamicCast(returnType); - if((builtin && builtin->kind() == Builtin::KindObject)) - { - string msg = "Method `" + name + "' cannot return an object by value."; - _unit->error(msg); - } - ClassDeclPtr classDecl = ClassDeclPtr::dynamicCast(returnType); - if(classDecl != 0 && !classDecl->isLocal()) - { - string msg = "Method `" + name + "' cannot return an object by value."; - _unit->error(msg); - } - } - } } // ---------------------------------------------------------------------- @@ -6038,6 +6178,11 @@ Slice::Unit::usesNonLocals() const return true; } + if(_builtins.find(Builtin::KindValue) != _builtins.end()) + { + return true; + } + return false; } @@ -6130,6 +6275,11 @@ Slice::Unit::parse(const string& filename, FILE* file, bool debug, Slice::Featur popContainer(); assert(_definitionContextStack.size() == 1); popDefinitionContext(); + + if(!checkUndefinedTypes()) + { + status = EXIT_FAILURE; + } } Slice::unit = 0; @@ -6228,6 +6378,113 @@ Slice::Unit::eraseWhiteSpace(string& s) } } +bool +Slice::Unit::checkUndefinedTypes() +{ + class Visitor : public ParserVisitor + { + public: + + Visitor(int& errors) : + _errors(errors), + _local(false) + { + } + + virtual bool visitClassDefStart(const ClassDefPtr& p) + { + _local = p->isLocal(); + return true; + } + + virtual bool visitExceptionStart(const ExceptionPtr& p) + { + _local = p->isLocal(); + return true; + } + + virtual bool visitStructStart(const StructPtr& p) + { + _local = p->isLocal(); + return true; + } + + virtual void visitOperation(const OperationPtr& p) + { + if(p->returnType()) + { + checkUndefined(p->returnType(), "return type", p->file(), p->line()); + } + ParamDeclList params = p->parameters(); + for(ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q) + { + checkUndefined((*q)->type(), "parameter " + (*q)->name(), (*q)->file(), (*q)->line()); + } + } + + virtual void visitParamDecl(const ParamDeclPtr& p) + { + checkUndefined(p->type(), "parameter " + p->name(), p->file(), p->line()); + } + + virtual void visitDataMember(const DataMemberPtr& p) + { + checkUndefined(p->type(), "member " + p->name(), p->file(), p->line()); + } + + virtual void visitSequence(const SequencePtr& p) + { + _local = p->isLocal(); + checkUndefined(p->type(), "element type", p->file(), p->line()); + } + + virtual void visitDictionary(const DictionaryPtr& p) + { + _local = p->isLocal(); + checkUndefined(p->keyType(), "key type", p->file(), p->line()); + checkUndefined(p->valueType(), "value type", p->file(), p->line()); + } + + private: + + void checkUndefined(const TypePtr& type, const string& desc, const string& file, const string& line) + { + // + // See ICE-6867. Any use of a proxy requires the full type definition, as does any + // use of a class in a non-local context. + // + ProxyPtr p = ProxyPtr::dynamicCast(type); + if(p) + { + const ClassDeclPtr cl = p->_class(); + if(!cl->definition()) + { + ostringstream ostr; + ostr << desc << " uses a proxy for undefined type `" << cl->scoped() << "'"; + emitError(file, line, ostr.str()); + _errors++; + } + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl && !cl->definition() && !_local) + { + ostringstream ostr; + ostr << desc << " refers to undefined type `" << cl->scoped() << "'"; + emitError(file, line, ostr.str()); + _errors++; + } + } + + int& _errors; + bool _local; + }; + + Visitor v(_errors); + visit(&v, true); + return _errors == 0; +} + // ---------------------------------------------------------------------- // CICompare // ---------------------------------------------------------------------- |