diff options
author | Bernard Normier <bernard@zeroc.com> | 2017-02-08 09:41:55 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2017-02-08 09:41:55 -0500 |
commit | af38cbf2ebf9c009fcea81cc316be64176da620e (patch) | |
tree | 28d6975bf5f1c4b7b89a5c24d2e1d9f1a2ba633c /cpp/src/Slice/Parser.cpp | |
parent | Added wide char overloads of Ice::createProperties & Ice::initialize (diff) | |
download | ice-af38cbf2ebf9c009fcea81cc316be64176da620e.tar.bz2 ice-af38cbf2ebf9c009fcea81cc316be64176da620e.tar.xz ice-af38cbf2ebf9c009fcea81cc316be64176da620e.zip |
Make Slice enums scoped
Add new cpp:scoped and objc:scoped metadata directives
Diffstat (limited to 'cpp/src/Slice/Parser.cpp')
-rw-r--r-- | cpp/src/Slice/Parser.cpp | 327 |
1 files changed, 215 insertions, 112 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 656da795cf4..de6ad85bb96 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -1167,13 +1167,8 @@ Slice::Container::createEnum(const string& name, bool local, NodeType nt) EnumeratorPtr Slice::Container::createEnumerator(const string& name) { - EnumeratorPtr p = validateEnumerator(name); - if(p) - { - return p; - } - - p = new Enumerator(this, name); + validateEnumerator(name); + EnumeratorPtr p = new Enumerator(this, name); _contents.push_back(p); return p; } @@ -1181,13 +1176,8 @@ Slice::Container::createEnumerator(const string& name) EnumeratorPtr Slice::Container::createEnumerator(const string& name, int value) { - EnumeratorPtr p = validateEnumerator(name); - if(p) - { - return p; - } - - p = new Enumerator(this, name, value); + validateEnumerator(name); + EnumeratorPtr p = new Enumerator(this, name, value); _contents.push_back(p); return p; } @@ -1233,15 +1223,17 @@ Slice::Container::createConst(const string name, const TypePtr& constType, const checkForGlobalDef(name, "constant"); // Don't return here -- we create the constant anyway. } + SyntaxTreeBasePtr resolvedValueType = valueType; + // - // Validate the constant and its value. + // Validate the constant and its value; for enums, find enumerator // - if(nt == Real && !validateConstant(name, constType, valueType, value, true)) + if(nt == Real && !validateConstant(name, constType, resolvedValueType, value, true)) { return 0; } - ConstPtr p = new Const(this, name, constType, metaData, valueType, value, literal); + ConstPtr p = new Const(this, name, constType, metaData, resolvedValueType, value, literal); _contents.push_back(p); return p; } @@ -1626,6 +1618,86 @@ Slice::Container::enums() const return result; } +EnumeratorList +Slice::Container::enumerators() const +{ + EnumeratorList result; + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + EnumeratorPtr q = EnumeratorPtr::dynamicCast(*p); + if(q) + { + result.push_back(q); + } + } + return result; +} + +// +// Find enumerators using the old unscoped enumerators lookup +// +EnumeratorList +Slice::Container::enumerators(const string& scoped) const +{ + EnumeratorList result; + string::size_type lastColon = scoped.rfind(':'); + + if(lastColon == string::npos) + { + // check all enclosing scopes + ContainerPtr container = const_cast<Container*>(this); + do + { + EnumList enums = container->enums(); + for(EnumList::iterator p = enums.begin(); p != enums.end(); ++p) + { + ContainedList cl = (*p)->lookupContained(scoped, false); + if(!cl.empty()) + { + result.push_back(EnumeratorPtr::dynamicCast(cl.front())); + } + } + + ContainedPtr contained = ContainedPtr::dynamicCast(container); + if(contained) + { + container = contained->container(); + } + else + { + container = 0; + } + } + while(result.empty() && container); + } + else + { + // Find the referenced scope + ContainerPtr container = const_cast<Container*>(this); + string scope = scoped.substr(0, scoped.rfind("::")); + ContainedList cl = container->lookupContained(scope, false); + if(!cl.empty()) + { + container = ContainerPtr::dynamicCast(cl.front()); + if(container) + { + EnumList enums = container->enums(); + string name = scoped.substr(lastColon + 1); + for(EnumList::iterator p = enums.begin(); p != enums.end(); ++p) + { + ContainedList cl = (*p)->lookupContained(name, false); + if(!cl.empty()) + { + result.push_back(EnumeratorPtr::dynamicCast(cl.front())); + } + } + } + } + } + + return result; +} + ConstList Slice::Container::consts() const { @@ -2627,7 +2699,7 @@ Slice::Container::checkGlobalMetaData(const StringList& m1, const StringList& m2 } bool -Slice::Container::validateConstant(const string& name, const TypePtr& type, const SyntaxTreeBasePtr& valueType, +Slice::Container::validateConstant(const string& name, const TypePtr& type, SyntaxTreeBasePtr& valueType, const string& value, bool isConstant) { // @@ -2856,20 +2928,57 @@ Slice::Container::validateConstant(const string& name, const TypePtr& type, cons } else { - EnumeratorPtr lte = EnumeratorPtr::dynamicCast(valueType); - - if(!lte) + if(valueType) { - string msg = "type of initializer is incompatible with the type of " + desc + " `" + name + "'"; - _unit->error(msg); - return false; + EnumeratorPtr lte = EnumeratorPtr::dynamicCast(valueType); + + if(!lte) + { + string msg = "type of initializer is incompatible with the type of " + desc + " `" + name + "'"; + _unit->error(msg); + return false; + } + EnumeratorList elist = e->enumerators(); + if(find(elist.begin(), elist.end(), lte) == elist.end()) + { + string msg = "enumerator `" + value + "' is not defined in enumeration `" + e->scoped() + "'"; + _unit->error(msg); + return false; + } } - EnumeratorList elist = e->getEnumerators(); - if(find(elist.begin(), elist.end(), lte) == elist.end()) + else { - string msg = "enumerator `" + value + "' is not defined in enumeration `" + e->scoped() + "'"; - _unit->error(msg); - return false; + // Check if value designates an enumerator of e + string newVal = value; + string::size_type lastColon = value.rfind(':'); + if(lastColon != string::npos && lastColon + 1 < value.length()) + { + newVal = value.substr(0, lastColon + 1) + e->name() + "::" + value.substr(lastColon + 1); + } + + ContainedList clist = e->lookupContained(newVal, false); + if(clist.empty()) + { + string msg = "`" + value + "' does not designate an enumerator of `" + e->scoped() + "'"; + _unit->error(msg); + return false; + } + EnumeratorPtr lte = EnumeratorPtr::dynamicCast(clist.front()); + if(lte) + { + valueType = lte; + if(lastColon != string::npos) + { + _unit->warning(Deprecated, string("referencing enumerator `") + lte->name() + + "' in its enumeration's enclosing scope is deprecated"); + } + } + else + { + string msg = "type of initializer is incompatible with the type of " + desc + " `" + name + "'"; + _unit->error(msg); + return false; + } } } } @@ -2877,7 +2986,7 @@ Slice::Container::validateConstant(const string& name, const TypePtr& type, cons return true; } -EnumeratorPtr +void Slice::Container::validateEnumerator(const string& name) { checkIdentifier(name); @@ -2885,32 +2994,19 @@ Slice::Container::validateEnumerator(const string& name) ContainedList matches = _unit->findContents(thisScope() + name); if(!matches.empty()) { - EnumeratorPtr p = EnumeratorPtr::dynamicCast(matches.front()); - if(p) - { - if(_unit->ignRedefs()) - { - p->updateIncludeLevel(); - return p; - } - } if(matches.front()->name() == name) { - string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name(); - msg += "' as enumerator"; - _unit->error(msg); + _unit->error(string("redefinition of enumerator `") + name + "'"); } else { string msg = "enumerator `" + name + "' differs only in capitalization from "; - msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'"; + msg += "`" + matches.front()->name() + "'"; _unit->error(msg); } } nameIsLegal(name, "enumerator"); // Don't return here -- we create the enumerator anyway. - - return 0; } // ---------------------------------------------------------------------- @@ -3486,7 +3582,7 @@ Slice::ClassDef::createDataMember(const string& name, const TypePtr& type, bool string dv = defaultValue; string dl = defaultLiteral; - if(dlt) + if(dlt || (EnumPtr::dynamicCast(type) && !dv.empty())) { // // Validate the default value. @@ -4009,7 +4105,7 @@ Slice::Exception::createDataMember(const string& name, const TypePtr& type, bool string dv = defaultValue; string dl = defaultLiteral; - if(dlt) + if(dlt || (EnumPtr::dynamicCast(type) && !dv.empty())) { // // Validate the default value. @@ -4331,7 +4427,7 @@ Slice::Struct::createDataMember(const string& name, const TypePtr& type, bool op string dv = defaultValue; string dl = defaultLiteral; - if(dlt) + if(dlt || (EnumPtr::dynamicCast(type) && !dv.empty())) { // // Validate the default value. @@ -4797,71 +4893,9 @@ Slice::Dictionary::Dictionary(const ContainerPtr& container, const string& name, void Slice::Enum::destroy() { - _enumerators.clear(); SyntaxTreeBase::destroy(); } -EnumeratorList -Slice::Enum::getEnumerators() -{ - return _enumerators; -} - -void -Slice::Enum::setEnumerators(const EnumeratorList& ens) -{ - _enumerators = ens; - int lastValue = -1; - set<int> values; - for(EnumeratorList::iterator p = _enumerators.begin(); p != _enumerators.end(); ++p) - { - (*p)->_type = this; - - if((*p)->_explicitValue) - { - _explicitValue = true; - - if((*p)->_value < 0) - { - string msg = "value for enumerator `" + (*p)->name() + "' is out of range"; - _unit->error(msg); - } - } - else - { - if(lastValue == Int32Max) - { - string msg = "value for enumerator `" + (*p)->name() + "' is out of range"; - _unit->error(msg); - } - - // - // If the enumerator was not assigned an explicit value, we automatically assign - // it one more than the previous enumerator. - // - (*p)->_value = lastValue + 1; - } - - if(values.count((*p)->_value) != 0) - { - string msg = "enumerator `" + (*p)->name() + "' has a duplicate value"; - _unit->error(msg); - } - values.insert((*p)->_value); - - lastValue = (*p)->_value; - - if(lastValue > _maxValue) - { - _maxValue = lastValue; - } - if(lastValue < _minValue) - { - _minValue = lastValue; - } - } -} - bool Slice::Enum::explicitValue() const { @@ -4930,15 +4964,77 @@ Slice::Enum::recDependencies(set<ConstructedPtr>&) Slice::Enum::Enum(const ContainerPtr& container, const string& name, bool local) : SyntaxTreeBase(container->unit()), + Container(container->unit()), Type(container->unit()), Contained(container, name), Constructed(container, name, local), _explicitValue(false), _minValue(Int32Max), - _maxValue(0) + _maxValue(0), + _lastValue(-1) { } +int +Slice::Enum::newEnumerator(const EnumeratorPtr& p) +{ + if(p->explicitValue()) + { + _explicitValue = true; + _lastValue = p->value(); + + if(_lastValue < 0) + { + string msg = "value for enumerator `" + p->name() + "' is out of range"; + _unit->error(msg); + } + } + else + { + if(_lastValue == Int32Max) + { + string msg = "value for enumerator `" + p->name() + "' is out of range"; + _unit->error(msg); + } + else + { + // + // If the enumerator was not assigned an explicit value, we automatically assign + // it one more than the previous enumerator. + // + ++_lastValue; + } + } + + bool checkForDuplicates = true; + if(_lastValue > _maxValue) + { + _maxValue = _lastValue; + checkForDuplicates = false; + } + if(_lastValue < _minValue) + { + _minValue = _lastValue; + checkForDuplicates = false; + } + + if(checkForDuplicates) + { + EnumeratorList enl = enumerators(); + for(EnumeratorList::iterator q = enl.begin(); q != enl.end(); ++q) + { + EnumeratorPtr& r = *q; + if(r != p && r->value() == _lastValue) + { + _unit->error(string("enumerator `") + p->name() + "' has the same value as enumerator `" + + r->name() + "'"); + } + } + } + + return _lastValue; +} + // ---------------------------------------------------------------------- // Enumerator // ---------------------------------------------------------------------- @@ -4946,7 +5042,7 @@ Slice::Enum::Enum(const ContainerPtr& container, const string& name, bool local) EnumPtr Slice::Enumerator::type() const { - return _type; + return EnumPtr::dynamicCast(container()); } Contained::ContainedType @@ -4985,6 +5081,7 @@ Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name) _explicitValue(false), _value(-1) { + _value = EnumPtr::dynamicCast(container)->newEnumerator(this); } Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name, int value) : @@ -4993,6 +5090,7 @@ Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name, _explicitValue(true), _value(value) { + EnumPtr::dynamicCast(container)->newEnumerator(this); } // ---------------------------------------------------------------------- @@ -5065,6 +5163,11 @@ Slice::Const::Const(const ContainerPtr& container, const string& name, const Typ _value(value), _literal(literal) { + if(valueType == 0) + { + cerr << "const " << name << " created with null valueType" << endl; + } + } // ---------------------------------------------------------------------- |