summaryrefslogtreecommitdiff
path: root/cpp/src/slice2cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2009-03-24 11:45:18 +0100
committerBenoit Foucher <benoit@zeroc.com>2009-03-24 11:45:18 +0100
commit06a08ecf28e205277336a97a6173db7ccbed1adc (patch)
treea369a5044a63f8cdba9e7c0a461e24ae344486b4 /cpp/src/slice2cpp
parentMerge branch 'R3_3_branch' (diff)
parentBug 3924: slice2py missing from VC60 installer (diff)
downloadice-06a08ecf28e205277336a97a6173db7ccbed1adc.tar.bz2
ice-06a08ecf28e205277336a97a6173db7ccbed1adc.tar.xz
ice-06a08ecf28e205277336a97a6173db7ccbed1adc.zip
Merge commit 'origin/R3_3_branch'
Conflicts: CHANGES cpp/demo/Freeze/backup/.depend cpp/demo/Freeze/bench/.depend cpp/demo/Freeze/casino/.depend cpp/demo/Freeze/customEvictor/.depend cpp/demo/Freeze/library/.depend cpp/demo/Freeze/phonebook/.depend cpp/demo/Freeze/transform/.depend cpp/demo/Glacier2/callback/.depend cpp/demo/Glacier2/chat/.depend cpp/demo/Ice/async/.depend cpp/demo/Ice/bidir/.depend cpp/demo/Ice/callback/.depend cpp/demo/Ice/converter/.depend cpp/demo/Ice/hello/.depend cpp/demo/Ice/invoke/.depend cpp/demo/Ice/latency/.depend cpp/demo/Ice/minimal/.depend cpp/demo/Ice/multicast/.depend cpp/demo/Ice/nested/.depend cpp/demo/Ice/nrvo/.depend cpp/demo/Ice/session/.depend cpp/demo/Ice/throughput/.depend cpp/demo/Ice/value/.depend cpp/demo/IceBox/hello/.depend cpp/demo/IceGrid/allocate/.depend cpp/demo/IceGrid/icebox/.depend cpp/demo/IceGrid/replication/.depend cpp/demo/IceGrid/sessionActivation/.depend cpp/demo/IceGrid/simple/.depend cpp/demo/IceStorm/clock/.depend cpp/demo/IceStorm/counter/.depend cpp/demo/IceStorm/replicated/.depend cpp/demo/IceStorm/replicated2/.depend cpp/demo/book/freeze_filesystem/.depend cpp/demo/book/lifecycle/.depend cpp/demo/book/printer/.depend cpp/demo/book/simple_filesystem/.depend cpp/src/Freeze/.depend cpp/src/FreezeScript/.depend cpp/src/Ice/.depend cpp/src/Ice/UdpTransceiver.cpp cpp/src/Ice/UdpTransceiver.h cpp/src/IceBox/.depend cpp/src/IceGrid/.depend cpp/src/IceGridLib/.depend cpp/src/IcePatch2/.depend cpp/src/IceStorm/.depend cpp/src/slice2freeze/.depend cpp/test/Freeze/complex/.depend cpp/test/Freeze/dbmap/.depend cpp/test/Freeze/evictor/.depend cpp/test/Freeze/oldevictor/.depend cpp/test/FreezeScript/dbmap/.depend cpp/test/FreezeScript/evictor/.depend cpp/test/Glacier2/attack/.depend cpp/test/Glacier2/dynamicFiltering/.depend cpp/test/Glacier2/router/.depend cpp/test/Glacier2/sessionControl/.depend cpp/test/Glacier2/ssl/.depend cpp/test/Glacier2/staticFiltering/.depend cpp/test/Ice/adapterDeactivation/.depend cpp/test/Ice/background/.depend cpp/test/Ice/binding/.depend cpp/test/Ice/checksum/.depend cpp/test/Ice/checksum/server/.depend cpp/test/Ice/custom/.depend cpp/test/Ice/exceptions/.depend cpp/test/Ice/facets/.depend cpp/test/Ice/faultTolerance/.depend cpp/test/Ice/gc/.depend cpp/test/Ice/hold/.depend cpp/test/Ice/inheritance/.depend cpp/test/Ice/interceptor/.depend cpp/test/Ice/location/.depend cpp/test/Ice/objects/.depend cpp/test/Ice/operations/.depend cpp/test/Ice/proxy/.depend cpp/test/Ice/retry/.depend cpp/test/Ice/servantLocator/.depend cpp/test/Ice/slicing/exceptions/.depend cpp/test/Ice/slicing/objects/.depend cpp/test/Ice/stream/.depend cpp/test/Ice/stringConverter/.depend cpp/test/Ice/timeout/.depend cpp/test/Ice/udp/.depend cpp/test/IceBox/configuration/.depend cpp/test/IceGrid/activation/.depend cpp/test/IceGrid/allocation/.depend cpp/test/IceGrid/deployer/.depend cpp/test/IceGrid/distribution/.depend cpp/test/IceGrid/replicaGroup/.depend cpp/test/IceGrid/replication/.depend cpp/test/IceGrid/session/.depend cpp/test/IceGrid/simple/.depend cpp/test/IceGrid/update/.depend cpp/test/IceSSL/configuration/.depend cpp/test/IceStorm/federation/.depend cpp/test/IceStorm/federation2/.depend cpp/test/IceStorm/rep1/.depend cpp/test/IceStorm/repgrid/.depend cpp/test/IceStorm/repstress/.depend cpp/test/IceStorm/single/.depend cpp/test/IceStorm/stress/.depend cpp/test/Slice/keyword/.depend cs/src/Ice/Instance.cs cs/src/IceSSL/ConnectorI.cs java/demo/book/simple_filesystem/Filesystem/DirectoryI.java java/demo/book/simple_filesystem/Filesystem/FileI.java java/src/IceInternal/TcpConnector.java java/src/IceSSL/ConnectorI.java py/modules/IcePy/.depend rb/src/IceRuby/.depend
Diffstat (limited to 'cpp/src/slice2cpp')
-rw-r--r--cpp/src/slice2cpp/.depend4
-rw-r--r--cpp/src/slice2cpp/Gen.cpp513
-rw-r--r--cpp/src/slice2cpp/Gen.h29
-rw-r--r--cpp/src/slice2cpp/Main.cpp14
-rw-r--r--cpp/src/slice2cpp/Makefile.mak4
5 files changed, 343 insertions, 221 deletions
diff --git a/cpp/src/slice2cpp/.depend b/cpp/src/slice2cpp/.depend
index 3e72263da59..a9700e4a72c 100644
--- a/cpp/src/slice2cpp/.depend
+++ b/cpp/src/slice2cpp/.depend
@@ -1,2 +1,2 @@
-Gen$(OBJEXT): Gen.cpp ./Gen.h $(includedir)/Slice/Parser.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/OutputUtil.h $(includedir)/Slice/Util.h $(includedir)/Slice/CPlusPlusUtil.h $(includedir)/IceUtil/Functional.h $(includedir)/IceUtil/Iterator.h $(includedir)/Slice/Checksum.h
-Main$(OBJEXT): Main.cpp $(includedir)/IceUtil/Options.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/RecMutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/CtrlCHandler.h $(includedir)/IceUtil/StaticMutex.h $(includedir)/Slice/Preprocessor.h ./Gen.h $(includedir)/Slice/Parser.h $(includedir)/IceUtil/OutputUtil.h
+Gen$(OBJEXT): Gen.cpp $(includedir)/IceUtil/DisableWarnings.h ./Gen.h $(includedir)/Slice/Parser.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/OutputUtil.h $(includedir)/Slice/Util.h $(includedir)/Slice/CPlusPlusUtil.h $(includedir)/IceUtil/Functional.h $(includedir)/IceUtil/Iterator.h $(includedir)/Slice/Checksum.h $(includedir)/Slice/FileTracker.h $(includedir)/Slice/Preprocessor.h
+Main$(OBJEXT): Main.cpp $(includedir)/IceUtil/Options.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/RecMutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/CtrlCHandler.h $(includedir)/IceUtil/StaticMutex.h $(includedir)/Slice/Preprocessor.h $(includedir)/Slice/FileTracker.h $(includedir)/Slice/Parser.h $(includedir)/Slice/Util.h ./Gen.h $(includedir)/IceUtil/OutputUtil.h
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 21345c09093..6bd7fe0bd50 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -22,8 +22,6 @@
#include <sys/stat.h>
#include <string.h>
-#include <iostream> //TODO
-
using namespace std;
using namespace Slice;
using namespace IceUtil;
@@ -86,11 +84,12 @@ Slice::Gen::~Gen()
void
Slice::Gen::generate(const UnitPtr& p)
{
+ string file = p->topLevelFile();
//
- // Check the header-ext global meta data if is not empty we override _headerExtension
+ // Give precedence to header-ext global metadata.
//
- string headerExtension = getHeaderExt(p->modules());
+ string headerExtension = getHeaderExt(file, p);
if(!headerExtension.empty())
{
_headerExtension = headerExtension;
@@ -291,7 +290,7 @@ Slice::Gen::generate(const UnitPtr& p)
for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q)
{
- string extension = getHeaderExt((*q), p->modules());
+ string extension = getHeaderExt((*q), p);
if(extension.empty())
{
extension = _headerExtension;
@@ -306,8 +305,24 @@ Slice::Gen::generate(const UnitPtr& p)
C << "\n#include <IceUtil/DisableWarnings.h>";
}
- GlobalIncludeVisitor globalIncludeVisitor(H);
- p->visit(&globalIncludeVisitor, false);
+ //
+ // Emit #include statements for any cpp:include metadata directives
+ // in the top-level Slice file.
+ //
+ {
+ DefinitionContextPtr dc = p->findDefinitionContext(file);
+ assert(dc);
+ StringList globalMetaData = dc->getMetaData();
+ for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q)
+ {
+ string s = *q;
+ static const string includePrefix = "cpp:include:";
+ if(s.find(includePrefix) == 0 && s.size() > includePrefix.size())
+ {
+ H << nl << "#include <" << s.substr(includePrefix.size()) << ">";
+ }
+ }
+ }
printVersionCheck(H);
printVersionCheck(C);
@@ -442,36 +457,6 @@ Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out)
}
}
-Slice::Gen::GlobalIncludeVisitor::GlobalIncludeVisitor(Output& h) :
- H(h), _finished(false)
-{
-}
-
-bool
-Slice::Gen::GlobalIncludeVisitor::visitModuleStart(const ModulePtr& p)
-{
- if(!_finished)
- {
- DefinitionContextPtr dc = p->definitionContext();
- assert(dc);
- StringList globalMetaData = dc->getMetaData();
-
- static const string includePrefix = "cpp:include:";
-
- for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q)
- {
- string s = *q;
- if(s.find(includePrefix) == 0)
- {
- H << nl << "#include <" << s.substr(includePrefix.size()) << ">";
- }
- }
- _finished = true;
- }
-
- return false;
-}
-
Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport, bool stream) :
H(h), C(c), _dllExport(dllExport), _stream(stream), _doneStaticSymbol(false), _useWstring(false)
{
@@ -1140,6 +1125,26 @@ void
Slice::Gen::TypesVisitor::visitDataMember(const DataMemberPtr& p)
{
string name = fixKwd(p->name());
+ TypePtr type = p->type();
+ if(p->container() != 0 && (StructPtr::dynamicCast(p->container()) || ExceptionPtr::dynamicCast(p->container())) &&
+ SequencePtr::dynamicCast(type))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(type);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, false, protobuf);
+ if(protobuf)
+ {
+ emitWarning(p->file(), p->line(), string("protobuf cannot be used as a ") +
+ (StructPtr::dynamicCast(p->container()) ? "struct" : "exception") +
+ " member in C++");
+ }
+ }
+ }
+
string s = typeToString(p->type(), _useWstring, p->getMetaData());
H << nl << s << ' ' << name << ';';
}
@@ -1151,14 +1156,20 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
TypePtr type = p->type();
string s = typeToString(type, _useWstring, p->typeMetaData());
StringList metaData = p->getMetaData();
- string seqType = findMetaData(metaData, false);
- if(!seqType.empty())
- {
- H << sp << nl << "typedef " << seqType << ' ' << name << ';';
- }
- else
+
+ bool protobuf;
+ string seqType = findMetaData(p, metaData, false, protobuf);
+ H << sp;
+ if(!protobuf)
{
- H << sp << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';';
+ if(!seqType.empty())
+ {
+ H << nl << "typedef " << seqType << ' ' << name << ';';
+ }
+ else
+ {
+ H << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';';
+ }
}
BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
@@ -1167,100 +1178,163 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
string scoped = fixKwd(p->scoped());
string scope = fixKwd(p->scope());
- if(!seqType.empty())
+ if(protobuf || !seqType.empty())
{
- H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << name << "&);";
- H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);";
+ string typeName = name;
+ string scopedName = scoped;
+ if(protobuf && !seqType.empty())
+ {
+ typeName = seqType;
+ scopedName = seqType;
+ }
+ H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const "
+ << typeName << "&);";
+ H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, "
+ << typeName << "&);";
if(_stream)
{
H << nl << _dllExport << "void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const "
- << name << "&);";
- H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name
+ << typeName << "&);";
+ H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << typeName
<< "&);";
}
C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name <<
- "(::IceInternal::BasicStream* __os, const " << scoped << "& v)";
- C << sb;
- C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());";
- C << nl << "__os->writeSize(size);";
- C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)";
+ "(::IceInternal::BasicStream* __os, const " << scopedName << "& v)";
C << sb;
- writeMarshalUnmarshalCode(C, type, "(*p)", true);
- C << eb;
+ if(protobuf)
+ {
+ C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());";
+ C << nl << "if(!v.IsInitialized())";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());";
+ C << eb;
+ C << nl << "if(!v.SerializeToArray(&data[0], data.size()))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"SerializeToArray failed\");";
+ C << eb;
+ C << nl << "__os->write(&data[0], &data[0] + data.size());";
+ }
+ else
+ {
+ C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());";
+ C << nl << "__os->writeSize(size);";
+ C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", true);
+ C << eb;
+ }
C << eb;
C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name
- << "(::IceInternal::BasicStream* __is, " << scoped << "& v)";
+ << "(::IceInternal::BasicStream* __is, " << scopedName << "& v)";
C << sb;
- C << nl << "::Ice::Int sz;";
- C << nl << "__is->readSize(sz);";
- C << nl << name << "(sz).swap(v);";
- if(type->isVariableLength())
+ if(protobuf)
{
- // Protect against bogus sequence sizes.
- C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");";
+ C << nl << "::std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;";
+ C << nl << "__is->read(data);";
+ C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");";
+ C << eb;
}
else
{
- C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");";
- }
- C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)";
- C << sb;
- writeMarshalUnmarshalCode(C, type, "(*p)", false);
+ C << nl << "::Ice::Int sz;";
+ C << nl << "__is->readSize(sz);";
+ C << nl << name << "(sz).swap(v);";
+ if(type->isVariableLength())
+ {
+ // Protect against bogus sequence sizes.
+ C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");";
+ }
+ else
+ {
+ C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");";
+ }
+ C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", false);
- //
- // After unmarshaling each element, check that there are still enough bytes left in the stream
- // to unmarshal the remainder of the sequence, and decrement the count of elements
- // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences
- // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to
- // abort unmarshaling for bogus sequence sizes at the earliest possible moment.
- // (For fixed-length sequences, we don't need to do this because the prediction of how many
- // bytes will be taken up by the sequence is accurate.)
- //
- if(type->isVariableLength())
- {
- if(!SequencePtr::dynamicCast(type))
+ //
+ // After unmarshaling each element, check that there are still enough bytes left in the stream
+ // to unmarshal the remainder of the sequence, and decrement the count of elements
+ // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences
+ // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to
+ // abort unmarshaling for bogus sequence sizes at the earliest possible moment.
+ // (For fixed-length sequences, we don't need to do this because the prediction of how many
+ // bytes will be taken up by the sequence is accurate.)
+ //
+ if(type->isVariableLength())
{
- //
- // No need to check for directly nested sequences because, at the start of each
- // sequence, we check anyway.
- //
- C << nl << "__is->checkSeq();";
+ if(!SequencePtr::dynamicCast(type))
+ {
+ //
+ // No need to check for directly nested sequences because, at the start of each
+ // sequence, we check anyway.
+ //
+ C << nl << "__is->checkSeq();";
+ }
+ C << nl << "__is->endElement();";
+ }
+ C << eb;
+ if(type->isVariableLength())
+ {
+ C << nl << "__is->endSeq(sz);";
}
- C << nl << "__is->endElement();";
- }
- C << eb;
- if(type->isVariableLength())
- {
- C << nl << "__is->endSeq(sz);";
}
C << eb;
if(_stream)
{
C << sp << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name()
- << "(const ::Ice::OutputStreamPtr& __outS, const " << scoped << "& v)";
- C << sb;
- C << nl << "__outS->writeSize(::Ice::Int(v.size()));";
- C << nl << scoped << "::const_iterator p;";
- C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ << "(const ::Ice::OutputStreamPtr& __outS, const " << scopedName << "& v)";
C << sb;
- writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", _useWstring);
- C << eb;
+ if(protobuf)
+ {
+ C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());";
+ C << nl << "if(!v.IsInitialized())";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());";
+ C << eb;
+ C << nl << "v.SerializeToArray(&data[0], data.size());";
+
+ C << nl << "__outS->writeByteSeq(data);";
+ }
+ else
+ {
+ C << nl << "__outS->writeSize(::Ice::Int(v.size()));";
+ C << nl << scopedName << "::const_iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", _useWstring);
+ C << eb;
+ }
C << eb;
C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name()
- << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& v)";
- C << sb;
- C << nl << "::Ice::Int sz = __inS->readSize();";
- C << nl << scoped << "(sz).swap(v);";
- C << nl << scoped << "::iterator p;";
- C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ << "(const ::Ice::InputStreamPtr& __inS, " << scopedName << "& v)";
C << sb;
- writeStreamMarshalUnmarshalCode(C, type, "(*p)", false, "", _useWstring);
- C << eb;
+ if(protobuf)
+ {
+ C << nl << "std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;";
+ C << nl << "__inS->readByteSeq(data);";
+ C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))";
+ C << sb;
+ C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");";
+ C << eb;
+ }
+ else
+ {
+ C << nl << "::Ice::Int sz = __inS->readSize();";
+ C << nl << scopedName << "(sz).swap(v);";
+ C << nl << scopedName << "::iterator p;";
+ C << nl << "for(p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeStreamMarshalUnmarshalCode(C, type, "(*p)", false, "", _useWstring);
+ C << eb;
+ }
C << eb;
}
}
@@ -1369,6 +1443,22 @@ Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
{
string name = fixKwd(p->name());
TypePtr keyType = p->keyType();
+ if(SequencePtr::dynamicCast(keyType))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(keyType);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, false, protobuf);
+ if(protobuf)
+ {
+ emitWarning(p->file(), p->line(), "protobuf cannot be used as a dictionary key in C++");
+ }
+ }
+ }
+
TypePtr valueType = p->valueType();
string ks = typeToString(keyType, _useWstring, p->keyMetaData());
if(ks[0] == ':')
@@ -2277,6 +2367,15 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p)
C << nl << "::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase;";
C << nl << "try";
C << sb;
+
+ C.zeroIndent();
+ C << nl << "#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600) // C++Builder 2009 compiler bug";
+ C.restoreIndent();
+ C << nl << "IceUtil::DummyBCC dummy;";
+ C.zeroIndent();
+ C << nl << "#endif";
+ C.restoreIndent();
+
if(p->returnsData())
{
C << nl << "__checkTwowayOnly(" << p->flattenedScope() + p->name() + "_name);";
@@ -2646,6 +2745,11 @@ Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p)
}
C << nl << "bool __ok = __og.invoke();";
+
+ //
+ // Declare the return __ret variable at the top-level scope to
+ // enable NRVO with GCC (see also bug #3619).
+ //
writeAllocateCode(C, ParamDeclList(), ret, p->getMetaData(), _useWstring);
if(!p->returnsData())
{
@@ -3811,6 +3915,23 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p)
bool prot = p->hasMetaData("protected");
for(q = dataMembers.begin(); q != dataMembers.end(); ++q)
{
+ TypePtr type = (*q)->type();
+ if(SequencePtr::dynamicCast(type))
+ {
+ SequencePtr s = SequencePtr::dynamicCast(type);
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(s->type());
+ if(builtin && builtin->kind() == Builtin::KindByte)
+ {
+ StringList metaData = s->getMetaData();
+ bool protobuf;
+ findMetaData(s, metaData, false, protobuf);
+ if(protobuf)
+ {
+ emitWarning((*q)->file(), (*q)->line(), "protobuf cannot be used as a class member in C++");
+ }
+ }
+ }
+
if(prot || (*q)->hasMetaData("protected"))
{
if(!inProtected)
@@ -4460,7 +4581,8 @@ Slice::Gen::ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p)
if(!allDataMembers.empty())
{
- C << sp << nl << p->scoped().substr(2) << "::" << fixKwd(p->name()) << spar << allParamDecls << epar << " :";
+ C << sp << nl << fixKwd(p->scoped()).substr(2) << "::" << fixKwd(p->name())
+ << spar << allParamDecls << epar << " :";
C.inc();
DataMemberList dataMembers = p->dataMembers();
@@ -5653,45 +5775,64 @@ Slice::Gen::validateMetaData(const UnitPtr& u)
}
bool
-Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
+Slice::Gen::MetaDataVisitor::visitUnitStart(const UnitPtr& p)
{
+ static const string prefix = "cpp:";
+
//
- // Validate global metadata.
+ // Validate global metadata in the top-level file and all included files.
//
- DefinitionContextPtr dc = p->definitionContext();
- assert(dc);
- StringList globalMetaData = dc->getMetaData();
- string file = dc->filename();
- static const string prefix = "cpp:";
+ StringList files = p->allFiles();
- int headerExtension = 0;
- for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q)
+ for(StringList::iterator q = files.begin(); q != files.end(); ++q)
{
- string s = *q;
- if(_history.count(s) == 0)
+ string file = *q;
+ DefinitionContextPtr dc = p->findDefinitionContext(file);
+ assert(dc);
+ StringList globalMetaData = dc->getMetaData();
+ int headerExtension = 0;
+ for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end(); ++r)
{
- if(s.find(prefix) == 0)
+ string s = *r;
+ if(_history.count(s) == 0)
{
- string ss = s.substr(prefix.size());
- if(ss.find("include:") == 0)
+ if(s.find(prefix) == 0)
{
- continue;
- }
- else if(ss.find("header-ext:") == 0)
- {
- headerExtension++;
- if(headerExtension == 1)
+ static const string cppIncludePrefix = "cpp:include:";
+ static const string cppHeaderExtPrefix = "cpp:header-ext:";
+ if(s.find(cppIncludePrefix) == 0 && s.size() > cppIncludePrefix.size())
{
continue;
}
+ else if(s.find(cppHeaderExtPrefix) == 0 && s.size() > cppHeaderExtPrefix.size())
+ {
+ headerExtension++;
+ if(headerExtension > 1)
+ {
+ ostringstream ostr;
+ ostr << "ignoring invalid global metadata `" << s
+ << "': directive can appear only once per file";
+ emitWarning(file, -1, ostr.str());
+ _history.insert(s);
+ }
+ continue;
+ }
+ ostringstream ostr;
+ ostr << "ignoring invalid global metadata `" << s << "'";
+ emitWarning(file, -1, ostr.str());
}
- cerr << file << ": warning: ignoring invalid global metadata `" << s << "', the cpp:header-ext global metadata can only appear once per file." << endl;
+ _history.insert(s);
}
- _history.insert(s);
}
}
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ return true;
+}
+
+bool
+Slice::Gen::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
+{
+ validate(p, p->getMetaData(), p->file(), p->line());
return true;
}
@@ -5703,13 +5844,13 @@ Slice::Gen::MetaDataVisitor::visitModuleEnd(const ModulePtr&)
void
Slice::Gen::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
}
bool
Slice::Gen::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
return true;
}
@@ -5721,7 +5862,7 @@ Slice::Gen::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&)
bool
Slice::Gen::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
return true;
}
@@ -5733,7 +5874,7 @@ Slice::Gen::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&)
bool
Slice::Gen::MetaDataVisitor::visitStructStart(const StructPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
return true;
}
@@ -5745,6 +5886,7 @@ Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&)
void
Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p)
{
+
bool ami = false;
ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container());
if(cl->hasMetaData("ami") || p->hasMetaData("ami") || cl->hasMetaData("amd") || p->hasMetaData("amd"))
@@ -5756,10 +5898,11 @@ Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p)
{
if(!cl->isLocal())
{
- cerr << p->definitionContext()->filename() << ":" << p->line()
- << ": warning: metadata directive `UserException' applies only to local operations "
+ ostringstream ostr;
+ ostr << "ignoring invalid metadata `UserException': directive applies only to local operations "
<< "but enclosing " << (cl->isInterface() ? "interface" : "class") << "`" << cl->name()
- << "' is not local" << endl;
+ << "' is not local";
+ emitWarning(p->file(), p->line(), ostr.str());
}
}
@@ -5775,60 +5918,86 @@ Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p)
{
if(q->find("cpp:type:", 0) == 0 || q->find("cpp:array", 0) == 0 || q->find("cpp:range", 0) == 0)
{
- cerr << p->definitionContext()->filename() << ":" << p->line()
- << ": warning: invalid metadata for operation" << endl;
+ emitWarning(p->file(), p->line(), "ignoring invalid metadata `" + *q +
+ "' for operation with void return type");
break;
}
}
}
else
{
- validate(returnType, metaData, p->definitionContext()->filename(), p->line(), ami);
+ validate(returnType, metaData, p->file(), p->line(), ami);
}
}
ParamDeclList params = p->parameters();
for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q)
{
- validate((*q)->type(), (*q)->getMetaData(), p->definitionContext()->filename(), (*q)->line(),
- ami || !(*q)->isOutParam());
+ validate((*q)->type(), (*q)->getMetaData(), p->file(), (*q)->line(), ami || !(*q)->isOutParam());
}
}
void
Slice::Gen::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
}
void
Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p)
{
- validate(p->type(), p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p->type(), p->getMetaData(), p->file(), p->line());
}
void
Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ StringList metaData = p->getMetaData();
+ const string file = p->file();
+ const string line = p->line();
+ static const string prefix = "cpp:protobuf";
+ for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); )
+ {
+ string s = *q++;
+ if(_history.count(s) == 0)
+ {
+ if(s.find(prefix) == 0)
+ {
+ //
+ // Remove from list so validate does not try to handle as well.
+ //
+ metaData.remove(s);
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type());
+ if(!builtin || builtin->kind() != Builtin::KindByte)
+ {
+ _history.insert(s);
+ emitWarning(file, line, "ignoring invalid metadata `" + s + "':\n"+
+ "`protobuf' encoding must be a byte sequence.");
+ }
+ }
+ }
+ }
+
+ validate(p, metaData, file, line);
}
void
Slice::Gen::MetaDataVisitor::visitDictionary(const DictionaryPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
}
void
Slice::Gen::MetaDataVisitor::visitEnum(const EnumPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
}
void
Slice::Gen::MetaDataVisitor::visitConst(const ConstPtr& p)
{
- validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line());
+ validate(p, p->getMetaData(), p->file(), p->line());
}
void
@@ -5867,8 +6036,7 @@ Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const Strin
{
continue;
}
-
- cerr << file << ":" << line << ": warning: ignoring invalid metadata `" << s << "'" << endl;
+ emitWarning(file, line, "ignoring invalid metadata `" + s + "'");
}
_history.insert(s);
}
@@ -5900,45 +6068,16 @@ Slice::Gen::resetUseWstring(list<bool>& hist)
}
string
-Slice::Gen::getHeaderExt(const string& file, const ModuleList& modules)
-{
- string ext = "";
- if(!modules.empty()) // Just in case the Slice file has no definitions
- {
- for(ModuleList::const_iterator i = modules.begin(); i != modules.end(); ++i)
- {
- if((*i)->definitionContext()->filename() == file)
- {
- string meta = (*i)->definitionContext()->findMetaData("cpp:header-ext");
- string::size_type index = meta.find_last_of(":");
- if(index != string::npos && index + 1 < meta.size())
- {
- ext = meta.substr(index + 1, meta.size() - index - 1);
- }
- }
- }
- }
- return ext;
-}
-
-string
-Slice::Gen::getHeaderExt(const ModuleList& modules)
+Slice::Gen::getHeaderExt(const string& file, const UnitPtr& unit)
{
- string ext = "";
- if(!modules.empty()) // Just in case the Slice file has no definitions
+ string ext;
+ static const string headerExtPrefix = "cpp:header-ext:";
+ DefinitionContextPtr dc = unit->findDefinitionContext(file);
+ assert(dc);
+ string meta = dc->findMetaData(headerExtPrefix);
+ if(meta.size() > headerExtPrefix.size())
{
- for(ModuleList::const_iterator i = modules.begin(); i != modules.end(); ++i)
- {
- if((*i)->definitionContext()->includeLevel() == 0)
- {
- string meta = (*i)->definitionContext()->findMetaData("cpp:header-ext");
- string::size_type index = meta.find_last_of(":");
- if(index != string::npos && index + 1 < meta.size())
- {
- ext = meta.substr(index + 1, meta.size() - index - 1);
- }
- }
- }
+ ext = meta.substr(headerExtPrefix.size());
}
return ext;
}
diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h
index 9cb699a205c..9f15d3fd6d9 100644
--- a/cpp/src/slice2cpp/Gen.h
+++ b/cpp/src/slice2cpp/Gen.h
@@ -46,17 +46,10 @@ private:
//
- // Get the header extension defined in the global metadata for a given file
- // if there isn't defined returns a empty string
+ // Returns the header extension defined in the global metadata for a given file,
+ // or an empty string if no global metadata was found.
//
- std::string getHeaderExt(const std::string& file, const ModuleList& modules);
-
- //
- // Get the header extension defined in the global metadata for the current
- // compiling file.
- // if there isn't defined returns a empty string
- //
- std::string getHeaderExt(const ModuleList& modules);
+ std::string getHeaderExt(const std::string& file, const UnitPtr& unit);
::IceUtilInternal::Output H;
::IceUtilInternal::Output C;
@@ -78,21 +71,6 @@ private:
bool _stream;
bool _ice;
- class GlobalIncludeVisitor : private ::IceUtil::noncopyable, public ParserVisitor
- {
- public:
-
- GlobalIncludeVisitor(::IceUtilInternal::Output&);
-
- virtual bool visitModuleStart(const ModulePtr&);
-
- private:
-
- ::IceUtilInternal::Output& H;
-
- bool _finished;
- };
-
class TypesVisitor : private ::IceUtil::noncopyable, public ParserVisitor
{
public:
@@ -416,6 +394,7 @@ private:
{
public:
+ virtual bool visitUnitStart(const UnitPtr&);
virtual bool visitModuleStart(const ModulePtr&);
virtual void visitModuleEnd(const ModulePtr&);
virtual void visitClassDecl(const ClassDeclPtr&);
diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp
index 86eafe9e64f..cdbefe44792 100644
--- a/cpp/src/slice2cpp/Main.cpp
+++ b/cpp/src/slice2cpp/Main.cpp
@@ -12,6 +12,7 @@
#include <IceUtil/StaticMutex.h>
#include <Slice/Preprocessor.h>
#include <Slice/FileTracker.h>
+#include <Slice/Util.h>
#include <Gen.h>
using namespace std;
@@ -84,6 +85,9 @@ main(int argc, char* argv[])
vector<string> args;
try
{
+#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600)
+ IceUtil::DummyBCC dummy;
+#endif
args = opts.parse(argc, (const char**)argv);
}
catch(const IceUtilInternal::BadOptException& e)
@@ -155,7 +159,7 @@ main(int argc, char* argv[])
if(args.empty())
{
- cerr << argv[0] << ": no input file" << endl;
+ getErrorStream() << argv[0] << ": error: no input file" << endl;
usage(argv[0]);
return EXIT_FAILURE;
}
@@ -169,15 +173,15 @@ main(int argc, char* argv[])
{
if(depend)
{
- Preprocessor icecpp(argv[0], *i, cppArgs, sourceExtension);
- if(!icecpp.printMakefileDependencies(Preprocessor::CPlusPlus, includePaths))
+ Preprocessor icecpp(argv[0], *i, cppArgs);
+ if(!icecpp.printMakefileDependencies(Preprocessor::CPlusPlus, includePaths, sourceExtension))
{
return EXIT_FAILURE;
}
}
else
{
- Preprocessor icecpp(argv[0], *i, cppArgs, sourceExtension);
+ Preprocessor icecpp(argv[0], *i, cppArgs);
FILE* cppHandle = icecpp.preprocess(false);
if(cppHandle == 0)
@@ -229,7 +233,7 @@ main(int argc, char* argv[])
// cleanup any created files.
FileTracker::instance()->cleanup();
u->destroy();
- cerr << argv[0] << ": " << ex.reason() << endl;
+ getErrorStream() << argv[0] << ": error: " << ex.reason() << endl;
return EXIT_FAILURE;
}
}
diff --git a/cpp/src/slice2cpp/Makefile.mak b/cpp/src/slice2cpp/Makefile.mak
index 847211d4f52..e039744dea8 100644
--- a/cpp/src/slice2cpp/Makefile.mak
+++ b/cpp/src/slice2cpp/Makefile.mak
@@ -26,7 +26,7 @@ CPPFLAGS = -I. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
PDBFLAGS = /pdb:$(NAME:.exe=.pdb)
!endif
-!if "$(CPP_COMPILER)" == "BCC2007"
+!if "$(BCPLUSPLUS)" == "yes"
RES_FILE = ,, Slice2Cpp.res
!else
RES_FILE = Slice2Cpp.res
@@ -46,7 +46,7 @@ install:: all
copy $(NAME) $(install_bindir)
-!if "$(CPP_COMPILER)" == "BCC2007" && "$(OPTIMIZE)" != "yes"
+!if "$(BCPLUSPLUS)" == "yes" && "$(OPTIMIZE)" != "yes"
install:: all
copy $(NAME:.exe=.tds) $(install_bindir)