summaryrefslogtreecommitdiff
path: root/cpp/src/Slice/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Slice/Parser.cpp')
-rw-r--r--cpp/src/Slice/Parser.cpp1086
1 files changed, 766 insertions, 320 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index af0b0f2bb73..00fb1d42047 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
@@ -79,6 +129,7 @@ Unit* unit;
Slice::DefinitionContext::DefinitionContext(int includeLevel, const StringList& metaData) :
_includeLevel(includeLevel), _metaData(metaData), _seenDefinition(false)
{
+ initSuppressedWarnings();
}
string
@@ -121,6 +172,7 @@ void
Slice::DefinitionContext::setMetaData(const StringList& metaData)
{
_metaData = metaData;
+ initSuppressedWarnings();
}
string
@@ -143,6 +195,74 @@ Slice::DefinitionContext::getMetaData() const
return _metaData;
}
+void
+Slice::DefinitionContext::warning(WarningCategory category, const string& file, int line, const string& msg) const
+{
+ if(!suppressWarning(category))
+ {
+ emitWarning(file, line, msg);
+ }
+}
+
+void
+Slice::DefinitionContext::warning(WarningCategory category, const string& file, const string& line, const string& msg) const
+{
+ if(!suppressWarning(category))
+ {
+ emitWarning(file, line, msg);
+ }
+}
+
+bool
+Slice::DefinitionContext::suppressWarning(WarningCategory category) const
+{
+ return _suppressedWarnings.find(category) != _suppressedWarnings.end() ||
+ _suppressedWarnings.find(All) != _suppressedWarnings.end();
+}
+
+void
+Slice::DefinitionContext::initSuppressedWarnings()
+{
+ _suppressedWarnings.clear();
+ const string prefix = "suppress-warning";
+ string value = findMetaData(prefix);
+ if(value == prefix)
+ {
+ _suppressedWarnings.insert(All);
+ }
+ else if(!value.empty())
+ {
+ assert(value.length() > prefix.length());
+ if(value[prefix.length()] == ':')
+ {
+ value = value.substr(prefix.length() + 1);
+ vector<string> result;
+ IceUtilInternal::splitString(value, ",", result);
+ for(vector<string>::iterator p = result.begin(); p != result.end(); ++p)
+ {
+ string s = IceUtilInternal::trim(*p);
+ if(s == "all")
+ {
+ _suppressedWarnings.insert(All);
+ }
+ else if(s == "deprecated")
+ {
+ _suppressedWarnings.insert(Deprecated);
+ }
+ else if(s == "invalid-metadata")
+ {
+ _suppressedWarnings.insert(InvalidMetaData);
+ }
+ else
+ {
+ warning(InvalidMetaData, "", "", string("invalid category `") + s +
+ "' in global metadata suppress-warning");
+ }
+ }
+ }
+ }
+}
+
// ----------------------------------------------------------------------
// SyntaxTreeBase
// ----------------------------------------------------------------------
@@ -258,6 +378,11 @@ Slice::Builtin::typeId() const
return "::Ice::LocalObject";
break;
}
+ case KindValue:
+ {
+ return "::Ice::Value";
+ break;
+ }
}
assert(false);
return ""; // Keep the compiler happy.
@@ -266,7 +391,7 @@ Slice::Builtin::typeId() const
bool
Slice::Builtin::usesClasses() const
{
- return _kind == KindObject;
+ return _kind == KindObject || _kind == KindValue;
}
size_t
@@ -283,7 +408,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 +419,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 +446,8 @@ const char* Slice::Builtin::builtinTable[] =
"string",
"Object",
"Object*",
- "LocalObject"
+ "LocalObject",
+ "Value"
};
Slice::Builtin::Builtin(const UnitPtr& unit, Kind kind) :
@@ -368,12 +495,13 @@ string
Slice::Contained::flattenedScope() const
{
string s = scope();
- string flattenedScope;
- for(string::const_iterator r = s.begin(); r != s.end(); ++r)
+ string::size_type pos = 0;
+ while((pos = s.find("::", pos)) != string::npos)
{
- flattenedScope += ((*r) == ':') ? '_' : *r;
+ s.replace(pos, 2, "_");
+
}
- return flattenedScope;
+ return s;
}
string
@@ -496,12 +624,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 +998,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 +1053,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())
{
@@ -997,7 +1097,7 @@ Slice::Container::createDictionary(const string& name, const TypePtr& keyType, c
}
if(containsSequence)
{
- _unit->warning("use of sequences in dictionary keys has been deprecated");
+ _unit->warning(Deprecated, "use of sequences in dictionary keys has been deprecated");
}
}
@@ -1067,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;
}
@@ -1081,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;
}
@@ -1133,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;
}
@@ -1178,16 +1270,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 +1388,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)
{
@@ -1539,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
{
@@ -1610,7 +1769,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 +1777,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 +1836,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 +1974,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)
@@ -2001,7 +2260,7 @@ Slice::Container::mergeModules()
metaData2.unique();
if(!checkGlobalMetaData(metaData1, metaData2))
{
- unit()->warning("global metadata mismatch for module `" + mod1->name() + "' in files " +
+ unit()->warning(All, "global metadata mismatch for module `" + mod1->name() + "' in files " +
dc1->filename() + " and " + dc2->filename());
}
@@ -2310,23 +2569,34 @@ Slice::Container::checkIdentifier(const string& name) const
//
// For rules controlled by a translator option, we don't complain about included files.
//
- _unit->error("illegal underscore in identifier `" + name + "'");
+
+ DefinitionContextPtr dc = _unit->currentDefinitionContext();
+ assert(dc);
+ if(dc->findMetaData("underscore") != "underscore") // no "underscore" global metadata
+ {
+ _unit->error("illegal underscore in identifier `" + name + "'");
+ }
}
+ //
+ // For rules controlled by a translator option, we don't complain about included files.
+ //
if(_unit->currentIncludeLevel() == 0 && !_unit->allowIcePrefix())
{
- //
- // For rules controlled by a translator option, we don't complain about included files.
- //
- if(name.size() >= 3)
+ DefinitionContextPtr dc = _unit->currentDefinitionContext();
+ assert(dc);
+ if(dc->findMetaData("ice-prefix") != "ice-prefix") // no "ice-prefix" global metadata
{
- string prefix3;
- prefix3 += ::tolower(static_cast<unsigned char>(name[0]));
- prefix3 += ::tolower(static_cast<unsigned char>(name[1]));
- prefix3 += ::tolower(static_cast<unsigned char>(name[2]));
- if(prefix3 == "ice")
+ if(name.size() >= 3)
{
- _unit->error("illegal identifier `" + name + "': `" + name.substr(0, 3) + "' prefix is reserved");
+ string prefix3;
+ prefix3 += ::tolower(static_cast<unsigned char>(name[0]));
+ prefix3 += ::tolower(static_cast<unsigned char>(name[1]));
+ prefix3 += ::tolower(static_cast<unsigned char>(name[2]));
+ if(prefix3 == "ice")
+ {
+ _unit->error("illegal identifier `" + name + "': `" + name.substr(0, 3) + "' prefix is reserved");
+ }
}
}
}
@@ -2429,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)
{
//
@@ -2575,6 +2845,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;
@@ -2657,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;
+ }
}
}
}
@@ -2678,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);
@@ -2686,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;
}
// ----------------------------------------------------------------------
@@ -3186,6 +3481,12 @@ Slice::ClassDef::createOperation(const string& name,
_unit->error(msg);
}
+ if(!isInterface() && !isLocal() && !_hasOperations)
+ {
+ // Only warn for the first operation
+ _unit->warning(Deprecated, "classes with operations are deprecated");
+ }
+
_hasOperations = true;
OperationPtr op = new Operation(this, name, returnType, optional, tag, mode);
_contents.push_back(op);
@@ -3199,28 +3500,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())
@@ -3303,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.
@@ -3456,7 +3735,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 +3884,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 +3937,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()),
@@ -3657,6 +3954,17 @@ Slice::ClassDef::ClassDef(const ContainerPtr& container, const string& name, int
_local(local),
_compactId(id)
{
+ if(!local && !intf)
+ {
+ for(ClassList::const_iterator p = _bases.begin(); p != _bases.end(); ++p)
+ {
+ if((*p)->isInterface())
+ {
+ _unit->warning(Deprecated, "classes implementing interfaces are deprecated");
+ break;
+ }
+ }
+ }
//
// First element of bases may be a class, all others must be
// interfaces.
@@ -3681,13 +3989,13 @@ Slice::ClassDef::ClassDef(const ContainerPtr& container, const string& name, int
bool
Slice::Proxy::isLocal() const
{
- return __class->isLocal();
+ return _classDecl->isLocal();
}
string
Slice::Proxy::typeId() const
{
- return __class->scoped();
+ return _classDecl->scoped();
}
bool
@@ -3711,13 +4019,13 @@ Slice::Proxy::isVariableLength() const
ClassDeclPtr
Slice::Proxy::_class() const
{
- return __class;
+ return _classDecl;
}
Slice::Proxy::Proxy(const ClassDeclPtr& cl) :
SyntaxTreeBase(cl->unit()),
Type(cl->unit()),
- __class(cl)
+ _classDecl(cl)
{
}
@@ -3739,28 +4047,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())
{
@@ -3830,7 +4116,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.
@@ -3925,7 +4211,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 +4347,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 +4387,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())
{
@@ -4167,7 +4438,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.
@@ -4230,7 +4501,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 +4842,7 @@ Slice::Dictionary::legalKeyType(const TypePtr& type, bool& containsSequence)
case Builtin::KindObject:
case Builtin::KindObjectProxy:
case Builtin::KindLocalObject:
+ case Builtin::KindValue:
{
return false;
break;
@@ -4630,71 +4904,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
{
@@ -4763,15 +4975,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
// ----------------------------------------------------------------------
@@ -4779,7 +5053,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
@@ -4818,6 +5092,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) :
@@ -4826,6 +5101,7 @@ Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name,
_explicitValue(true),
_value(value)
{
+ EnumPtr::dynamicCast(container)->newEnumerator(this);
}
// ----------------------------------------------------------------------
@@ -4898,6 +5174,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;
+ }
+
}
// ----------------------------------------------------------------------
@@ -4941,33 +5222,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 +5348,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 +5568,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;
}
@@ -5263,7 +5625,7 @@ Slice::Operation::attributes() const
}
if(i == 2)
{
- emitWarning(definitionContext()->filename(), line(), "invalid freeze metadata for operation");
+ _unit->warning(InvalidMetaData, "invalid freeze metadata for operation");
}
else
{
@@ -5284,7 +5646,7 @@ Slice::Operation::attributes() const
{
if(result != 0 && (i == int(Supports) || i == int(Never)))
{
- emitWarning(definitionContext()->filename(), line(), "invalid freeze metadata for operation");
+ _unit->warning(InvalidMetaData, "invalid freeze metadata for operation");
}
else
{
@@ -5298,7 +5660,7 @@ Slice::Operation::attributes() const
if(i == 4)
{
- emitWarning(definitionContext()->filename(), line(), "invalid freeze metadata for operation");
+ _unit->warning(InvalidMetaData, "invalid freeze metadata for operation");
//
// Set default
@@ -5356,26 +5718,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);
- }
- }
- }
}
// ----------------------------------------------------------------------
@@ -5801,13 +6143,6 @@ Slice::Unit::setSeenDefinition()
}
void
-Slice::Unit::error(const char* s)
-{
- emitError(currentFile(), _currentLine, s);
- _errors++;
-}
-
-void
Slice::Unit::error(const string& s)
{
emitError(currentFile(), _currentLine, s);
@@ -5815,15 +6150,16 @@ Slice::Unit::error(const string& s)
}
void
-Slice::Unit::warning(const char* s) const
-{
- emitWarning(currentFile(), _currentLine, s);
-}
-
-void
-Slice::Unit::warning(const string& s) const
+Slice::Unit::warning(WarningCategory category, const string& msg) const
{
- emitWarning(currentFile(), _currentLine, s);
+ if(_definitionContextStack.empty())
+ {
+ emitWarning(currentFile(), _currentLine, msg);
+ }
+ else
+ {
+ _definitionContextStack.top()->warning(category, currentFile(), _currentLine, msg);
+ }
}
ContainerPtr
@@ -6038,6 +6374,11 @@ Slice::Unit::usesNonLocals() const
return true;
}
+ if(_builtins.find(Builtin::KindValue) != _builtins.end())
+ {
+ return true;
+ }
+
return false;
}
@@ -6059,12 +6400,6 @@ Slice::Unit::usesConsts() const
return false;
}
-FeatureProfile
-Slice::Unit::profile() const
-{
- return _featureProfile;
-}
-
StringList
Slice::Unit::includeFiles() const
{
@@ -6084,7 +6419,7 @@ Slice::Unit::allFiles() const
}
int
-Slice::Unit::parse(const string& filename, FILE* file, bool debug, Slice::FeatureProfile profile)
+Slice::Unit::parse(const string& filename, FILE* file, bool debug)
{
slice_debug = debug ? 1 : 0;
@@ -6094,7 +6429,6 @@ Slice::Unit::parse(const string& filename, FILE* file, bool debug, Slice::Featur
_currentComment = "";
_currentLine = 1;
_currentIncludeLevel = 0;
- _featureProfile = profile;
_topLevelFile = fullPath(filename);
pushContainer(this);
pushDefinitionContext();
@@ -6130,6 +6464,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 +6567,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
// ----------------------------------------------------------------------