summaryrefslogtreecommitdiff
path: root/cpp/src/Slice/Parser.cpp
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2017-02-08 09:41:55 -0500
committerBernard Normier <bernard@zeroc.com>2017-02-08 09:41:55 -0500
commitaf38cbf2ebf9c009fcea81cc316be64176da620e (patch)
tree28d6975bf5f1c4b7b89a5c24d2e1d9f1a2ba633c /cpp/src/Slice/Parser.cpp
parentAdded wide char overloads of Ice::createProperties & Ice::initialize (diff)
downloadice-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.cpp327
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;
+ }
+
}
// ----------------------------------------------------------------------