diff options
Diffstat (limited to 'cpp/src/slice2cpp/Gen.cpp')
-rw-r--r-- | cpp/src/slice2cpp/Gen.cpp | 5543 |
1 files changed, 3945 insertions, 1598 deletions
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 2e5e9b2a3f5..140438eb37e 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -14,7 +14,8 @@ #include <IceUtil/Functional.h> #include <IceUtil/Iterator.h> #include <IceUtil/InputUtil.h> -#include <IceUtil/Unicode.h> +#include <IceUtil/StringConverter.h> +#include <IceUtil/StringUtil.h> #include <Slice/Checksum.h> #include <Slice/FileTracker.h> #include <IceUtil/FileUtil.h> @@ -30,8 +31,58 @@ using namespace IceUtilInternal; namespace { +bool +isConstexprType(const TypePtr& type) +{ + BuiltinPtr bp = BuiltinPtr::dynamicCast(type); + if(bp) + { + switch(bp->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + case Builtin::KindValue: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + { + return true; + } + default: + { + return false; + } + } + } + else if(EnumPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type)) + { + return true; + } + else + { + StructPtr s = StructPtr::dynamicCast(type); + if(s) + { + DataMemberList members = s->dataMembers(); + for(DataMemberList::const_iterator i = members.begin(); i != members.end(); ++i) + { + if(!isConstexprType((*i)->type())) + { + return false; + } + } + return true; + } + return false; + } +} + string -u32CodePoint(unsigned int value) +u32CodePoint(unsigned int value, bool cpp11) { ostringstream s; // @@ -39,7 +90,7 @@ u32CodePoint(unsigned int value) // With VC++ < 140 characters in the range of 0 to 0x9f cannot be represented // with a universal character name (UCN). // - if(value <= 0x9f) + if(!cpp11 && value <= 0x9f) { switch(value) { @@ -79,28 +130,13 @@ u32CodePoint(unsigned int value) } void -writeU8Buffer(const vector<unsigned char>& u8buffer, ::IceUtilInternal::Output& out) +writeU8Buffer(const vector<unsigned char>& u8buffer, ::IceUtilInternal::Output& out, bool cpp11) { - vector<unsigned int> u32buffer; - IceUtilInternal::ConversionResult result = convertUTF8ToUTF32(u8buffer, u32buffer, IceUtil::lenientConversion); - switch(result) - { - case conversionOK: - break; - case sourceExhausted: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source exhausted"); - case sourceIllegal: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source illegal"); - default: - { - assert(0); - throw IceUtil::IllegalConversionException(__FILE__, __LINE__); - } - } + vector<unsigned int> u32buffer = toUTF32(u8buffer); for(vector<unsigned int>::const_iterator c = u32buffer.begin(); c != u32buffer.end(); ++c) { - out << u32CodePoint(*c); + out << u32CodePoint(*c, cpp11); } } @@ -123,7 +159,7 @@ getDeprecateSymbol(const ContainedPtr& p1, const ContainedPtr& p2) void writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const SyntaxTreeBasePtr& valueType, - const string& value, int useWstring, const StringList& metaData) + const string& value, int useWstring, const StringList& metaData, bool cpp11 = false) { ConstPtr constant = ConstPtr::dynamicCast(valueType); if(constant) @@ -144,21 +180,21 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt "0123456789" "_{}[]#()<>%:;.?*+-/^&|~!=,\\\"' "; static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); - - if((useWstring & TypeContextUseWstring) || findMetaData(metaData) == "wstring") + bool wide = (useWstring & TypeContextUseWstring) || findMetaData(metaData) == "wstring"; + if(wide || cpp11) { // - // Wide strings + // Wide strings or C++11 narrow string // vector<unsigned char> u8buffer; // Buffer to convert multibyte characters - out << "L\""; + out << (wide ? "L\"" : "u8\""); for(size_t i = 0; i < value.size();) { if(charSet.find(value[i]) == charSet.end()) { if(static_cast<unsigned char>(value[i]) < 128) // Single byte character { - out << u32CodePoint(static_cast<unsigned char>(value[i])); + out << u32CodePoint(static_cast<unsigned char>(value[i]), cpp11); } else { @@ -172,7 +208,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt // if(!u8buffer.empty()) { - writeU8Buffer(u8buffer, out); + writeU8Buffer(u8buffer, out, cpp11); u8buffer.clear(); } @@ -210,7 +246,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt assert(codepoint.size() == sz); IceUtil::Int64 v = IceUtilInternal::strToInt64(codepoint.c_str(), 0, 16); - out << u32CodePoint(static_cast<unsigned int>(v)); + out << u32CodePoint(static_cast<unsigned int>(v), cpp11); i = j + 1 + sz; } @@ -239,12 +275,12 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt // if(!u8buffer.empty()) { - writeU8Buffer(u8buffer, out); + writeU8Buffer(u8buffer, out, cpp11); u8buffer.clear(); } out << "\""; } - else // narrow strings + else // C++98 narrow strings { out << "\""; // Opening " @@ -302,23 +338,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt vector<unsigned int> u32buffer; u32buffer.push_back(static_cast<unsigned int>(v)); - vector<unsigned char> u8buffer; - - IceUtilInternal::ConversionResult result = convertUTF32ToUTF8(u32buffer, u8buffer, IceUtil::lenientConversion); - switch(result) - { - case conversionOK: - break; - case sourceExhausted: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source exhausted"); - case sourceIllegal: - throw IceUtil::IllegalConversionException(__FILE__, __LINE__, "string source illegal"); - default: - { - assert(0); - throw IceUtil::IllegalConversionException(__FILE__, __LINE__); - } - } + vector<unsigned char> u8buffer = fromUTF32(u32buffer); ostringstream s; for(vector<unsigned char>::const_iterator q = u8buffer.begin(); q != u8buffer.end(); ++q) @@ -356,7 +376,14 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt } else if(bp && bp->kind() == Builtin::KindLong) { - out << "ICE_INT64(" << value << ")"; + if(cpp11) + { + out << value << "LL"; + } + else + { + out << "ICE_INT64(" << value << ")"; + } } else if(bp && bp->kind() == Builtin::KindFloat) { @@ -372,7 +399,24 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt EnumPtr ep = EnumPtr::dynamicCast(type); if(ep) { - out << fixKwd(value); + bool unscoped = findMetaData(ep->getMetaData(), cpp11 ? TypeContextCpp11 : 0) == "%unscoped"; + if(!cpp11 || unscoped) + { + out << fixKwd(value); + } + else + { + string v = value; + string scope; + size_t pos = value.rfind("::"); + if(pos != string::npos) + { + v = value.substr(pos + 2); + scope = value.substr(0, value.size() - v.size()); + } + + out << fixKwd(scope + ep->name() + "::" + v); + } } else { @@ -382,39 +426,34 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt } } -void -writeMarshalUnmarshalDataMember(IceUtilInternal::Output& C, const DataMemberPtr& p, bool marshal) -{ - writeMarshalUnmarshalCode(C, p->type(), p->optional(), p->tag(), fixKwd(p->name()), marshal, p->getMetaData()); -} - -void -writeMarshalUnmarshalDataMemberInHolder(IceUtilInternal::Output& C, const string& holder, const DataMemberPtr& p, bool marshal) +string +toDllClassExport(const string& dllExport) { - writeMarshalUnmarshalCode(C, p->type(), p->optional(), p->tag(), holder + fixKwd(p->name()), marshal, p->getMetaData()); + if(!dllExport.empty()) + { + return "ICE_CLASS(" + dllExport.substr(0, dllExport.size() - 1) + ") "; + } + else + { + return ""; + } } -void -writeMarshalUnmarshalDataMembers(IceUtilInternal::Output& C, - const DataMemberList& dataMembers, - const DataMemberList& optionalDataMembers, - bool marshal) +string +toDllMemberExport(const string& dllExport) { - for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + if(!dllExport.empty()) { - if(!(*q)->optional()) - { - writeMarshalUnmarshalDataMember(C, *q, marshal); - } + return "ICE_MEMBER(" + dllExport.substr(0, dllExport.size() - 1) + ") "; } - for(DataMemberList::const_iterator q = optionalDataMembers.begin(); q != optionalDataMembers.end(); ++q) + else { - writeMarshalUnmarshalDataMember(C, *q, marshal); + return ""; } } void -writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& members, int useWstring) +writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& members, int useWstring, bool cpp11 = false) { bool first = true; for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) @@ -433,18 +472,163 @@ writeDataMemberInitializers(IceUtilInternal::Output& C, const DataMemberList& me } C << nl << memberName << '('; writeConstantValue(C, (*p)->type(), (*p)->defaultValueType(), (*p)->defaultValue(), useWstring, - (*p)->getMetaData()); + (*p)->getMetaData(), cpp11); C << ')'; } } } +void +writeInParamsLambda(IceUtilInternal::Output& C, const OperationPtr& p, const ParamDeclList& inParams) +{ + if(inParams.empty()) + { + C << "nullptr"; + } + else + { + C << "[&](::Ice::OutputStream* __os)"; + C << sb; + writeMarshalCode(C, inParams, 0, true, TypeContextInParam | TypeContextCpp11); + if(p->sendsClasses(false)) + { + C << nl << "__os->writePendingValues();"; + } + C << eb; + } +} + +void +throwUserExceptionLambda(IceUtilInternal::Output& C, ExceptionList throws) +{ + if(throws.empty()) + { + C << "nullptr"; + } + else + { + throws.sort(); + throws.unique(); + + // + // Arrange exceptions into most-derived to least-derived order. If we don't + // do this, a base exception handler can appear before a derived exception + // handler, causing compiler warnings and resulting in the base exception + // being marshaled instead of the derived exception. + // + throws.sort(Slice::DerivedToBaseCompare()); + + C << "[](const ::Ice::UserException& __ex)"; + C << sb; + C << nl << "try"; + C << sb; + C << nl << "__ex.ice_throw();"; + C << eb; + // + // Generate a catch block for each legal user exception. + // + for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i) + { + string scoped = (*i)->scoped(); + C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)"; + C << sb; + C << nl << "throw;"; + C << eb; + } + C << nl << "catch(const ::Ice::UserException&)"; + C << sb; + C << eb; + C << eb; + } +} + +string +resultStructName(const string& name, const string& scope = "", bool marshaledResult = false) +{ + assert(!name.empty()); + string stName = IceUtilInternal::toUpper(name.substr(0, 1)) + name.substr(1); + stName += marshaledResult ? "MarshaledResult" : "Result"; + if(!scope.empty()) + { + stName = scope + "::" + stName; + } + return stName; +} + +void +emitOpNameResult(IceUtilInternal::Output& H, const OperationPtr& p, int useWstring) +{ + string name = p->name(); + + TypePtr ret = p->returnType(); + string retS = returnTypeToString(ret, p->returnIsOptional(), p->getMetaData(), useWstring | TypeContextCpp11); + + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + + for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + outParams.push_back(*q); + } + } + + if((outParams.size() > 1) || (ret && outParams.size() > 0)) + { + // + // Generate OpNameResult struct + // + list<string> dataMembers; + string returnValueS = "returnValue"; + + for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q) + { + string typeString = typeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), + useWstring | TypeContextCpp11); + + dataMembers.push_back(typeString + " " + fixKwd((*q)->name())); + + if((*q)->name() == "returnValue") + { + returnValueS = "_returnValue"; + } + } + + if(ret) + { + dataMembers.push_front(retS + " " + returnValueS); + } + + H << sp; + H << nl << "struct " << resultStructName(name); + H << sb; + for(list<string>::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + H << nl << *q << ";"; + } + H << eb << ";"; + } +} + +string +condMove(bool moveIt, const string& str) +{ + return moveIt ? string("::std::move(") + str + ")" : str; +} + +string +condString(bool ok, const string& str) +{ + return ok ? str : ""; +} + } Slice::Gen::Gen(const string& base, const string& headerExtension, const string& sourceExtension, const vector<string>& extraHeaders, const string& include, const vector<string>& includePaths, const string& dllExport, const string& dir, - bool imp, bool checksum, bool stream, bool ice) : + bool implCpp98, bool implCpp11, bool checksum, bool ice) : _base(base), _headerExtension(headerExtension), _implHeaderExtension(headerExtension), @@ -454,9 +638,9 @@ Slice::Gen::Gen(const string& base, const string& headerExtension, const string& _includePaths(includePaths), _dllExport(dllExport), _dir(dir), - _impl(imp), + _implCpp98(implCpp98), + _implCpp11(implCpp11), _checksum(checksum), - _stream(stream), _ice(ice) { for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p) @@ -477,7 +661,7 @@ Slice::Gen::~Gen() H << "\n#endif\n"; C << '\n'; - if(_impl) + if(_implCpp98 || _implCpp11) { implH << "\n\n#endif\n"; implC << '\n'; @@ -485,6 +669,38 @@ Slice::Gen::~Gen() } void +Slice::Gen::generateChecksumMap(const UnitPtr& p) +{ + if(_checksum) + { + ChecksumMap map = createChecksums(p); + if(!map.empty()) + { + C << sp << nl << "namespace"; + C << nl << "{"; + C << sp << nl << "const char* __sliceChecksums[] ="; + C << sb; + for(ChecksumMap::const_iterator q = map.begin(); q != map.end(); ++q) + { + C << nl << "\"" << q->first << "\", \""; + ostringstream str; + str.flags(ios_base::hex); + str.fill('0'); + for(vector<unsigned char>::const_iterator r = q->second.begin(); r != q->second.end(); ++r) + { + str << static_cast<int>(*r); + } + C << str.str() << "\","; + } + C << nl << "0"; + C << eb << ';'; + C << nl << "const IceInternal::SliceChecksumInit __sliceChecksumInit(__sliceChecksums);"; + C << sp << nl << "}"; + } + } +} + +void Slice::Gen::generate(const UnitPtr& p) { string file = p->topLevelFile(); @@ -498,7 +714,7 @@ Slice::Gen::generate(const UnitPtr& p) _headerExtension = headerExtension; } - if(_impl) + if(_implCpp98 || _implCpp11) { string fileImplH = _base + "I." + _implHeaderExtension; string fileImplC = _base + "I." + _sourceExtension; @@ -540,7 +756,7 @@ Slice::Gen::generate(const UnitPtr& p) } FileTracker::instance()->addFile(fileImplC); - string s = fileImplH; + string s = _base + "I." + _implHeaderExtension; if(_include.size()) { s = _include + '/' + s; @@ -583,7 +799,7 @@ Slice::Gen::generate(const UnitPtr& p) printGeneratedHeader(C, _base + ".ice"); - string s = fileH; + string s = _base + "." + _headerExtension;; if(_include.size()) { s = _include + '/' + s; @@ -612,66 +828,61 @@ Slice::Gen::generate(const UnitPtr& p) C << _base << "." << _headerExtension << ">"; C << "\n#include <IceUtil/PushDisableWarnings.h>"; - H << "\n#include <IceUtil/PushDisableWarnings.h>"; H << "\n#include <Ice/ProxyF.h>"; H << "\n#include <Ice/ObjectF.h>"; + H << "\n#include <Ice/ValueF.h>"; H << "\n#include <Ice/Exception.h>"; H << "\n#include <Ice/LocalObject.h>"; H << "\n#include <Ice/StreamHelpers.h>"; + H << "\n#include <Ice/Comparable.h>"; if(p->hasNonLocalClassDefs()) { H << "\n#include <Ice/Proxy.h>"; + H << "\n#include <Ice/Object.h>"; H << "\n#include <Ice/GCObject.h>"; - H << "\n#include <Ice/AsyncResult.h>"; + H << "\n#include <Ice/Value.h>"; H << "\n#include <Ice/Incoming.h>"; if(p->hasContentsWithMetaData("amd")) { H << "\n#include <Ice/IncomingAsync.h>"; } C << "\n#include <Ice/LocalException.h>"; - C << "\n#include <Ice/ObjectFactory.h>"; - C << "\n#include <Ice/Outgoing.h>"; + C << "\n#include <Ice/ValueFactory.h>"; C << "\n#include <Ice/OutgoingAsync.h>"; } else if(p->hasLocalClassDefsWithAsync()) { - H << "\n#include <Ice/Proxy.h>"; - H << "\n#include <Ice/AsyncResult.h>"; - C << "\n#include <Ice/OutgoingAsync.h>"; + H << "\n#include <Ice/OutgoingAsync.h>"; } else if(p->hasNonLocalClassDecls()) { H << "\n#include <Ice/Proxy.h>"; } - if(p->hasNonLocalDataOnlyClasses() || p->hasNonLocalExceptions()) + if(p->hasNonLocalClassDefs() || p->hasNonLocalExceptions()) { H << "\n#include <Ice/FactoryTableInit.h>"; } H << "\n#include <IceUtil/ScopedArray.h>"; - H << "\n#include <IceUtil/Optional.h>"; + H << "\n#include <Ice/Optional.h>"; - if(p->usesNonLocals()) + if(p->hasExceptions()) { - C << "\n#include <Ice/BasicStream.h>"; + H << "\n#include <Ice/ExceptionHelpers.h>"; } - if(_stream || p->hasNonLocalClassDefs() || p->hasNonLocalExceptions()) + if(p->usesNonLocals()) { - if(!p->hasNonLocalClassDefs()) - { - C << "\n#include <Ice/LocalException.h>"; - } - - H << "\n#include <Ice/StreamF.h>"; + C << "\n#include <Ice/InputStream.h>"; + C << "\n#include <Ice/OutputStream.h>"; + } - if(_stream) - { - C << "\n#include <Ice/Stream.h>"; - } + if(p->hasNonLocalExceptions()) + { + C << "\n#include <Ice/LocalException.h>"; } if(p->hasContentsWithMetaData("preserve-slice")) @@ -685,7 +896,6 @@ Slice::Gen::generate(const UnitPtr& p) C << "\n#include <Ice/SliceChecksums.h>"; } - C << "\n#include <IceUtil/Iterator.h>"; C << "\n#include <IceUtil/PopDisableWarnings.h>"; StringList includes = p->includeFiles(); @@ -730,96 +940,153 @@ Slice::Gen::generate(const UnitPtr& p) _dllExport += " "; } - ProxyDeclVisitor proxyDeclVisitor(H, C, _dllExport); - p->visit(&proxyDeclVisitor, false); - - ObjectDeclVisitor objectDeclVisitor(H, C, _dllExport); - p->visit(&objectDeclVisitor, false); + H << sp; + H.zeroIndent(); + H << nl << "#ifdef ICE_CPP11_MAPPING // C++11 mapping"; + H.restoreIndent(); - TypesVisitor typesVisitor(H, C, _dllExport, _stream); - p->visit(&typesVisitor, false); + C << sp; + C.zeroIndent(); + C << nl << "#ifdef ICE_CPP11_MAPPING // C++11 mapping"; + C.restoreIndent(); + { + normalizeMetaData(p, true); - StreamVisitor streamVisitor(H, C, _dllExport); - p->visit(&streamVisitor, false); + Cpp11DeclVisitor declVisitor(H, C, _dllExport); + p->visit(&declVisitor, false); - AsyncVisitor asyncVisitor(H, C, _dllExport); - p->visit(&asyncVisitor, false); + Cpp11TypesVisitor typesVisitor(H, C, _dllExport); + p->visit(&typesVisitor, false); - AsyncImplVisitor asyncImplVisitor(H, C, _dllExport); - p->visit(&asyncImplVisitor, false); + Cpp11LocalObjectVisitor localObjectVisitor(H, C, _dllExport); + p->visit(&localObjectVisitor, false); - // - // The templates are emitted before the proxy definition - // so the derivation hierarchy is known to the proxy: - // the proxy relies on knowing the hierarchy to make the begin_ - // methods type-safe. - // - AsyncCallbackVisitor asyncCallbackVisitor(H, C, _dllExport); - p->visit(&asyncCallbackVisitor, false); + Cpp11InterfaceVisitor interfaceVisitor(H, C, _dllExport); + p->visit(&interfaceVisitor, false); - ProxyVisitor proxyVisitor(H, C, _dllExport); - p->visit(&proxyVisitor, false); + Cpp11ValueVisitor valueVisitor(H, C, _dllExport); + p->visit(&valueVisitor, false); - ObjectVisitor objectVisitor(H, C, _dllExport, _stream); - p->visit(&objectVisitor, false); + Cpp11ProxyVisitor proxyVisitor(H, C, _dllExport); + p->visit(&proxyVisitor, false); - // - // We need to delay generating the template after the proxy - // definition, because completed calls the begin_ method in the - // proxy. - // - AsyncCallbackTemplateVisitor asyncCallbackTemplateVisitor(H, C, _dllExport); - p->visit(&asyncCallbackTemplateVisitor, false); + Cpp11StreamVisitor streamVisitor(H, C, _dllExport); + p->visit(&streamVisitor, false); - if(_impl) - { - implH << "\n#include <"; - if(_include.size()) + if(_implCpp11) { - implH << _include << '/'; - } - implH << _base << "." << _headerExtension << ">"; + implH << "\n#include <"; + if(_include.size()) + { + implH << _include << '/'; + } + implH << _base << "." << _headerExtension << ">"; + implH << nl << "//base"; + writeExtraHeaders(implC); - writeExtraHeaders(implC); + implC << "\n#include <"; + if(_include.size()) + { + implC << _include << '/'; + } + implC << _base << "I." << _implHeaderExtension << ">"; - implC << "\n#include <"; - if(_include.size()) - { - implC << _include << '/'; + Cpp11ImplVisitor implVisitor(implH, implC, _dllExport); + p->visit(&implVisitor, false); } - implC << _base << "I." << _implHeaderExtension << ">"; - ImplVisitor implVisitor(implH, implC, _dllExport); - p->visit(&implVisitor, false); + Cpp11CompatibilityVisitor compatibilityVisitor(H, C, _dllExport); + p->visit(&compatibilityVisitor, false); + + generateChecksumMap(p); } + H << sp; + H.zeroIndent(); + H << nl << "#else // C++98 mapping"; + H.restoreIndent(); - if(_checksum) + C << sp; + C.zeroIndent(); + C << nl << "#else // C++98 mapping"; + C.restoreIndent(); { - ChecksumMap map = createChecksums(p); - if(!map.empty()) + normalizeMetaData(p, false); + + ProxyDeclVisitor proxyDeclVisitor(H, C, _dllExport); + p->visit(&proxyDeclVisitor, false); + + ObjectDeclVisitor objectDeclVisitor(H, C, _dllExport); + p->visit(&objectDeclVisitor, false); + + TypesVisitor typesVisitor(H, C, _dllExport); + p->visit(&typesVisitor, false); + + AsyncVisitor asyncVisitor(H, C, _dllExport); + p->visit(&asyncVisitor, false); + + AsyncImplVisitor asyncImplVisitor(H, C, _dllExport); + p->visit(&asyncImplVisitor, false); + + // + // The templates are emitted before the proxy definition + // so the derivation hierarchy is known to the proxy: + // the proxy relies on knowing the hierarchy to make the begin_ + // methods type-safe. + // + AsyncCallbackVisitor asyncCallbackVisitor(H, C, _dllExport); + p->visit(&asyncCallbackVisitor, false); + + ProxyVisitor proxyVisitor(H, C, _dllExport); + p->visit(&proxyVisitor, false); + + ObjectVisitor objectVisitor(H, C, _dllExport); + p->visit(&objectVisitor, false); + + StreamVisitor streamVisitor(H, C, _dllExport); + p->visit(&streamVisitor, false); + + // + // We need to delay generating the template after the proxy + // definition, because completed calls the begin_ method in the + // proxy. + // + AsyncCallbackTemplateVisitor asyncCallbackTemplateVisitor(H, C, _dllExport); + p->visit(&asyncCallbackTemplateVisitor, false); + + if(_implCpp98) { - C << sp << nl << "namespace"; - C << nl << "{"; - C << sp << nl << "const char* __sliceChecksums[] ="; - C << sb; - for(ChecksumMap::const_iterator q = map.begin(); q != map.end(); ++q) + implH << "\n#include <"; + if(_include.size()) { - C << nl << "\"" << q->first << "\", \""; - ostringstream str; - str.flags(ios_base::hex); - str.fill('0'); - for(vector<unsigned char>::const_iterator r = q->second.begin(); r != q->second.end(); ++r) - { - str << static_cast<int>(*r); - } - C << str.str() << "\","; + implH << _include << '/'; } - C << nl << "0"; - C << eb << ';'; - C << nl << "const IceInternal::SliceChecksumInit __sliceChecksumInit(__sliceChecksums);"; - C << sp << nl << "}"; + implH << _base << "." << _headerExtension << ">"; + + writeExtraHeaders(implC); + + implC << "\n#include <"; + if(_include.size()) + { + implC << _include << '/'; + } + implC << _base << "I." << _implHeaderExtension << ">"; + + ImplVisitor implVisitor(implH, implC, _dllExport); + p->visit(&implVisitor, false); } + + generateChecksumMap(p); } + + H << sp; + H.zeroIndent(); + H << nl << "#endif"; + H.restoreIndent(); + + C << sp; + C.zeroIndent(); + C << nl << "#endif"; + C.restoreIndent(); } void @@ -858,8 +1125,8 @@ Slice::Gen::writeExtraHeaders(IceUtilInternal::Output& out) } } -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) +Slice::Gen::TypesVisitor::TypesVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport), _doneStaticSymbol(false), _useWstring(false) { } @@ -979,7 +1246,6 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) H << nl << "virtual ~" << name << "() throw();"; H << sp; - if(!p->isLocal()) { string initName = p->flattenedScope() + p->name() + "_init"; @@ -1076,10 +1342,10 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) C << sb; C << eb; - H << nl << "virtual ::std::string ice_name() const;"; - C << sp << nl << "::std::string" << nl << scoped.substr(2) << "::ice_name() const"; + H << nl << "virtual ::std::string ice_id() const;"; + C << sp << nl << "::std::string" << nl << scoped.substr(2) << "::ice_id() const"; C << sb; - C << nl << "return \"" << p->scoped().substr(2) << "\";"; + C << nl << "return \"" << p->scoped() << "\";"; C << eb; StringList metaData = p->getMetaData(); @@ -1137,135 +1403,73 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) if(preserved && !basePreserved) { - H << sp << nl << "virtual void __write(::IceInternal::BasicStream*) const;"; - H << nl << "virtual void __read(::IceInternal::BasicStream*);"; + H << sp << nl << "virtual void __write(::Ice::OutputStream*) const;"; + H << nl << "virtual void __read(::Ice::InputStream*);"; - if(_stream) - { - H << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;"; - H << nl << "virtual void __read(const ::Ice::InputStreamPtr&);"; - } - else - { - string baseName = base ? fixKwd(base->scoped()) : string("::Ice::UserException"); - H << nl << "using " << baseName << "::__write;"; - H << nl << "using " << baseName << "::__read;"; - } + string baseName = base ? fixKwd(base->scoped()) : string("::Ice::UserException"); + H << nl << "using " << baseName << "::__write;"; + H << nl << "using " << baseName << "::__read;"; } H.dec(); H << sp << nl << "protected:"; H.inc(); - H << nl << "virtual void __writeImpl(::IceInternal::BasicStream*) const;"; - H << nl << "virtual void __readImpl(::IceInternal::BasicStream*);"; + H << sp << nl << "virtual void __writeImpl(::Ice::OutputStream*) const;"; + H << nl << "virtual void __readImpl(::Ice::InputStream*);"; - if(_stream) - { - H << nl << "virtual void __writeImpl(const ::Ice::OutputStreamPtr&) const;"; - H << nl << "virtual void __readImpl(const ::Ice::InputStreamPtr&);"; - } - else - { - string baseName = base ? fixKwd(base->scoped()) : string("::Ice::UserException"); - H << nl << "using " << baseName << "::__writeImpl;"; - H << nl << "using " << baseName << "::__readImpl;"; - } + string baseName = base ? fixKwd(base->scoped()) : string("::Ice::UserException"); if(preserved && !basePreserved) { H << sp << nl << "::Ice::SlicedDataPtr __slicedData;"; - C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::IceInternal::BasicStream* __os) const"; + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::Ice::OutputStream* __os) const"; C << sb; - C << nl << "__os->startWriteException(__slicedData);"; + C << nl << "__os->startException(__slicedData);"; C << nl << "__writeImpl(__os);"; - C << nl << "__os->endWriteException();"; + C << nl << "__os->endException();"; C << eb; - C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is)"; + C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::Ice::InputStream* __is)"; C << sb; - C << nl << "__is->startReadException();"; + C << nl << "__is->startException();"; C << nl << "__readImpl(__is);"; - C << nl << "__slicedData = __is->endReadException(true);"; + C << nl << "__slicedData = __is->endException(true);"; C << eb; } - C << sp << nl << "void" << nl << scoped.substr(2) << "::__writeImpl(::IceInternal::BasicStream* __os) const"; + C << sp << nl << "void" << nl << scoped.substr(2) << "::__writeImpl(::Ice::OutputStream* __os) const"; C << sb; - C << nl << "__os->startWriteSlice(\"" << p->scoped() << "\", -1, " << (!base ? "true" : "false") << ");"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), true); - C << nl << "__os->endWriteSlice();"; + C << nl << "__os->startSlice(\"" << p->scoped() << "\", -1, " << (!base ? "true" : "false") << ");"; + C << nl << "Ice::StreamWriter< ::" << scoped.substr(2) << ", ::Ice::OutputStream>::write(__os, *this);"; + C << nl << "__os->endSlice();"; if(base) { emitUpcall(base, "::__writeImpl(__os);"); } C << eb; - C << sp << nl << "void" << nl << scoped.substr(2) << "::__readImpl(::IceInternal::BasicStream* __is)"; + C << sp << nl << "void" << nl << scoped.substr(2) << "::__readImpl(::Ice::InputStream* __is)"; C << sb; - C << nl << "__is->startReadSlice();"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), false); - C << nl << "__is->endReadSlice();"; + C << nl << "__is->startSlice();"; + C << nl << "Ice::StreamReader< ::" << scoped.substr(2) << ", ::Ice::InputStream>::read(__is, *this);"; + C << nl << "__is->endSlice();"; if(base) { emitUpcall(base, "::__readImpl(__is);"); } C << eb; - - if(_stream) - { - if(preserved && !basePreserved) - { - C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __os) const"; - C << sb; - C << nl << "__os->startException(__slicedData);"; - C << nl << "__writeImpl(__os);"; - C << nl << "__os->endException();"; - C << eb; - - C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr& __is)"; - C << sb; - C << nl << "__is->startException();"; - C << nl << "__readImpl(__is);"; - C << nl << "__slicedData = __is->endException(true);"; - C << eb; - } - - C << sp << nl << "void" << nl << scoped.substr(2) - << "::__writeImpl(const ::Ice::OutputStreamPtr& __os) const"; - C << sb; - C << nl << "__os->startSlice(\"" << p->scoped() << "\", -1, " << (!base ? "true" : "false") << ");"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), true); - C << nl << "__os->endSlice();"; - if(base) - { - emitUpcall(base, "::__writeImpl(__os);"); - } - C << eb; - - C << sp << nl << "void" << nl << scoped.substr(2) - << "::__readImpl(const ::Ice::InputStreamPtr& __is)"; - C << sb; - C << nl << "__is->startSlice();"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), false); - C << nl << "__is->endSlice();"; - if(base) - { - emitUpcall(base, "::__readImpl(__is);"); - } - C << eb; - } } H << eb << ';'; if(!p->isLocal()) { // - // We need an instance here to trigger initialization if the implementation is in a shared libarry. + // We need an instance here to trigger initialization if the implementation is in a static library. // But we do this only once per source file, because a single instance is sufficient to initialize - // all of the globals in a shared library. + // all of the globals in a compilation unit. // if(!_doneStaticSymbol) { @@ -1288,7 +1492,7 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) bool classMetaData = findMetaData(p->getMetaData()) == "%class"; if(classMetaData) { - H << sp << nl << "class " << _dllExport << name << " : public IceUtil::Shared"; + H << sp << nl << "class " << name << " : public IceUtil::Shared"; H << sb; H.dec(); H << nl << "public:"; @@ -1340,10 +1544,6 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) } H << nl; - if(!classMetaData) - { - H << _dllExport; - } if(paramDecls.size() == 1) { H << "explicit "; @@ -1622,13 +1822,14 @@ Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p) string scoped = fixKwd(p->scoped()); H << sp << nl << "class " << name << ';'; - H << nl << _dllExport << "void __read(::IceInternal::BasicStream*, ::IceInternal::ProxyHandle< ::IceProxy" + H << nl << _dllExport << "void __read(::Ice::InputStream*, ::IceInternal::ProxyHandle< ::IceProxy" << scoped << ">&);"; H << nl << _dllExport << "::IceProxy::Ice::Object* upCast(::IceProxy" << scoped << "*);"; } Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) : - H(h), C(c), _dllExport(dllExport), _useWstring(false) + H(h), C(c), _dllExport(dllExport), _dllClassExport(toDllClassExport(dllExport)), + _dllMemberExport(toDllMemberExport(dllExport)), _useWstring(false) { } @@ -1691,49 +1892,74 @@ Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) string scoped = fixKwd(p->scoped()); ClassList bases = p->bases(); - H << sp << nl << "class " << _dllExport << name << " : "; - if(bases.empty()) - { - H << "virtual public ::IceProxy::Ice::Object"; - } - else + if(bases.size() > 1) { + // + // Generated helper class to deal with multiple inheritance + // when using Proxy template. + // + + string baseName = fixKwd("_" + p->name() + "Base"); + + H << sp << nl << "class " << _dllClassExport << baseName << " : "; H.useCurrentPosAsIndent(); - ClassList::const_iterator q = bases.begin(); - while(q != bases.end()) + for(ClassList::const_iterator q = bases.begin(); q != bases.end();) { - H << "virtual public ::IceProxy" << fixKwd((*q)->scoped()); + H << "public virtual ::IceProxy" << fixKwd((*q)->scoped()); if(++q != bases.end()) { - H << ',' << nl; + H << ", " << nl; } } H.restoreIndent(); + H << sb; + + H.dec(); + H << nl << "public:"; + H.inc(); + + // Out of line dtor to avoid weak vtable + H << sp << nl << _dllMemberExport << "virtual ~" << baseName << "();"; + C << sp; + C << nl << "::IceProxy" << scope << baseName << "::~" << baseName << "()"; + C << sb; + C << eb; + + H.dec(); + H << sp << nl << "protected:"; + H.inc(); + + H << sp << nl << "virtual Object* __newInstance() const = 0;"; + H << eb << ';'; } + H << sp << nl << "class " << _dllClassExport << name << " : "; + H << "public virtual ::Ice::Proxy<" << name << ", "; + if(bases.empty()) + { + H << "::IceProxy::Ice::Object"; + } + else if(bases.size() == 1) + { + H << "::IceProxy" << fixKwd(bases.front()->scoped()); + } + else + { + H << fixKwd("_" + p->name() + "Base"); + } + H << ">"; + H << sb; H.dec(); H << nl << "public:"; H.inc(); - if(_dllExport != "") - { - // - // To export the virtual table - // - C << nl << "#ifdef __SUNPRO_CC"; - C << nl << "class " << _dllExport - << "IceProxy" << scoped << ";"; - C << nl << "#endif"; - } - C << nl << _dllExport - << "::IceProxy::Ice::Object* ::IceProxy" << scope << "upCast(::IceProxy" << scoped - << "* p) { return p; }"; + << "::IceProxy::Ice::Object* ::IceProxy" << scope << "upCast(::IceProxy" << scoped << "* p) { return p; }"; C << sp; - C << nl << "void" << nl << "::IceProxy" << scope << "__read(::IceInternal::BasicStream* __is, " + C << nl << "void" << nl << "::IceProxy" << scope << "__read(::Ice::InputStream* __is, " << "::IceInternal::ProxyHandle< ::IceProxy" << scoped << ">& v)"; C << sb; C << nl << "::Ice::ObjectPrx proxy;"; @@ -1759,143 +1985,25 @@ Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); - // - // "Overwrite" various non-virtual functions in ::IceProxy::Ice::Object that return an ObjectPrx and - // are more usable when they return a <name>Prx - // - - // - // No identity! - // - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_context(const ::Ice::Context& __context) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_context(__context).get());"; - H << eb; - - // - // No facet! - // - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_adapterId(const ::std::string& __id) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_adapterId(__id).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_endpoints(const ::Ice::EndpointSeq& __endpoints) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_endpoints(__endpoints).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_locatorCacheTimeout(int __timeout) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_locatorCacheTimeout(__timeout).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_connectionCached(bool __cached) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_connectionCached(__cached).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_endpointSelection(::Ice::EndpointSelectionType __est) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_endpointSelection(__est).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_secure(bool __secure) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_secure(__secure).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_preferSecure(bool __preferSecure) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_preferSecure(__preferSecure).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_router(const ::Ice::RouterPrx& __router) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_router(__router).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_locator(const ::Ice::LocatorPrx& __locator) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_locator(__locator).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_collocationOptimized(bool __co) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_collocationOptimized(__co).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_invocationTimeout(int __timeout) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_invocationTimeout(__timeout).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_twoway() const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_twoway().get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_oneway() const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_oneway().get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_batchOneway() const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_batchOneway().get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_datagram() const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_datagram().get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_batchDatagram() const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_batchDatagram().get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_compress(bool __compress) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_compress(__compress).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_timeout(int __timeout) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_timeout(__timeout).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name << "> ice_connectionId(const ::std::string& __id) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_connectionId(__id).get());"; - H << eb; - - H << nl << nl << "::IceInternal::ProxyHandle<" << name - << "> ice_encodingVersion(const ::Ice::EncodingVersion& __v) const"; - H << sb; - H << nl << "return dynamic_cast<" << name << "*>(::IceProxy::Ice::Object::ice_encodingVersion(__v).get());"; - H << eb; - - H << nl << nl << "static const ::std::string& ice_staticId();"; + H << nl << nl << _dllMemberExport << "static const ::std::string& ice_staticId();"; H.dec(); - H << sp << nl << "private: "; + H << sp << nl << "protected: "; H.inc(); - H << nl << "virtual ::IceProxy::Ice::Object* __newInstance() const;"; + H << sp << nl << _dllMemberExport << "virtual ::IceProxy::Ice::Object* __newInstance() const;"; H << eb << ';'; C << sp; - C << nl << "const ::std::string&" << nl << "IceProxy" << scoped << "::ice_staticId()"; + C << nl << "::IceProxy::Ice::Object*"; + C << nl << "IceProxy" << scoped << "::__newInstance() const"; C << sb; - C << nl << "return "<< scoped << "::ice_staticId();"; + C << nl << "return new " << name << ";"; C << eb; - C << sp << nl << "::IceProxy::Ice::Object*"; - C << nl << "IceProxy" << scoped << "::__newInstance() const"; + C << sp; + C << nl << "const ::std::string&" << nl << "IceProxy" << scoped << "::ice_staticId()"; C << sb; - C << nl << "return new " << name << ";"; + C << nl << "return " << scoped << "::ice_staticId();"; C << eb; _useWstring = resetUseWstring(_useWstringHist); @@ -2018,7 +2126,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) // // Check if we need to generate a private ___end_ method. This is the case if the - // when using certain mapping features such as cpp:array or cpp:range:array. While + // when using certain mapping features such as cpp:array. While // the regular end_ method can't return pair<const TYPE*, const TYPE*> because the // pointers would be invalid once end_ returns, we still want to allow using this // alternate mapping with AMI response callbacks (to allow zero-copy for instance). @@ -2037,219 +2145,21 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) string thisPointer = fixKwd(scope.substr(0, scope.size() - 2)) + "*"; string deprecateSymbol = getDeprecateSymbol(p, cl); - H << sp << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << epar; - H << sb; - H << nl; + H << sp << nl << deprecateSymbol << _dllMemberExport << retS << ' ' << fixKwd(name) << spar << paramsDecl + << "const ::Ice::Context& __ctx = ::Ice::noExplicitContext" << epar; + H << sb << nl; if(ret) { H << "return "; } - H << fixKwd(name) << spar << args << "0" << epar << ';'; - H << eb; - H << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl << "const ::Ice::Context& __ctx" - << epar; - H << sb; - H << nl; - if(ret) - { - H << "return "; - } - H << fixKwd(name) << spar << args << "&__ctx" << epar << ';'; - H << eb; - - H.zeroIndent(); - H << nl << "#ifdef ICE_CPP11"; - H.restoreIndent(); - - string retEndArg = getEndArg(ret, p->getMetaData(), "__ret"); - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#if !defined(_MSC_VER) || _MSC_VER > 1700"; - H.restoreIndent(); - H << nl << "//"; - H << nl << "// COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with"; - H << nl << "// std::function due to lack of variadic templates."; - H << nl << "//"; - } - - H << nl << "::Ice::AsyncResultPtr"; - H << nl << "begin_" << name << spar << paramsDeclAMI - << "const ::IceInternal::Function<void " << spar; - if(!retInS.empty()) - { - H << retInS; - } - H << outDecls << epar << ">& __response, " - << "const ::IceInternal::Function<void (const ::Ice::Exception&)>& __exception = " - "::IceInternal::Function<void (const ::Ice::Exception&)>(), " - << "const ::IceInternal::Function<void (bool)>& __sent = ::IceInternal::Function<void (bool)>()" << epar; - - H << sb; - if(p->returnsData()) - { - H << nl << "return __begin_" << name << spar << argsAMI << "0, __response, __exception, __sent" << epar << ";"; - } - else - { - H << nl << "return begin_" << name << spar << argsAMI - << "0, new ::IceInternal::Cpp11FnOnewayCallbackNC(__response, __exception, __sent)" << epar << ";"; - - } - H << eb; - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#endif"; - H.restoreIndent(); - } - - H << nl << "::Ice::AsyncResultPtr"; - H << nl << "begin_" << name << spar << paramsDeclAMI - << "const ::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>& __completed" - << "const ::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>& __sent = " - "::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>()" << epar; - H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "0, ::Ice::newCallback(__completed, __sent), 0" << epar << ";"; - H << eb; - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#if !defined(_MSC_VER) || _MSC_VER > 1700"; - H.restoreIndent(); - H << nl << "//"; - H << nl << "// COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with"; - H << nl << "// std::function due to lack of variadic templates."; - H << nl << "//"; - } - - H << nl << "::Ice::AsyncResultPtr"; - H << nl << "begin_" << name << spar << paramsDeclAMI << "const ::Ice::Context& __ctx" - << "const ::IceInternal::Function<void " << spar; - if(!retInS.empty()) - { - H << retInS; - } - H << outDecls << epar << ">& __response, " - << "const ::IceInternal::Function<void (const ::Ice::Exception&)>& __exception = " - "::IceInternal::Function<void (const ::Ice::Exception&)>(), " - << "const ::IceInternal::Function<void (bool)>& __sent = ::IceInternal::Function<void (bool)>()" << epar; - - H << sb; - if(p->returnsData()) - { - H << nl << "return __begin_" << name << spar << argsAMI << "&__ctx, __response, __exception, __sent" << epar << ";"; - } - else - { - H << nl << "return begin_" << name << spar << argsAMI - << "&__ctx, new ::IceInternal::Cpp11FnOnewayCallbackNC(__response, __exception, __sent), 0" << epar << ";"; - } - H << eb; - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#endif"; - H.restoreIndent(); - } - - H << nl << "::Ice::AsyncResultPtr"; - H << nl << "begin_" << name << spar << paramsDeclAMI - << "const ::Ice::Context& __ctx" - << "const ::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>& __completed" - << "const ::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>& __sent = " - "::IceInternal::Function<void (const ::Ice::AsyncResultPtr&)>()" << epar; - H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "&__ctx, ::Ice::newCallback(__completed, __sent)" << epar << ";"; - H << eb; - - if(p->returnsData()) - { - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#if !defined(_MSC_VER) || _MSC_VER > 1700"; - H.restoreIndent(); - H << nl << "//"; - H << nl << "// COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with"; - H << nl << "// std::function due to lack of variadic templates."; - H << nl << "//"; - } - - H << nl; - H.dec(); - H << nl << "private:"; - H.inc(); - - - H << sp << nl << "::Ice::AsyncResultPtr __begin_" << name << spar << paramsDeclAMI - << "const ::Ice::Context* __ctx" << "const ::IceInternal::Function<void " << spar; - - - if(!retInS.empty()) - { - H << retInS; - } - H << outDecls; - - H << epar << ">& __response, " - << "const ::IceInternal::Function<void (const ::Ice::Exception&)>& __exception, " - << "const ::IceInternal::Function<void (bool)>& __sent" << epar << ";"; - - H << nl; - H.dec(); - H << nl << "public:"; - H.inc(); - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - H.zeroIndent(); - H << nl << "#endif"; - H.restoreIndent(); - } - } - - H.zeroIndent(); - H << nl << "#endif"; - H.restoreIndent(); - - H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << epar; - H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "0" << "::IceInternal::__dummyCallback" << "0" - << epar << ';'; + H << "end_" << name << spar << outParamNamesAMI << "__begin_" + name << spar << argsAMI; + H << "__ctx" << "::IceInternal::__dummyCallback" << "0" << "true" << epar << epar << ';'; H << eb; H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI - << "const ::Ice::Context& __ctx" << epar; + << "const ::Ice::Context& __ctx = ::Ice::noExplicitContext" << epar; H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "::IceInternal::__dummyCallback" << "0" + H << nl << "return __begin_" << name << spar << argsAMI << "__ctx" << "::IceInternal::__dummyCallback" << "0" << epar << ';'; H << eb; @@ -2257,7 +2167,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) << "const ::Ice::CallbackPtr& __del" << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar; H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "0" << "__del" << "__cookie" << epar << ';'; + H << nl << "return __begin_" << name << spar << argsAMI << "::Ice::noExplicitContext" << "__del" << "__cookie" << epar << ';'; H << eb; H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI @@ -2265,14 +2175,14 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) << "const ::Ice::CallbackPtr& __del" << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar; H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "__del" << "__cookie" << epar << ';'; + H << nl << "return __begin_" << name << spar << argsAMI << "__ctx" << "__del" << "__cookie" << epar << ';'; H << eb; H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << "const " + delNameScoped + "Ptr& __del" << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar; H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "0" << "__del" << "__cookie" << epar << ';'; + H << nl << "return __begin_" << name << spar << argsAMI << "::Ice::noExplicitContext" << "__del" << "__cookie" << epar << ';'; H << eb; H << sp << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI @@ -2280,14 +2190,14 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) << "const " + delNameScoped + "Ptr& __del" << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar; H << sb; - H << nl << "return begin_" << name << spar << argsAMI << "&__ctx" << "__del" << "__cookie" << epar << ';'; + H << nl << "return __begin_" << name << spar << argsAMI << "__ctx" << "__del" << "__cookie" << epar << ';'; H << eb; - H << sp << nl << retS << " end_" << name << spar << outParamsDeclAMI + H << sp << nl << _dllMemberExport << retS << " end_" << name << spar << outParamsDeclAMI << "const ::Ice::AsyncResultPtr&" << epar << ';'; if(generatePrivateEnd) { - H << sp << nl << " void ___end_" << name << spar << outParamsDeclEndAMI; + H << sp << nl << _dllMemberExport << "void ___end_" << name << spar << outParamsDeclEndAMI; H << "const ::Ice::AsyncResultPtr&" << epar << ';'; } @@ -2295,137 +2205,26 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) H.dec(); H << nl << "private:"; H.inc(); - H << sp << nl << retS << ' ' << fixKwd(name) << spar << params << "const ::Ice::Context*" << epar - << ';'; - H << nl << "::Ice::AsyncResultPtr begin_" << name << spar << paramsAMI << "const ::Ice::Context*" + H << sp << nl << _dllMemberExport << "::Ice::AsyncResultPtr __begin_" << name << spar + << paramsAMI << "const ::Ice::Context&" << "const ::IceInternal::CallbackBasePtr&" - << "const ::Ice::LocalObjectPtr& __cookie = 0" << epar << ';'; + << "const ::Ice::LocalObjectPtr& __cookie = 0" + << "bool sync = false" << epar << ';'; H << nl; H.dec(); H << nl << "public:"; H.inc(); - C << sp << nl << retS << nl << "IceProxy" << scoped << spar << paramsDecl << "const ::Ice::Context* __ctx" << epar; - C << sb; - if(p->returnsData()) - { - C << nl << "__checkTwowayOnly(" << flatName << ");"; - } - C << nl << "::IceInternal::Outgoing __og(this, " << flatName << ", " << operationModeToString(p->sendMode()) - << ", __ctx);"; - if(inParams.empty()) - { - C << nl << "__og.writeEmptyParams();"; - } - else - { - C << nl << "try"; - C << sb; - C << nl<< "::IceInternal::BasicStream* __os = __og.startWriteParams(" << opFormatTypeToString(p) << ");"; - writeMarshalCode(C, inParams, 0, true, TypeContextInParam); - if(p->sendsClasses(false)) - { - C << nl << "__os->writePendingObjects();"; - } - C << nl << "__og.endWriteParams();"; - C << eb; - C << nl << "catch(const ::Ice::LocalException& __ex)"; - C << sb; - C << nl << "__og.abort(__ex);"; - C << eb; - } - - if(!p->returnsData()) - { - C << nl << "__invoke(__og);"; // Use helpers for methods that don't return data. - } - else - { - C << nl << "if(!__og.invoke())"; - C << sb; - C << nl << "try"; - C << sb; - C << nl << "__og.throwUserException();"; - C << eb; - - // - // Generate a catch block for each legal user exception. This is necessary - // to prevent an "impossible" user exception to be thrown if client and - // and server use different exception specifications for an operation. For - // example: - // - // Client compiled with: - // exception A {}; - // exception B {}; - // interface I { - // void op() throws A; - // }; - // - // Server compiled with: - // exception A {}; - // exception B {}; - // interface I { - // void op() throws B; // Differs from client - // }; - // - // We need the catch blocks so, if the server throws B from op(), the - // client receives UnknownUserException instead of B. - // - ExceptionList throws = p->throws(); - throws.sort(); - throws.unique(); -#if defined(__SUNPRO_CC) - throws.sort(derivedToBaseCompare); -#else - throws.sort(Slice::DerivedToBaseCompare()); -#endif - for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i) - { - C << nl << "catch(const " << fixKwd((*i)->scoped()) << "&)"; - C << sb; - C << nl << "throw;"; - C << eb; - } - C << nl << "catch(const ::Ice::UserException& __ex)"; - C << sb; - // - // COMPILERFIX: Don't throw UnknownUserException directly. This is causing access - // violation errors with Visual C++ 64bits optimized builds. See bug #2962. - // - C << nl << "::Ice::UnknownUserException __uue(__FILE__, __LINE__, __ex.ice_name());"; - C << nl << "throw __uue;"; - C << eb; - C << eb; - - if(ret || !outParams.empty()) - { - writeAllocateCode(C, ParamDeclList(), p, true, _useWstring); - C << nl << "::IceInternal::BasicStream* __is = __og.startReadParams();"; - writeUnmarshalCode(C, outParams, p, true); - if(p->returnsClasses(false)) - { - C << nl << "__is->readPendingObjects();"; - } - C << nl << "__og.endReadParams();"; - } - - if(ret) - { - C << nl << "return __ret;"; - } - } - C << eb; - - C << sp << nl << "::Ice::AsyncResultPtr" << nl << "IceProxy" << scope << "begin_" << name << spar << paramsDeclAMI - << "const ::Ice::Context* __ctx" << "const ::IceInternal::CallbackBasePtr& __del" - << "const ::Ice::LocalObjectPtr& __cookie" << epar; + C << sp << nl << "::Ice::AsyncResultPtr" << nl << "IceProxy" << scope << "__begin_" << name << spar << paramsDeclAMI + << "const ::Ice::Context& __ctx" << "const ::IceInternal::CallbackBasePtr& __del" + << "const ::Ice::LocalObjectPtr& __cookie" << "bool sync" << epar; C << sb; if(p->returnsData()) { - C << nl << "__checkAsyncTwowayOnly(" << flatName << ");"; + C << nl << "__checkTwowayOnly(" << flatName << ", sync);"; } - C << nl << "::IceInternal::OutgoingAsyncPtr __result = new ::IceInternal::OutgoingAsync(this, "; - C << flatName << ", __del, __cookie);"; + C << nl << "::IceInternal::OutgoingAsyncPtr __result = new ::IceInternal::CallbackOutgoing(this, " << flatName + << ", __del, __cookie, sync);"; C << nl << "try"; C << sb; C << nl << "__result->prepare(" << flatName << ", " << operationModeToString(p->sendMode()) << ", __ctx);"; @@ -2435,15 +2234,15 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) } else { - C << nl << "::IceInternal::BasicStream* __os = __result->startWriteParams(" << opFormatTypeToString(p) <<");"; + C << nl << "::Ice::OutputStream* __os = __result->startWriteParams(" << opFormatTypeToString(p) <<");"; writeMarshalCode(C, inParams, 0, true, TypeContextInParam); if(p->sendsClasses(false)) { - C << nl << "__os->writePendingObjects();"; + C << nl << "__os->writePendingValues();"; } C << nl << "__result->endWriteParams();"; } - C << nl << "__result->invoke();"; + C << nl << "__result->invoke(" << flatName << ");"; C << eb; C << nl << "catch(const ::Ice::Exception& __ex)"; C << sb; @@ -2452,140 +2251,6 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) C << nl << "return __result;"; C << eb; - if(p->returnsData()) - { - C << nl << nl << "#ifdef ICE_CPP11"; - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - - C << nl << "#if !defined(_MSC_VER) || _MSC_VER > 1700"; - - C << nl << "//"; - C << nl << "// COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with"; - C << nl << "// std::function due to lack of variadic templates."; - C << nl << "//"; - } - - C << sp << nl << "::Ice::AsyncResultPtr" << nl - << "IceProxy" << scope << "__begin_" << name << spar << paramsDeclAMI - << "const ::Ice::Context* __ctx" << "const ::IceInternal::Function<void " << spar; - - if(!retInS.empty()) - { - C << retInS; - } - C << outDecls; - - C << epar << ">& __response, " - << "const ::IceInternal::Function<void (const ::Ice::Exception&)>& __exception, " - << "const ::IceInternal::Function<void (bool)>& __sent" << epar; - - C << sb; - C << nl << "class Cpp11CB : public ::IceInternal::Cpp11FnCallbackNC"; - C << sb; - C.dec(); - C << nl << "public:"; - C.inc(); - C << sp << nl << "Cpp11CB" << spar << "const ::std::function<void " << spar; - if(!retInS.empty()) - { - C << retInS; - } - C << outDecls; - C << epar << ">& responseFunc, " - << "const ::std::function<void (const ::Ice::Exception&)>& exceptionFunc, " - << "const ::std::function<void (bool)>& sentFunc" << epar << " :"; - C.inc(); - C << nl << "::IceInternal::Cpp11FnCallbackNC(exceptionFunc, sentFunc),"; - C << nl << "_response(responseFunc)"; - C.dec(); - C << sb; - C << nl << "CallbackBase::checkCallback(true, responseFunc || exceptionFunc != nullptr);"; - C << eb; - - // - // completed. - // - C << sp << nl << "virtual void completed(const ::Ice::AsyncResultPtr& __result) const"; - C << sb; - C << nl << clScope << clName << "Prx __proxy = " << clScope << clName - << "Prx::uncheckedCast(__result->getProxy());"; - writeAllocateCode(C, outParams, p, true, _useWstring | TypeContextInParam | TypeContextAMICallPrivateEnd); - C << nl << "try"; - C << sb; - C << nl; - if(!usePrivateEnd(p)) - { - if(ret) - { - C << retEndArg << " = "; - } - C << "__proxy->end_" << p->name() << spar << outEndArgs << "__result" << epar << ';'; - } - else - { - C << "__proxy->___end_" << p->name() << spar << outEndArgs; - if(ret) - { - C << retEndArg; - } - C << "__result" << epar << ';'; - } - writeEndCode(C, outParams, p, true); - C << eb; - C << nl << "catch(const ::Ice::Exception& ex)"; - C << sb; - C << nl << "Cpp11FnCallbackNC::exception(__result, ex);"; - C << nl << "return;"; - C << eb; - C << nl << "if(_response != nullptr)"; - C << sb; - C << nl << "_response" << spar; - if(ret) - { - C << "__ret"; - } - C << outParamNamesAMI; - C << epar << ';'; - C << eb; - C << eb; - - C.dec(); - C << nl << nl << "private:"; - C.inc(); - C << nl; - C << nl << "::std::function<void " << spar; - - if(!retInS.empty()) - { - C << retInS; - } - C << outDecls; - - C << epar << "> _response;"; - - C << eb << ';'; - - C << nl << "return begin_" << name << spar << argsAMI << "__ctx" - << "new Cpp11CB(__response, __exception, __sent)" << epar << ';'; - C << eb; - - // - // COMPILERFIX VC compilers up to VC110 don't support more than 10 parameters with std::function due to - // lack of variadic templates. - // - if(outDecls.size() > 10 || (outDecls.size() > 9 && !retInS.empty())) - { - C << nl << "#endif"; - } - C << nl << "#endif"; // ICE_CPP11 - } - C << sp << nl << retS << nl << "IceProxy" << scope << "end_" << name << spar << outParamsDeclAMI << "const ::Ice::AsyncResultPtr& __result" << epar; C << sb; @@ -2627,16 +2292,16 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) } C << nl << "catch(const ::Ice::UserException& __ex)"; C << sb; - C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name());"; + C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_id());"; C << eb; C << eb; if(ret || !outParams.empty()) { - C << nl << "::IceInternal::BasicStream* __is = __result->__startReadParams();"; + C << nl << "::Ice::InputStream* __is = __result->__startReadParams();"; writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextAMIEnd); if(p->returnsClasses(false)) { - C << nl << "__is->readPendingObjects();"; + C << nl << "__is->readPendingValues();"; } C << nl << "__result->__endReadParams();"; } @@ -2690,16 +2355,17 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) } C << nl << "catch(const ::Ice::UserException& __ex)"; C << sb; - C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name());"; + C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_id());"; C << eb; C << eb; + if(ret || !outParams.empty()) { - C << nl << "::IceInternal::BasicStream* __is = __result->__startReadParams();"; + C << nl << "::Ice::InputStream* __is = __result->__startReadParams();"; writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextAMIPrivateEnd); if(p->returnsClasses(false)) { - C << nl << "__is->readPendingObjects();"; + C << nl << "__is->readPendingValues();"; } C << nl << "__result->__endReadParams();"; } @@ -2750,6 +2416,7 @@ Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p) H << nl << _dllExport << "::Ice::Object* upCast(" << scoped << "*);"; H << nl << "typedef ::IceInternal::Handle< " << scoped << "> " << p->name() << "Ptr;"; H << nl << "typedef ::IceInternal::ProxyHandle< ::IceProxy" << scoped << "> " << p->name() << "Prx;"; + H << nl << "typedef " << p->name() << "Prx " << p->name() << "PrxPtr;"; H << nl << _dllExport << "void __patch(" << p->name() << "Ptr&, const ::Ice::ObjectPtr&);"; } else @@ -2770,8 +2437,8 @@ Slice::Gen::ObjectDeclVisitor::visitOperation(const OperationPtr& p) } } -Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport, bool stream) : - H(h), C(c), _dllExport(dllExport), _stream(stream), _doneStaticSymbol(false), _useWstring(false) +Slice::Gen::ObjectVisitor::ObjectVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport), _doneStaticSymbol(false), _useWstring(false) { } @@ -2826,11 +2493,11 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) { if(p->isLocal()) { - H << "virtual public ::Ice::LocalObject"; + H << "public virtual ::Ice::LocalObject"; } else { - H << "virtual public ::Ice::Object"; + H << "public virtual ::Ice::Object"; } } else @@ -2853,7 +2520,7 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) } bool hasBaseClass = !bases.empty() && !bases.front()->isInterface(); - bool override = p->canBeCyclic() && (!hasBaseClass || !bases.front()->canBeCyclic()); + bool override = !p->isLocal() && p->canBeCyclic() && (!hasBaseClass || !bases.front()->canBeCyclic()); bool hasGCObjectBaseClass = basePreserved || override || preserved; if(!basePreserved && (override || preserved)) { @@ -2879,6 +2546,12 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) H << nl << "typedef " << p->name() << "Ptr PointerType;"; } + H << sp << nl << "virtual ~" << name << "();"; + C << sp; + C << nl << scoped.substr(2) << "::~" << name << "()"; + C << sb; + C << eb; + vector<string> params; vector<string> allTypes; vector<string> allParamDecls; @@ -2912,124 +2585,7 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) H << sb << eb; } - /* - * Strong guarantee: commented-out code marked "Strong guarantee" generates - * a copy-assignment operator that provides the strong exception guarantee. - * For now, this is commented out, and we use the compiler-generated - * copy-assignment operator. However, that one does not provide the strong - * guarantee. - - H << ';'; - if(!p->isAbstract()) - { - H << nl << name << "& operator=(const " << name << "&)"; - if(allDataMembers.empty()) - { - H << " { return *this; }"; - } - H << ';'; - } - - // - // __swap() is static because classes may be abstract, so we - // can't use a non-static member function when we do an upcall - // from a non-abstract derived __swap to the __swap in an abstract base. - // - H << sp << nl << "static void __swap(" << name << "&, " << name << "&) throw()"; - if(allDataMembers.empty()) - { - H << " {}"; - } - H << ';'; - H << nl << "void swap(" << name << "& rhs) throw()"; - H << sb; - if(!allDataMembers.empty()) - { - H << nl << "__swap(*this, rhs);"; - } - H << eb; - - * Strong guarantee - */ - emitOneShotConstructor(p); - H << sp; - - /* - * Strong guarantee - - if(!allDataMembers.empty()) - { - C << sp << nl << "void"; - C << nl << scoped.substr(2) << "::__swap(" << name << "& __lhs, " << name << "& __rhs) throw()"; - C << sb; - - if(base) - { - emitUpcall(base, "::__swap(__lhs, __rhs);"); - } - - // - // We use a map to remember for which types we have already declared - // a temporary variable and reuse that variable if a class has - // more than one member of the same type. That way, we don't use more - // temporaries than necessary. (::std::swap() instantiates a new temporary - // each time it is used.) - // - map<string, int> tmpMap; - map<string, int>::iterator pos; - int tmpCount = 0; - - for(q = dataMembers.begin(); q != dataMembers.end(); ++q) - { - string memberName = fixKwd((*q)->name()); - TypePtr type = (*q)->type(); - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin && builtin->kind() != Builtin::KindString - || EnumPtr::dynamicCast(type) || ProxyPtr::dynamicCast(type) - || ClassDeclPtr::dynamicCast(type) || StructPtr::dynamicCast(type)) - { - // - // For built-in types (except string), enums, proxies, structs, and classes, - // do the swap via a temporary variable. - // - string typeName = typeToString(type); - pos = tmpMap.find(typeName); - if(pos == tmpMap.end()) - { - pos = tmpMap.insert(pos, make_pair(typeName, tmpCount)); - C << nl << typeName << " __tmp" << tmpCount << ';'; - tmpCount++; - } - C << nl << "__tmp" << pos->second << " = __rhs." << memberName << ';'; - C << nl << "__rhs." << memberName << " = __lhs." << memberName << ';'; - C << nl << "__lhs." << memberName << " = __tmp" << pos->second << ';'; - } - else - { - // - // For dictionaries, vectors, and maps, use the standard container's - // swap() (which is usually optimized). - // - C << nl << "__lhs." << memberName << ".swap(__rhs." << memberName << ");"; - } - } - C << eb; - - if(!p->isAbstract()) - { - C << sp << nl << scoped << "&"; - C << nl << scoped.substr(2) << "::operator=(const " << name << "& __rhs)"; - C << sb; - C << nl << name << " __tmp(__rhs);"; - C << nl << "__swap(*this, __tmp);"; - C << nl << "return *this;"; - C << eb; - } - } - - * Strong guarantee - */ } if(!p->isLocal()) @@ -3045,7 +2601,7 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) if(!p->isInterface()) { - H << nl << "virtual ::Ice::ObjectPtr ice_clone() const;"; + H << sp << nl << "virtual ::Ice::ObjectPtr ice_clone() const;"; if(hasGCObjectBaseClass) { @@ -3062,8 +2618,6 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) C << sb; if(!p->isAbstract()) { - - C << nl << "::Ice::Object* __p = new " << name << "(*this);"; C << nl << "return __p;"; } @@ -3101,16 +2655,11 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) H << sp; H << nl << "virtual bool ice_isA" - << "(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const;"; + << "(const ::std::string&, const ::Ice::Current& = ::Ice::noExplicitCurrent) const;"; H << nl << "virtual ::std::vector< ::std::string> ice_ids" - << "(const ::Ice::Current& = ::Ice::Current()) const;"; - H << nl << "virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const;"; - H << nl << "static const ::std::string& ice_staticId();"; - - if(!dataMembers.empty()) - { - H << sp; - } + << "(const ::Ice::Current& = ::Ice::noExplicitCurrent) const;"; + H << nl << "virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::noExplicitCurrent) const;"; + H << sp << nl << "static const ::std::string& ice_staticId();"; string flatName = p->flattenedScope() + p->name() + "_ids"; @@ -3149,7 +2698,7 @@ Slice::Gen::ObjectVisitor::visitClassDefStart(const ClassDefPtr& p) C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_id(const ::Ice::Current&) const"; C << sb; - C << nl << "return " << flatName << '[' << scopedPos << "];"; + C << nl << "return ice_staticId();"; C << eb; C << sp; @@ -3195,6 +2744,8 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) bool basePreserved = p->inheritsMetaData("preserve-slice"); bool preserved = p->hasMetaData("preserve-slice"); + bool inProtected = false; + if(!p->isLocal()) { OperationList allOps = p->allOperations(); @@ -3212,8 +2763,7 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) allOpNames.unique(); H << sp; - H << nl - << "virtual ::Ice::DispatchStatus __dispatch(::IceInternal::Incoming&, const ::Ice::Current&);"; + H << nl << "virtual bool __dispatch(::IceInternal::Incoming&, const ::Ice::Current&);"; string flatName = p->flattenedScope() + p->name() + "_all"; C << sp << nl << "namespace"; @@ -3232,8 +2782,8 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) C << eb << ';'; C << sp << nl << "}"; C << sp; - C << nl << "::Ice::DispatchStatus" << nl << scoped.substr(2) - << "::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current)"; + C << nl << "bool"; + C << nl << scoped.substr(2) << "::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current)"; C << sb; C << nl << "::std::pair< const ::std::string*, const ::std::string*> r = " @@ -3255,12 +2805,14 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) C << nl << "return ___" << *q << "(in, current);"; C << eb; } - C << eb; - C << sp; + C << nl << "default:"; + C << sb; C << nl << "assert(false);"; C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, current.id, " << "current.facet, current.operation);"; C << eb; + C << eb; + C << eb; // // Check if we need to generate ice_operationAttributes() @@ -3330,74 +2882,49 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) if(!p->isAbstract()) { - H << sp << nl << "static ::Ice::ObjectFactoryPtr ice_factory();"; + H << sp << nl << "static ::Ice::ValueFactoryPtr ice_factory();"; } if(preserved && !basePreserved) { H << sp; - H << nl << "virtual void __write(::IceInternal::BasicStream*) const;"; - H << nl << "virtual void __read(::IceInternal::BasicStream*);"; - - if(_stream) - { - H << nl << "virtual void __write(const ::Ice::OutputStreamPtr&) const;"; - H << nl << "virtual void __read(const ::Ice::InputStreamPtr&);"; - } - else - { - string baseName = base ? fixKwd(base->scoped()) : string("::Ice::Object"); - H << nl << "using " << baseName << "::__write;"; - H << nl << "using " << baseName << "::__read;"; - } + H << nl << "virtual void __write(::Ice::OutputStream*) const;"; + H << nl << "virtual void __read(::Ice::InputStream*);"; } H.dec(); H << sp << nl << "protected:"; + inProtected = true; H.inc(); - H << nl << "virtual void __writeImpl(::IceInternal::BasicStream*) const;"; - H << nl << "virtual void __readImpl(::IceInternal::BasicStream*);"; - - if(_stream) - { - H << nl << "virtual void __writeImpl(const ::Ice::OutputStreamPtr&) const;"; - H << nl << "virtual void __readImpl(const ::Ice::InputStreamPtr&);"; - } - else - { - string baseName = base ? fixKwd(base->scoped()) : string("::Ice::Object"); - H << nl << "using " << baseName << "::__writeImpl;"; - H << nl << "using " << baseName << "::__readImpl;"; - } + H << sp << nl << "virtual void __writeImpl(::Ice::OutputStream*) const;"; + H << nl << "virtual void __readImpl(::Ice::InputStream*);"; if(preserved && !basePreserved) { C << sp; - C << nl << "void" << nl << scoped.substr(2) - << "::__write(::IceInternal::BasicStream* __os) const"; + C << nl << "void" << nl << scoped.substr(2) << "::__write(::Ice::OutputStream* __os) const"; C << sb; - C << nl << "__os->startWriteObject(__slicedData);"; + C << nl << "__os->startValue(__slicedData);"; C << nl << "__writeImpl(__os);"; - C << nl << "__os->endWriteObject();"; + C << nl << "__os->endValue();"; C << eb; C << sp; - C << nl << "void" << nl << scoped.substr(2) << "::__read(::IceInternal::BasicStream* __is)"; + C << nl << "void" << nl << scoped.substr(2) << "::__read(::Ice::InputStream* __is)"; C << sb; - C << nl << "__is->startReadObject();"; + C << nl << "__is->startValue();"; C << nl << "__readImpl(__is);"; - C << nl << "__slicedData = __is->endReadObject(true);"; + C << nl << "__slicedData = __is->endValue(true);"; C << eb; } C << sp; - C << nl << "void" << nl << scoped.substr(2) - << "::__writeImpl(::IceInternal::BasicStream* __os) const"; + C << nl << "void" << nl << scoped.substr(2) << "::__writeImpl(::Ice::OutputStream* __os) const"; C << sb; - C << nl << "__os->startWriteSlice(ice_staticId(), " << p->compactId() << (!base ? ", true" : ", false") << ");"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), true); - C << nl << "__os->endWriteSlice();"; + C << nl << "__os->startSlice(ice_staticId(), " << p->compactId() << (!base ? ", true" : ", false") << ");"; + C << nl << "Ice::StreamWriter< ::" << scoped.substr(2) << ", ::Ice::OutputStream>::write(__os, *this);"; + C << nl << "__os->endSlice();"; if(base) { emitUpcall(base, "::__writeImpl(__os);"); @@ -3405,60 +2932,17 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) C << eb; C << sp; - C << nl << "void" << nl << scoped.substr(2) << "::__readImpl(::IceInternal::BasicStream* __is)"; + C << nl << "void" << nl << scoped.substr(2) << "::__readImpl(::Ice::InputStream* __is)"; C << sb; - C << nl << "__is->startReadSlice();"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), false); - C << nl << "__is->endReadSlice();"; + C << nl << "__is->startSlice();"; + C << nl << "Ice::StreamReader< ::" << scoped.substr(2) << ", ::Ice::InputStream>::read(__is, *this);"; + C << nl << "__is->endSlice();"; if(base) { emitUpcall(base, "::__readImpl(__is);"); } C << eb; - if(_stream) - { - if(preserved && !basePreserved) - { - C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(const ::Ice::OutputStreamPtr& __os) const"; - C << sb; - C << nl << "__os->startObject(__slicedData);"; - C << nl << "__writeImpl(__os);"; - C << nl << "__os->endObject();"; - C << eb; - - C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(const ::Ice::InputStreamPtr& __is)"; - C << sb; - C << nl << "__is->startObject();"; - C << nl << "__readImpl(__is);"; - C << nl << "__slicedData = __is->endObject(true);"; - C << eb; - } - - C << sp << nl << "void" << nl << scoped.substr(2) - << "::__writeImpl(const ::Ice::OutputStreamPtr& __os) const"; - C << sb; - C << nl << "__os->startSlice(ice_staticId(), " << p->compactId() << (!base ? ", true" : ", false") << ");"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), true); - C << nl << "__os->endSlice();"; - if(base) - { - emitUpcall(base, "::__writeImpl(__os);"); - } - C << eb; - - C << sp << nl << "void" << nl << scoped.substr(2) << "::__readImpl(const ::Ice::InputStreamPtr& __is)"; - C << sb; - C << nl << "__is->startSlice();"; - writeMarshalUnmarshalDataMembers(C, p->dataMembers(), p->orderedOptionalDataMembers(), false); - C << nl << "__is->endSlice();"; - if(base) - { - emitUpcall(base, "::__readImpl(__is);"); - } - C << eb; - } - if(!p->isAbstract() || p->compactId() >= 0) { C << sp << nl << "namespace"; @@ -3467,22 +2951,22 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) if(!p->isAbstract()) { string initName = p->flattenedScope() + p->name() + "_init"; - C << sp << nl << "const ::IceInternal::DefaultObjectFactoryInit< " << scoped << "> " + C << nl << "const ::IceInternal::DefaultValueFactoryInit< " << scoped << "> " << initName << "(\"" << p->scoped() << "\");"; } if(p->compactId() >= 0) { string initName = p->flattenedScope() + p->name() + "_compactIdInit"; - C << sp << nl << "const ::IceInternal::CompactIdInit " + C << nl << "const ::IceInternal::CompactIdInit " << initName << "(\"" << p->scoped() << "\", " << p->compactId() << ");"; } C << nl << "}"; if(!p->isAbstract()) { - C << sp << nl << "::Ice::ObjectFactoryPtr" << nl << scoped.substr(2) << "::ice_factory()"; + C << sp << nl << "::Ice::ValueFactoryPtr" << nl << scoped.substr(2) << "::ice_factory()"; C << sb; - C << nl << "return ::IceInternal::factoryTable->getObjectFactory(" << scoped << "::ice_staticId());"; + C << nl << "return ::IceInternal::factoryTable->getValueFactory(" << scoped << "::ice_staticId());"; C << eb; } } @@ -3491,9 +2975,10 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) // // Emit data members. Access visibility may be specified by metadata. // - bool inProtected = true; + bool generateFriend = false; DataMemberList dataMembers = p->dataMembers(); bool prot = p->hasMetaData("protected"); + bool needSp = true; for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) { if(prot || (*q)->hasMetaData("protected")) @@ -3501,48 +2986,47 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) if(!inProtected) { H.dec(); - H << sp << nl << "protected:"; + H << sp << nl << "protected:" << sp; H.inc(); inProtected = true; + needSp = false; } + generateFriend = true; } else { if(inProtected) { H.dec(); - H << sp << nl << "public:"; + H << sp << nl << "public:" << sp; H.inc(); inProtected = false; + needSp = false; } } + if(needSp) + { + H << sp; + needSp = false; + } + emitDataMember(*q); } - if(!p->isAbstract()) + if(!p->isLocal() && preserved && !basePreserved) { - // - // We add a protected destructor to force heap instantiation of the class. - // if(!inProtected) { H.dec(); - H << nl << "protected:"; + H << sp << nl << "protected:"; H.inc(); inProtected = true; } - H << sp << nl << "virtual ~" << fixKwd(p->name()) << "() {}"; - - if(!_doneStaticSymbol) - { - H.dec(); - H << sp << nl << "friend class " << p->name() << "__staticInit;"; - H.inc(); - } + H << sp << nl << "::Ice::SlicedDataPtr __slicedData;"; } - if(!p->isLocal() && preserved && !basePreserved) + if(generateFriend) { if(!inProtected) { @@ -3551,7 +3035,12 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) H.inc(); inProtected = true; } - H << sp << nl << "::Ice::SlicedDataPtr __slicedData;"; + + H << sp; + H << nl << "template<typename T, typename S>"; + H << nl << "friend struct Ice::StreamWriter;"; + H << nl << "template<typename T, typename S>"; + H << nl << "friend struct Ice::StreamReader;"; } H << eb << ';'; @@ -3559,40 +3048,11 @@ Slice::Gen::ObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) if(!p->isAbstract() && !p->isLocal() && !_doneStaticSymbol) { // - // We need an instance here to trigger initialization if the implementation is in a shared library. + // We need an instance here to trigger initialization if the implementation is in a static library. // But we do this only once per source file, because a single instance is sufficient to initialize - // all of the globals in a shared library. + // all of the globals in a compilation unit. // - // For a Slice class Foo, we instantiate a dummy class Foo__staticInit instead of using a static - // Foo instance directly because Foo has a protected destructor. - // - H.zeroIndent(); - H << nl << "#if !defined(_MSC_VER) || (_MSC_VER < 1900)"; - H.restoreIndent(); - H << nl << "//"; - H << nl << "// COMPILERFIX: Visual Studio 2015 update 1 fails to access"; - H << nl << "// the proected destructor from a friend class."; - H << nl << "//"; - - H << sp << nl << "class " << p->name() << "__staticInit"; - H << sb; - H.dec(); - H << nl << "public:"; - H.inc(); - H << sp << nl << scoped << " _init;"; - H << eb << ';'; - _doneStaticSymbol = true; - H << sp << nl << "static " << p->name() << "__staticInit _" << p->name() << "_init;"; - - H.zeroIndent(); - H << nl << "#else"; - H.restoreIndent(); - - H << nl << "static auto _" << p->name() << "_init = " << p->scoped() << "::ice_factory;"; - - H.zeroIndent(); - H << nl << "#endif"; - H.restoreIndent(); + H << nl << "static ::Ice::ValueFactoryPtr _" << p->name() << "_init = " << p->scoped() << "::ice_factory();"; } if(p->isLocal()) @@ -3669,7 +3129,7 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) string paramsAMD = "(const " + classScopedAMD + '_' + name + "Ptr&, "; string paramsDeclAMD = "(const " + classScopedAMD + '_' + name + "Ptr& __cb, "; - string argsAMD = "(__cb, "; + string argsAMD = "(new IceAsync" + classScopedAMD + '_' + name + "(__inS), "; ParamDeclList inParams; ParamDeclList outParams; @@ -3731,7 +3191,7 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) args += ", "; } - params += "const ::Ice::Current& = ::Ice::Current())"; + params += "const ::Ice::Current& = ::Ice::noExplicitCurrent)"; paramsDecl += "const ::Ice::Current& __current)"; args += "__current)"; } @@ -3742,11 +3202,11 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) args += ')'; } - paramsAMD += "const ::Ice::Current& = ::Ice::Current())"; + paramsAMD += "const ::Ice::Current& = ::Ice::noExplicitCurrent)"; paramsDeclAMD += "const ::Ice::Current& __current)"; argsAMD += "__current)"; - bool isConst = (p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const"); + string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : ""; bool amd = !cl->isLocal() && (cl->hasMetaData("amd") || p->hasMetaData("amd")); string deprecateSymbol = getDeprecateSymbol(p, cl); @@ -3754,69 +3214,46 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) H << sp; if(!amd) { - H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params - << (isConst ? " const" : "") << " = 0;"; + H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params << isConst << " = 0;"; } else { - H << nl << deprecateSymbol << "virtual void " << name << "_async" << paramsAMD - << (isConst ? " const" : "") << " = 0;"; + H << nl << deprecateSymbol << "virtual void " << name << "_async" << paramsAMD << isConst << " = 0;"; } if(!cl->isLocal()) { - H << nl << "::Ice::DispatchStatus ___" << name - << "(::IceInternal::Incoming&, const ::Ice::Current&)" << (isConst ? " const" : "") << ';'; + H << nl << "bool ___" << name << "(::IceInternal::Incoming&, const ::Ice::Current&)" << isConst << ';'; C << sp; - C << nl << "::Ice::DispatchStatus" << nl << scope.substr(2) << "___" << name - << "(::IceInternal::Incoming& __inS"; - C << ", const ::Ice::Current& __current)" << (isConst ? " const" : ""); + C << nl << "bool" << nl << scope.substr(2) << "___" << name << "(::IceInternal::Incoming& __inS" + << ", const ::Ice::Current& __current)" << isConst; C << sb; - if(!amd) - { - ExceptionList throws = p->throws(); - throws.sort(); - throws.unique(); + C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);"; - // - // Arrange exceptions into most-derived to least-derived order. If we don't - // do this, a base exception handler can appear before a derived exception - // handler, causing compiler warnings and resulting in the base exception - // being marshaled instead of the derived exception. - // - -#if defined(__SUNPRO_CC) - throws.sort(derivedToBaseCompare); -#else - throws.sort(Slice::DerivedToBaseCompare()); -#endif - - C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);"; - - if(!inParams.empty()) - { - C << nl << "::IceInternal::BasicStream* __is = __inS.startReadParams();"; - writeAllocateCode(C, inParams, 0, true, _useWstring | TypeContextInParam); - writeUnmarshalCode(C, inParams, 0, true, TypeContextInParam); - if(p->sendsClasses(false)) - { - C << nl << "__is->readPendingObjects();"; - } - C << nl << "__inS.endReadParams();"; - } - else + if(!inParams.empty()) + { + C << nl << "::Ice::InputStream* __is = __inS.startReadParams();"; + writeAllocateCode(C, inParams, 0, true, _useWstring | TypeContextInParam); + writeUnmarshalCode(C, inParams, 0, true, TypeContextInParam); + if(p->sendsClasses(false)) { - C << nl << "__inS.readEmptyParams();"; + C << nl << "__is->readPendingValues();"; } + C << nl << "__inS.endReadParams();"; + } + else + { + C << nl << "__inS.readEmptyParams();"; + } + if(p->format() != DefaultFormat) + { + C << nl << "__inS.setFormat(" << opFormatTypeToString(p) << ");"; + } + if(!amd) + { writeAllocateCode(C, outParams, 0, true, _useWstring); - if(!throws.empty()) - { - C << nl << "try"; - C << sb; - } - C << nl; if(ret) { C << retS << " __ret = "; @@ -3824,74 +3261,29 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) C << fixKwd(name) << args << ';'; if(ret || !outParams.empty()) { - C << nl << "::IceInternal::BasicStream* __os = __inS.__startWriteParams(" - << opFormatTypeToString(p) << ");"; + C << nl << "::Ice::OutputStream* __os = __inS.startWriteParams();"; writeMarshalCode(C, outParams, p, true); if(p->returnsClasses(false)) { - C << nl << "__os->writePendingObjects();"; + C << nl << "__os->writePendingValues();"; } - C << nl << "__inS.__endWriteParams(true);"; + C << nl << "__inS.endWriteParams();"; } else { - C << nl << "__inS.__writeEmptyParams();"; - } - C << nl << "return ::Ice::DispatchOK;"; - if(!throws.empty()) - { - C << eb; - ExceptionList::const_iterator r; - for(r = throws.begin(); r != throws.end(); ++r) - { - C << nl << "catch(const " << fixKwd((*r)->scoped()) << "& __ex)"; - C << sb; - C << nl << "__inS.__writeUserException(__ex, " << opFormatTypeToString(p) << ");"; - C << eb; - } - C << nl << "return ::Ice::DispatchUserException;"; + C << nl << "__inS.writeEmptyParams();"; } + C << nl << "return false;"; } else { - C << nl << "__checkMode(" << operationModeToString(p->mode()) << ", __current.mode);"; - - if(!inParams.empty()) - { - C << nl << "::IceInternal::BasicStream* __is = __inS.startReadParams();"; - writeAllocateCode(C, inParams, 0, true, _useWstring | TypeContextInParam); - writeUnmarshalCode(C, inParams, 0, true, TypeContextInParam); - if(p->sendsClasses(false)) - { - C << nl << "__is->readPendingObjects();"; - } - C << nl << "__inS.endReadParams();"; - } - else - { - C << nl << "__inS.readEmptyParams();"; - } - - C << nl << classScopedAMD << '_' << name << "Ptr __cb = new IceAsync" << classScopedAMD << '_' << name - << "(__inS);"; - C << nl << "try"; - C << sb; C << nl << name << "_async" << argsAMD << ';'; - C << eb; - C << nl << "catch(const ::std::exception& __ex)"; - C << sb; - C << nl << "__cb->ice_exception(__ex);"; - C << eb; - C << nl << "catch(...)"; - C << sb; - C << nl << "__cb->ice_exception();"; - C << eb; - C << nl << "return ::Ice::DispatchAsync;"; + C << nl << "return true;"; } C << eb; } - if(cl->isLocal() && (cl->hasMetaData("async") || p->hasMetaData("async"))) + if(cl->isLocal() && (cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway"))) { vector<string> paramsDeclAMI; vector<string> outParamsDeclAMI; @@ -3923,12 +3315,6 @@ Slice::Gen::ObjectVisitor::visitOperation(const OperationPtr& p) } } - H << nl << "// Only supported with C++ 11 support enabled"; - H << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI - << "const ::IceInternal::Function<void (const ::Ice::Exception&)>& exception" - << "const ::IceInternal::Function<void (bool)>& sent = ::IceInternal::Function<void (bool)>()" - << epar << " = 0;"; - H << sp << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI << epar << " = 0;"; H << sp << nl << "virtual ::Ice::AsyncResultPtr begin_" << name << spar << paramsDeclAMI @@ -3952,7 +3338,7 @@ void Slice::Gen::ObjectVisitor::emitDataMember(const DataMemberPtr& p) { string name = fixKwd(p->name()); - H << sp << nl << typeToString(p->type(), p->optional(), p->getMetaData(), _useWstring) << ' ' << name << ';'; + H << nl << typeToString(p->type(), p->optional(), p->getMetaData(), _useWstring) << ' ' << name << ';'; } void @@ -4028,7 +3414,9 @@ void Slice::Gen::ObjectVisitor::emitGCVisitCode(const TypePtr& p, const string& prefix, const string& name, int level) { BuiltinPtr builtin = BuiltinPtr::dynamicCast(p); - if((builtin && BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(p)) + if((builtin && + (BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindObject || BuiltinPtr::dynamicCast(p)->kind() == Builtin::KindValue)) || + ClassDeclPtr::dynamicCast(p)) { C << nl << "if(" << prefix << name << ')'; C << sb; @@ -4215,7 +3603,7 @@ Slice::Gen::AsyncCallbackVisitor::AsyncCallbackVisitor(Output& h, Output&, const bool Slice::Gen::AsyncCallbackVisitor::visitModuleStart(const ModulePtr& p) { - if(!p->hasNonLocalClassDefs() && !p->hasContentsWithMetaData("async")) + if(!p->hasNonLocalClassDefs() && !p->hasContentsWithMetaData("async-oneway")) { return false; } @@ -4253,7 +3641,7 @@ Slice::Gen::AsyncCallbackVisitor::visitOperation(const OperationPtr& p) { ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container()); - if(cl->isLocal() && !(cl->hasMetaData("async") || p->hasMetaData("async"))) + if(cl->isLocal() && !(cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway"))) { return; } @@ -4262,7 +3650,7 @@ Slice::Gen::AsyncCallbackVisitor::visitOperation(const OperationPtr& p) // Write the callback base class and callback smart pointer. // string delName = "Callback_" + cl->name() + "_" + p->name(); - H << sp << nl << "class " << delName << "_Base : virtual public ::IceInternal::CallbackBase { };"; + H << sp << nl << "class " << delName << "_Base : public virtual ::IceInternal::CallbackBase { };"; H << nl << "typedef ::IceUtil::Handle< " << delName << "_Base> " << delName << "Ptr;"; } @@ -4300,7 +3688,6 @@ void Slice::Gen::AsyncCallbackTemplateVisitor::visitModuleEnd(const ModulePtr&) { _useWstring = resetUseWstring(_useWstringHist); - H << sp << nl << '}'; } @@ -4489,7 +3876,9 @@ Slice::Gen::AsyncCallbackTemplateVisitor::generateOperation(const OperationPtr& H << epar << ';'; H << eb; H << eb; + H.dec(); H << sp << nl << "private:"; + H.inc(); H << sp << nl << "Response _response;"; } H << eb << ';'; @@ -4574,57 +3963,8 @@ Slice::Gen::ImplVisitor::ImplVisitor(Output& h, Output& c, const string& dllExpo { } -void -Slice::Gen::ImplVisitor::writeDecl(Output& out, const string& name, const TypePtr& type, const StringList& metaData) -{ - out << nl << typeToString(type, metaData, _useWstring) << ' ' << name; - - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin) - { - switch(builtin->kind()) - { - case Builtin::KindBool: - { - out << " = false"; - break; - } - case Builtin::KindByte: - case Builtin::KindShort: - case Builtin::KindInt: - case Builtin::KindLong: - { - out << " = 0"; - break; - } - case Builtin::KindFloat: - case Builtin::KindDouble: - { - out << " = 0.0"; - break; - } - case Builtin::KindString: - case Builtin::KindObject: - case Builtin::KindObjectProxy: - case Builtin::KindLocalObject: - { - break; - } - } - } - - EnumPtr en = EnumPtr::dynamicCast(type); - if(en) - { - EnumeratorList enumerators = en->getEnumerators(); - out << " = " << fixKwd(en->scope()) << fixKwd(enumerators.front()->name()); - } - - out << ';'; -} - -void -Slice::Gen::ImplVisitor::writeReturn(Output& out, const TypePtr& type, const StringList& metaData) +string +Slice::Gen::ImplVisitor::defaultValue(const TypePtr& type, const StringList& metaData) const { BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) @@ -4633,84 +3973,76 @@ Slice::Gen::ImplVisitor::writeReturn(Output& out, const TypePtr& type, const Str { case Builtin::KindBool: { - out << nl << "return false;"; - break; + return "false"; } case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: { - out << nl << "return 0;"; - break; + return "0"; } case Builtin::KindFloat: case Builtin::KindDouble: { - out << nl << "return 0.0;"; - break; + return "0.0"; } case Builtin::KindString: { - out << nl << "return ::std::string();"; - break; + return "::std::string()"; } + case Builtin::KindValue: case Builtin::KindObject: case Builtin::KindObjectProxy: case Builtin::KindLocalObject: { - out << nl << "return 0;"; - break; + return "0"; } } } else { ProxyPtr prx = ProxyPtr::dynamicCast(type); - if(prx) + + if(ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type)) { - out << nl << "return 0;"; + return "0"; } - else + + StructPtr st = StructPtr::dynamicCast(type); + if(st) { - ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); - if(cl) - { - out << nl << "return 0;"; - } - else - { - StructPtr st = StructPtr::dynamicCast(type); - if(st) - { - out << nl << "return " << fixKwd(st->scoped()) << "();"; - } - else - { - EnumPtr en = EnumPtr::dynamicCast(type); - if(en) - { - EnumeratorList enumerators = en->getEnumerators(); - out << nl << "return " << fixKwd(en->scope()) << fixKwd(enumerators.front()->name()) << ';'; - } - else - { - SequencePtr seq = SequencePtr::dynamicCast(type); - if(seq) - { - out << nl << "return " << typeToString(seq, metaData, _useWstring) << "();"; - } - else - { - DictionaryPtr dict = DictionaryPtr::dynamicCast(type); - assert(dict); - out << nl << "return " << fixKwd(dict->scoped()) << "();"; - } - } - } - } + return fixKwd(st->scoped()) + "()"; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + EnumeratorList enumerators = en->getEnumerators(); + return fixKwd(en->scope() + enumerators.front()->name()); + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return typeToString(seq, metaData, _useWstring | TypeContextCpp11) + "()"; + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(dict) + { + return fixKwd(dict->scoped()) + "()"; } } + + assert(false); + return "???"; +} + +void +Slice::Gen::ImplVisitor::writeReturn(Output& out, const TypePtr& type, const StringList& metaData) +{ + out << nl << "return " << defaultValue(type, metaData) << ";"; } bool @@ -4720,32 +4052,8 @@ Slice::Gen::ImplVisitor::visitModuleStart(const ModulePtr& p) { return false; } - _useWstring = setUseWstring(p, _useWstringHist, _useWstring); - - set<string> includes; - ClassList classes = p->classes(); - for(ClassList::const_iterator q = classes.begin(); q != classes.end(); ++q) - { - ClassList bases = (*q)->bases(); - for(ClassList::const_iterator r = bases.begin(); r != bases.end(); ++r) - { - if((*r)->isAbstract()) - { - includes.insert((*r)->name()); - } - } - } - - for(set<string>::const_iterator it = includes.begin(); it != includes.end(); ++it) - { - H << nl << "#include <" << *it << "I.h>"; - } - - string name = fixKwd(p->name()); - - H << sp << nl << "namespace " << name << nl << '{'; - + H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{'; return true; } @@ -4771,38 +4079,25 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) string name = p->name(); string scope = fixKwd(p->scope()); string cls = scope.substr(2) + name + "I"; - string classScopedAMD = scope + "AMD_" + name; ClassList bases = p->bases(); H << sp; - H << nl << "class " << name << "I : "; - H.useCurrentPosAsIndent(); - H << "virtual public " << fixKwd(name); - for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) - { - H << ',' << nl << "virtual public " << fixKwd((*q)->scope()); - if((*q)->isAbstract()) - { - H << (*q)->name() << "I"; - } - else - { - H << fixKwd((*q)->name()); - } - } - H.restoreIndent(); + H << nl << "class " << name << "I : public virtual " << fixKwd(name); H << sb; H.dec(); H << nl << "public:"; H.inc(); - OperationList ops = p->operations(); + OperationList ops = p->allOperations(); for(OperationList::const_iterator r = ops.begin(); r != ops.end(); ++r) { OperationPtr op = (*r); string opName = op->name(); + string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : ""; + + string classScopedAMD = scope + "AMD_" + ClassDefPtr::dynamicCast(op->container())->name(); TypePtr ret = op->returnType(); string retS = returnTypeToString(ret, op->returnIsOptional(), op->getMetaData(), _useWstring); @@ -4824,10 +4119,7 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) } H << ',' << nl << "const Ice::Current&"; H.restoreIndent(); - - bool isConst = (op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const"); - - H << ")" << (isConst ? " const" : "") << ';'; + H << ")" << isConst << ';'; C << sp << nl << "void" << nl << scope << name << "I::" << opName << "_async("; C.useCurrentPosAsIndent(); @@ -4842,7 +4134,7 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) } C << ',' << nl << "const Ice::Current& current"; C.restoreIndent(); - C << ")" << (isConst ? " const" : ""); + C << ")" << isConst; C << sb; string result = "r"; @@ -4854,22 +4146,11 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) break; } } - if(ret) - { - writeDecl(C, result, ret, op->getMetaData()); - } - for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) - { - if((*q)->isOutParam()) - { - writeDecl(C, fixKwd((*q)->name()), (*q)->type(), (*q)->getMetaData()); - } - } C << nl << opName << "CB->ice_response("; if(ret) { - C << result; + C << defaultValue(ret, op->getMetaData()); } for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) { @@ -4879,7 +4160,7 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) { C << ", "; } - C << fixKwd((*q)->name()); + C << defaultValue((*q)->type(), op->getMetaData()); } } C << ");"; @@ -4897,17 +4178,14 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) { H << ',' << nl; } - StringList metaData = (*q)->getMetaData(); - string typeString; if((*q)->isOutParam()) { - typeString = outputTypeToString((*q)->type(), (*q)->optional(), metaData, _useWstring); + H << outputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), _useWstring); } else { - typeString = inputTypeToString((*q)->type(), (*q)->optional(), metaData, _useWstring); + H << inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), _useWstring); } - H << typeString; } if(!p->isLocal()) { @@ -4919,9 +4197,9 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) } H.restoreIndent(); - bool isConst = (op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const"); + string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : ""; - H << ")" << (isConst ? " const" : "") << ';'; + H << ")" << isConst << ';'; C << sp << nl << retS << nl; C << scope.substr(2) << name << "I::" << fixKwd(opName) << '('; @@ -4932,17 +4210,16 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) { C << ',' << nl; } - StringList metaData = (*q)->getMetaData(); - string typeString; if((*q)->isOutParam()) { - typeString = outputTypeToString((*q)->type(), (*q)->optional(), metaData, _useWstring); + C << outputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), _useWstring) << " " + << fixKwd((*q)->name()); } else { - typeString = inputTypeToString((*q)->type(), (*q)->optional(), metaData, _useWstring); + C << inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), _useWstring) << " /*" + << fixKwd((*q)->name()) << "*/"; } - C << typeString << ' ' << fixKwd((*q)->name()); } if(!p->isLocal()) { @@ -4954,7 +4231,7 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) } C.restoreIndent(); C << ')'; - C << (isConst ? " const" : ""); + C << isConst; C << sb; if(ret) @@ -4973,8 +4250,8 @@ Slice::Gen::ImplVisitor::visitClassDefStart(const ClassDefPtr& p) return true; } -Slice::Gen::AsyncVisitor::AsyncVisitor(Output& h, Output&, const string& dllExport) : - H(h), _dllExport(dllExport), _useWstring(false) +Slice::Gen::AsyncVisitor::AsyncVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport), _useWstring(false) { } @@ -5084,17 +4361,27 @@ Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p) } } - paramsInvoke.push_back("const ::Ice::Context*"); - paramsDeclInvoke.push_back("const ::Ice::Context* __ctx"); + paramsInvoke.push_back("const ::Ice::Context&"); + paramsDeclInvoke.push_back("const ::Ice::Context& __ctx"); if(cl->hasMetaData("amd") || p->hasMetaData("amd")) { - H << sp << nl << "class " << _dllExport << classNameAMD << '_' << name - << " : virtual public ::Ice::AMDCallback"; + string cbName = classNameAMD + '_' + name; + + H << sp << nl << "class " << _dllExport << cbName + << " : public virtual ::Ice::AMDCallback"; H << sb; H.dec(); H << nl << "public:"; H.inc(); + + // Out of line dtor to avoid weak vtable + H << sp << nl << "virtual ~" << cbName << "();"; + C << sp; + C << nl << classScope.substr(2) << cbName << "::~" << cbName << "()"; + C << sb; + C << eb; + H << sp; H << nl << "virtual void ice_response" << spar << paramsAMD << epar << " = 0;"; H << eb << ';'; @@ -5186,22 +4473,6 @@ Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p) string paramsDecl; string args; - ExceptionList throws = p->throws(); - throws.sort(); - throws.unique(); - - // - // Arrange exceptions into most-derived to least-derived order. If we don't - // do this, a base exception handler can appear before a derived exception - // handler, causing compiler warnings and resulting in the base exception - // being marshaled instead of the derived exception. - // -#if defined(__SUNPRO_CC) - throws.sort(derivedToBaseCompare); -#else - throws.sort(Slice::DerivedToBaseCompare()); -#endif - TypePtr ret = p->returnType(); string retS = inputTypeToString(ret, p->returnIsOptional(), p->getMetaData(), _useWstring); @@ -5253,12 +4524,6 @@ Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p) H << sp; H << nl << "virtual void ice_response(" << params << ");"; - if(!throws.empty()) - { - H << nl << "// COMPILERFIX: The using directive avoid compiler warnings with -Woverloaded-virtual"; - H << nl << "using ::IceInternal::IncomingAsync::ice_exception;"; - H << nl << "virtual void ice_exception(const ::std::exception&);"; - } H << eb << ';'; C << sp << nl << "IceAsync" << classScopedAMD << '_' << name << "::" << classNameAMD << '_' << name @@ -5269,65 +4534,25 @@ Slice::Gen::AsyncImplVisitor::visitOperation(const OperationPtr& p) C << sb; C << eb; - C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name << "::ice_response(" - << paramsDecl << ')'; - C << sb; - C << nl << "if(__validateResponse(true))"; + C << sp << nl << "void"; + C << nl << "IceAsync" << classScopedAMD << '_' << name << "::ice_response(" << paramsDecl << ')'; C << sb; if(ret || !outParams.empty()) { - C << nl << "try"; - C << sb; - C << nl << "::IceInternal::BasicStream* __os = __startWriteParams(" << opFormatTypeToString(p) << ");"; + C << nl << "::Ice::OutputStream* __os = startWriteParams();"; writeMarshalCode(C, outParams, p, false, TypeContextInParam); if(p->returnsClasses(false)) { - C << nl << "__os->writePendingObjects();"; + C << nl << "__os->writePendingValues();"; } - C << nl << "__endWriteParams(true);"; - C << eb; - C << nl << "catch(const ::Ice::Exception& __ex)"; - C << sb; - C << nl << "__exception(__ex);"; - C << nl << "return;"; - C << eb; + C << nl << "endWriteParams();"; } else { - C << nl << "__writeEmptyParams();"; + C << nl << "writeEmptyParams();"; } - C << nl << "__response();"; - C << eb; + C << nl << "completed();"; C << eb; - - if(!throws.empty()) - { - C << sp << nl << "void" << nl << "IceAsync" << classScopedAMD << '_' << name - << "::ice_exception(const ::std::exception& ex)"; - C << sb; - for(ExceptionList::const_iterator r = throws.begin(); r != throws.end(); ++r) - { - C << nl; - if(r != throws.begin()) - { - C << "else "; - } - C << "if(const " << fixKwd((*r)->scoped()) << "* __ex = dynamic_cast<const " << fixKwd((*r)->scoped()) - << "*>(&ex))"; - C << sb; - C << nl <<"if(__validateResponse(false))"; - C << sb; - C << nl << "__writeUserException(*__ex, " << opFormatTypeToString(p) << ");"; - C << nl << "__response();"; - C << eb; - C << eb; - } - C << nl << "else"; - C << sb; - C << nl << "::IceInternal::IncomingAsync::ice_exception(ex);"; - C << eb; - C << eb; - } } Slice::Gen::StreamVisitor::StreamVisitor(Output& h, Output& c, const string& dllExport) : @@ -5342,6 +4567,7 @@ Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m) { if(!m->hasNonLocalContained(Contained::ContainedTypeStruct) && !m->hasNonLocalContained(Contained::ContainedTypeEnum) && + !m->hasNonLocalContained(Contained::ContainedTypeClass) && !m->hasNonLocalContained(Contained::ContainedTypeException)) { return false; @@ -5353,7 +4579,7 @@ Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m) // Only emit this for the top-level module. // H << sp; - H << nl << "namespace Ice" << nl << '{'; + H << nl << "namespace Ice" << nl << '{' << sp; C << sp; C << nl << "namespace Ice" << nl << '{'; @@ -5376,6 +4602,16 @@ Slice::Gen::StreamVisitor::visitModuleEnd(const ModulePtr& m) } bool +Slice::Gen::StreamVisitor::visitClassDefStart(const ClassDefPtr& c) +{ + if(!c->isLocal()) + { + writeStreamHelpers(H, c, c->dataMembers(), c->hasBaseDataMembers(), true, false); + } + return false; +} + +bool Slice::Gen::StreamVisitor::visitExceptionStart(const ExceptionPtr& p) { if(!p->isLocal()) @@ -5386,6 +4622,8 @@ Slice::Gen::StreamVisitor::visitExceptionStart(const ExceptionPtr& p) H << sb; H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryUserException;"; H << eb << ";" << nl; + + writeStreamHelpers(H, p, p->dataMembers(), p->hasBaseDataMembers(), true, false); } return false; } @@ -5424,53 +4662,7 @@ Slice::Gen::StreamVisitor::visitStructStart(const StructPtr& p) } H << eb << ";" << nl; - DataMemberList dataMembers = p->dataMembers(); - - string holder = classMetaData ? "v->" : "v."; - - H << nl << "template<class S>"; - H << nl << "struct StreamWriter< " << fullStructName << ", S>"; - H << sb; - H << nl << "static void write(S* __os, const " << fullStructName << "& v)"; - H << sb; - for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) - { - writeMarshalUnmarshalDataMemberInHolder(H, holder, *q, true); - } - H << eb; - H << eb << ";" << nl; - - H << nl << "template<class S>"; - H << nl << "struct StreamReader< " << fullStructName << ", S>"; - H << sb; - H << nl << "static void read(S* __is, " << fullStructName << "& v)"; - H << sb; - for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) - { - writeMarshalUnmarshalDataMemberInHolder(H, holder, *q, false); - } - H << eb; - H << eb << ";" << nl; - - if(!_dllExport.empty()) - { - // - // We tell "importers" that the implementation exports these instantiations - // - H << nl << "#if defined(ICE_HAS_DECLSPEC_IMPORT_EXPORT) && !defined("; - H << _dllExport.substr(0, _dllExport.size() - 1) + "_EXPORTS) && !defined(ICE_STATIC_LIBS)"; - H << nl << "template struct " << _dllExport << "StreamWriter< " << fullStructName << ", ::IceInternal::BasicStream>;"; - H << nl << "template struct " << _dllExport << "StreamReader< " << fullStructName << ", ::IceInternal::BasicStream>;"; - H << nl << "#endif" << nl; - - // - // The instantations: - // - C << nl << "#if defined(ICE_HAS_DECLSPEC_IMPORT_EXPORT) && !defined(ICE_STATIC_LIBS)"; - C << nl << "template struct " << _dllExport << "StreamWriter< " << fullStructName << ", ::IceInternal::BasicStream>;"; - C << nl << "template struct " << _dllExport << "StreamReader< " << fullStructName << ", ::IceInternal::BasicStream>;"; - C << nl << "#endif"; - } + writeStreamHelpers(H, p, p->dataMembers(), false, true, false); } return false; } @@ -5507,6 +4699,7 @@ Slice::Gen::MetaDataVisitor::visitUnitStart(const UnitPtr& p) // // Validate global metadata in the top-level file and all included files. + // Note that these metadata can only be cpp:, never cpp98: or cpp11: // StringList files = p->allFiles(); @@ -5698,13 +4891,36 @@ void Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const StringList& metaData, const string& file, const string& line, bool /*inParam*/) { - static const string prefix = "cpp:"; + static const string cppPrefix = "cpp:"; + static const string cpp11Prefix = "cpp11:"; + static const string cpp98Prefix = "cpp98:"; + for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) { string s = *p; + if(_history.count(s) == 0) { - if(s.find(prefix) == 0) + string prefix; + bool cpp98 = false; + bool cpp11 = false; + + if(s.find(cppPrefix) == 0) + { + prefix = cppPrefix; + } + else if(s.find(cpp98Prefix) == 0) + { + prefix = cpp98Prefix; + cpp98 = true; + } + else if(s.find(cpp11Prefix) == 0) + { + prefix = cpp11Prefix; + cpp11 = true; + } + + if(!prefix.empty()) { string ss = s.substr(prefix.size()); if(ss == "type:wstring" || ss == "type:string") @@ -5737,18 +4953,46 @@ Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const Strin { continue; } - if(StructPtr::dynamicCast(cont) && (ss == "class" || ss == "comparable")) + if(!cpp11 && StructPtr::dynamicCast(cont) && (ss == "class" || ss == "comparable")) { continue; } - if(ClassDefPtr::dynamicCast(cont) && ss == "virtual") + { - continue; + ClassDefPtr cl = ClassDefPtr::dynamicCast(cont); + if(cl && ((!cpp11 && ss == "virtual") || + (cl->isLocal() && ss.find("type:") == 0) || + (!cpp11 && cl->isLocal() && ss == "comparable"))) + { + continue; + } } if(ExceptionPtr::dynamicCast(cont) && ss == "ice_print") { continue; } + if(!cpp98 && EnumPtr::dynamicCast(cont) && ss == "unscoped") + { + continue; + } + + { + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(cont); + if(cl && cl->isLocal() && ss.find("type:") == 0) + { + continue; + } + } + emitWarning(file, line, "ignoring invalid metadata `" + s + "'"); + } + + if(s.find("delegate") == 0) + { + ClassDefPtr cl = ClassDefPtr::dynamicCast(cont); + if(cl && cl->isDelegate()) + { + continue; + } emitWarning(file, line, "ignoring invalid metadata `" + s + "'"); } _history.insert(s); @@ -5756,6 +5000,249 @@ Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const Strin } } + +void +Slice::Gen::normalizeMetaData(const UnitPtr& u, bool cpp11) +{ + NormalizeMetaDataVisitor visitor(cpp11); + u->visit(&visitor, false); +} + +Slice::Gen::NormalizeMetaDataVisitor::NormalizeMetaDataVisitor(bool cpp11) : + _cpp11(cpp11) +{ +} + +bool +Slice::Gen::NormalizeMetaDataVisitor::visitUnitStart(const UnitPtr& p) +{ + return true; +} + +bool +Slice::Gen::NormalizeMetaDataVisitor::visitModuleStart(const ModulePtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); + return true; +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitModuleEnd(const ModulePtr&) +{ +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + +bool +Slice::Gen::NormalizeMetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); + return true; +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) +{ +} + +bool +Slice::Gen::NormalizeMetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); + return true; +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) +{ +} + +bool +Slice::Gen::NormalizeMetaDataVisitor::visitStructStart(const StructPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); + return true; +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitStructEnd(const StructPtr&) +{ +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitOperation(const OperationPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); + + ParamDeclList params = p->parameters(); + for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) + { + (*q)->setMetaData(normalize((*q)->getMetaData())); + } +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitDataMember(const DataMemberPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitSequence(const SequencePtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitDictionary(const DictionaryPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitEnum(const EnumPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + +void +Slice::Gen::NormalizeMetaDataVisitor::visitConst(const ConstPtr& p) +{ + p->setMetaData(normalize(p->getMetaData())); +} + + +StringList +Slice::Gen::NormalizeMetaDataVisitor::normalize(const StringList& metaData) +{ + // + // if _cpp11: transform "cpp:" into "cpp-all:" and "cpp" + // + transform "cpp11:" into "cpp:" in front + // + // if !_cpp11: remove "cpp:", transform "cpp-all:" into "cpp" + // + transform "cpp98:" into "cpp:" in front + + // + // Note: global metadata like header-ext exists only in cpp: + // form and are not processed at all + // + + StringList result; + + static const string cppPrefixTable[] = + { + "array", + "class", + "comparable", + "const", + "ice_print", + "range", + "type:", + "unscoped", + "view-type:", + "virtual", + "" + }; + + static const string cppPrefix = "cpp:"; + static const string cppAllPrefix = "cpp-all:"; + + // + // First look for the higher priority cpp98/cpp11, that go to the + // front of result + // + + static const string cpp11Prefix = "cpp11:"; + static const string cpp98Prefix = "cpp98:"; + + const string altCppPrefix = _cpp11 ? cpp11Prefix : cpp98Prefix; + + for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) + { + string s = *p; + + unsigned int i = 0; + bool found = false; + while(!found) + { + string m = cppPrefixTable[i++]; + if(m.empty()) + { + break; + } + if(s.find(altCppPrefix + m) == 0) + { + found = true; + } + } + + if(found) + { + s.replace(0, altCppPrefix.length(), cppPrefix); + result.push_back(s); + } + } + + // + // Then look for the lower-priority "cpp:" / "cpp-all:", pushed back later + // + + const string prefix = _cpp11 ? cppPrefix : cppAllPrefix; + + for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) + { + string s = *p; + + unsigned int i = 0; + bool foundPrefix = false; + bool foundOld = false; + while(!foundPrefix && !foundOld) + { + string m = cppPrefixTable[i++]; + if(m.empty()) + { + break; // while + } + if(s.find(prefix + m) == 0) + { + foundPrefix = true; + } + else if(!_cpp11 && s.find(cppPrefix + m) == 0) + { + // + // We want to filter-out "cpp:" when !_cpp11 + // + foundOld = true; + } + } + + if(foundPrefix) + { + if(_cpp11) + { + result.push_back(s); + s.replace(0, prefix.length(), cppAllPrefix); + result.push_back(s); + } + else + { + s.replace(0, prefix.length(), cppPrefix); + result.push_back(s); + } + } + else if(_cpp11 || !foundOld) + { + result.push_back(s); + } + } + + return result; +} + int Slice::Gen::setUseWstring(ContainedPtr p, list<int>& hist, int use) { @@ -5794,3 +5281,2863 @@ Slice::Gen::getHeaderExt(const string& file, const UnitPtr& unit) } return ext; } + +// C++11 visitors +Slice::Gen::Cpp11DeclVisitor::Cpp11DeclVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport) +{ +} + +bool +Slice::Gen::Cpp11DeclVisitor::visitUnitStart(const UnitPtr& p) +{ + if(!p->hasClassDecls() && !p->hasNonLocalExceptions()) + { + return false; + } + C << sp << nl << "namespace" << nl << "{"; + return true; +} + +void +Slice::Gen::Cpp11DeclVisitor::visitUnitEnd(const UnitPtr& p) +{ + C << sp << nl << "}"; +} + +bool +Slice::Gen::Cpp11DeclVisitor::visitModuleStart(const ModulePtr& p) +{ + if(p->hasClassDecls()) + { + H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{' << sp; + } + return true; +} + +void +Slice::Gen::Cpp11DeclVisitor::visitModuleEnd(const ModulePtr& p) +{ + if(p->hasClassDecls()) + { + H << sp << nl << '}'; + } +} + +void +Slice::Gen::Cpp11DeclVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + ClassDefPtr def = p->definition(); + if(def && def->isDelegate()) + { + return; + } + + H << nl << "class " << fixKwd(p->name()) << ';'; + if(p->isInterface() || (def && !def->allOperations().empty())) + { + H << nl << "class " << p->name() << "Prx;"; + } +} + +bool +Slice::Gen::Cpp11DeclVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + if(!p->isInterface()) + { + C << sp; + + C << nl << "const ::IceInternal::DefaultValueFactoryInit<" << fixKwd(p->scoped()) << "> "; + C << p->flattenedScope() + p->name() + "_init" << "(\"" << p->scoped() << "\");"; + + if(p->compactId() >= 0) + { + string n = p->flattenedScope() + p->name() + "_compactIdInit "; + C << "const ::IceInternal::CompactIdInit " << n << "(\"" << p->scoped() << "\", " << p->compactId() << ");"; + } + } + + OperationList allOps = p->allOperations(); + if(p->isInterface() || !allOps.empty()) + { + C << sp; + + ClassList allBases = p->allBases(); + StringList ids; + transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); + StringList other; + other.push_back(p->scoped()); + other.push_back("::Ice::Object"); + other.sort(); + ids.merge(other); + ids.unique(); + + C << nl << "const ::std::string " << p->flattenedScope() << p->name() << "_ids[" << ids.size() << "] ="; + C << sb; + for(StringList::const_iterator r = ids.begin(); r != ids.end();) + { + C << nl << '"' << *r << '"'; + if(++r != ids.end()) + { + C << ','; + } + } + C << eb << ';'; + + StringList allOpNames; + transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); + allOpNames.push_back("ice_id"); + allOpNames.push_back("ice_ids"); + allOpNames.push_back("ice_isA"); + allOpNames.push_back("ice_ping"); + allOpNames.sort(); + allOpNames.unique(); + + C << nl << "const ::std::string " << p->flattenedScope() << p->name() << "_ops[] ="; + C << sb; + for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end();) + { + C << nl << '"' << *q << '"'; + if(++q != allOpNames.end()) + { + C << ','; + } + } + C << eb << ';'; + } + + return true; +} + +bool +Slice::Gen::Cpp11DeclVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + C << sp; + C << nl << "const ::IceInternal::DefaultUserExceptionFactoryInit<" << fixKwd(p->scoped()) << "> "; + C << p->flattenedScope() + p->name() + "_init" << "(\"" << p->scoped() << "\");"; + return false; +} + +void +Slice::Gen::Cpp11DeclVisitor::visitOperation(const OperationPtr& p) +{ + ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container()); + if(cl && !cl->isLocal()) + { + string flatName = p->flattenedScope() + p->name() + "_name"; + C << nl << "const ::std::string " << flatName << " = \"" << p->name() << "\";"; + } +} + +Slice::Gen::Cpp11TypesVisitor::Cpp11TypesVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport), _dllClassExport(toDllClassExport(dllExport)), + _dllMemberExport(toDllMemberExport(dllExport)), _doneStaticSymbol(false), _useWstring(false) +{ +} + +bool +Slice::Gen::Cpp11TypesVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasOtherConstructedOrExceptions()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitModuleEnd(const ModulePtr& p) +{ + if(p->hasStructs()) + { + H << sp << nl << "using Ice::operator<;"; + H << nl << "using Ice::operator<=;"; + H << nl << "using Ice::operator>;"; + H << nl << "using Ice::operator>=;"; + H << nl << "using Ice::operator==;"; + H << nl << "using Ice::operator!=;"; + } + H << sp << nl << '}'; + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11TypesVisitor::visitClassDefStart(const ClassDefPtr&) +{ + return false; +} + +bool +Slice::Gen::Cpp11TypesVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string name = fixKwd(p->name()); + string scoped = fixKwd(p->scoped()); + ExceptionPtr base = p->base(); + DataMemberList dataMembers = p->dataMembers(); + DataMemberList allDataMembers = p->allDataMembers(); + DataMemberList baseDataMembers; + + vector<string> params; + vector<string> allTypes; + vector<string> allParamDecls; + vector<string> baseParams; + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + params.push_back(fixKwd((*q)->name())); + } + + for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q) + { + string typeName = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), + _useWstring | TypeContextCpp11); + allTypes.push_back(typeName); + allParamDecls.push_back(typeName + " " + fixKwd("__ice_" + (*q)->name())); + } + + if(base) + { + baseDataMembers = base->allDataMembers(); + for(DataMemberList::const_iterator q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q) + { + baseParams.push_back(fixKwd("__ice_" + (*q)->name())); + } + } + + string helperClass = p->isLocal() ? "Ice::LocalExceptionHelper" : "Ice::UserExceptionHelper"; + string baseClass = base ? fixKwd(base->scoped()) : (p->isLocal() ? "::Ice::LocalException" : "::Ice::UserException"); + string templateParameters = name + ", " + baseClass; + + H << sp << nl; + H << "class " << _dllClassExport << name << " : public ::" << helperClass << "<" << templateParameters << ">"; + H << sb; + + H.dec(); + H << nl << "public:"; + H.inc(); + + // Out of line dtor to avoid weak vtable + H << sp << nl << _dllMemberExport << "virtual ~" << name << "();"; + C << sp; + C << nl << scoped.substr(2) << "::~" << name << "()"; + C << sb; + C << eb; + + if(p->isLocal()) + { + H << sp << nl << name << "(const char* __ice_file, int __ice_line) : "; + H << "::Ice::LocalExceptionHelper" << "<" << templateParameters << ">"; + H << "(__ice_file, __ice_line)"; + H << sb; + H << eb; + } + else + { + H << sp << nl << name << "() = default;"; + } + + if(!allDataMembers.empty()) + { + H << sp << nl << name << "("; + if(p->isLocal()) + { + H << "const char* __ice_file, int __ice_line"; + if(!allParamDecls.empty()) + { + H << ", "; + } + } + + for(vector<string>::const_iterator q = allParamDecls.begin(); q != allParamDecls.end(); ++q) + { + if(q != allParamDecls.begin()) + { + H << ", "; + } + H << (*q); + } + H << ") :"; + H.inc(); + if(base && (p->isLocal() || !baseDataMembers.empty())) + { + H << nl << "::" << helperClass << "<" << templateParameters << ">" << "("; + if(p->isLocal()) + { + H << "__ice_file, __ice_line"; + if(!baseDataMembers.empty()) + { + H << ", "; + } + } + + for(DataMemberList::const_iterator q = baseDataMembers.begin(); q != baseDataMembers.end(); ++q) + { + if(q != baseDataMembers.begin()) + { + H << ", "; + } + if(isMovable((*q)->type())) + { + H << "::std::move(" << fixKwd("__ice_" + (*q)->name()) << ")"; + } + else + { + H << fixKwd("__ice_" + (*q)->name()); + } + } + + H << ")"; + if(!dataMembers.empty()) + { + H << ","; + } + } + else if(p->isLocal()) + { + H << " ::Ice::LocalExceptionHelper" << "<" << templateParameters << ">"; + H << "(__ice_file, __ice_line)"; + if(!dataMembers.empty()) + { + H << ","; + } + } + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(q != dataMembers.begin()) + { + H << ", "; + } + if(isMovable((*q)->type())) + { + H << nl << fixKwd((*q)->name()) << "(::std::move(" << fixKwd("__ice_" + (*q)->name()) << "))"; + } + else + { + H << nl << fixKwd((*q)->name()) << "(" << fixKwd("__ice_" + (*q)->name()) << ")"; + } + } + + H.dec(); + H << sb; + H << eb; + } + + writeIceTuple(H, p->allDataMembers(), _useWstring); + + H << sp; + H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();"; + + + C << sp << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()"; + C << sb; + // + // Use local static so that ice_staticId() is usable during static construction. + // + C << nl << "static const ::std::string typeId = \"" << p->scoped() << "\";"; + C << nl << "return typeId;"; + C << eb; + + StringList metaData = p->getMetaData(); + if(find(metaData.begin(), metaData.end(), "cpp:ice_print") != metaData.end()) + { + H << nl << _dllMemberExport << "virtual void ice_print(::std::ostream&) const override;"; + } + + if(!p->isLocal() && p->usesClasses(false)) + { + if(!base || (base && !base->usesClasses(false))) + { + H << sp << nl << _dllMemberExport << "virtual bool __usesClasses() const override;"; + + C << sp << nl << "bool"; + C << nl << scoped.substr(2) << "::__usesClasses() const"; + C << sb; + C << nl << "return true;"; + C << eb; + } + } + + if(!dataMembers.empty()) + { + H << sp; + } + return true; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) +{ + string name = fixKwd(p->name()); + string scope = fixKwd(p->scope()); + string scoped = fixKwd(p->scoped()); + string factoryName; + + if(!p->isLocal()) + { + ExceptionPtr base = p->base(); + bool basePreserved = p->inheritsMetaData("preserve-slice"); + bool preserved = p->hasMetaData("preserve-slice"); + + if(preserved && !basePreserved) + { + H << sp << nl << _dllMemberExport << "virtual void __write(::Ice::OutputStream*) const override;"; + H << nl << _dllMemberExport << "virtual void __read(::Ice::InputStream*) override;"; + + H << sp << nl << "::std::shared_ptr<::Ice::SlicedData> __slicedData;"; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__write(::Ice::OutputStream* __os) const"; + C << sb; + C << nl << "__os->startException(__slicedData);"; + C << nl << "__writeImpl(__os);"; + C << nl << "__os->endException();"; + C << eb; + + C << sp << nl << "void" << nl << scoped.substr(2) << "::__read(::Ice::InputStream* __is)"; + C << sb; + C << nl << "__is->startException();"; + C << nl << "__readImpl(__is);"; + C << nl << "__slicedData = __is->endException(true);"; + C << eb; + } + } + H << eb << ';'; + + if(!p->isLocal()) + { + // + // We need an instance here to trigger initialization if the implementation is in a shared libarry. + // But we do this only once per source file, because a single instance is sufficient to initialize + // all of the globals in a shared library. + // + if(!_doneStaticSymbol) + { + _doneStaticSymbol = true; + H << sp << nl << "static " << name << " __" << p->name() << "_init;"; + } + } + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11TypesVisitor::visitStructStart(const StructPtr& p) +{ + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + H << sp << nl << "struct " << fixKwd(p->name()); + H << sb; + + return true; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitStructEnd(const StructPtr& p) +{ + writeIceTuple(H, p->dataMembers(), _useWstring); + H << eb << ';'; + _useWstring = resetUseWstring(_useWstringHist); +} + +void +Slice::Gen::Cpp11TypesVisitor::visitDataMember(const DataMemberPtr& p) +{ + string name = fixKwd(p->name()); + H << nl << typeToString(p->type(), p->optional(), p->getMetaData(), _useWstring | TypeContextCpp11) + << ' ' << name; + + string defaultValue = p->defaultValue(); + if(!defaultValue.empty()) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(p->optional() && builtin->kind() == Builtin::KindString) + { + // + // = "<string literal>" doesn't work for optional<std::string> + // + H << '{'; + writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring, p->getMetaData(), true); + H << '}'; + } + else + { + H << " = "; + writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring, p->getMetaData(), true); + } + } + + H << ';'; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitSequence(const SequencePtr& p) +{ + string name = fixKwd(p->name()); + TypePtr type = p->type(); + int typeCtx = p->isLocal() ? (_useWstring | TypeContextLocal) : _useWstring; + string s = typeToString(type, p->typeMetaData(), typeCtx | TypeContextCpp11); + StringList metaData = p->getMetaData(); + + string seqType = findMetaData(metaData, _useWstring); + H << sp; + + if(!seqType.empty()) + { + H << nl << "using " << name << " = " << seqType << ';'; + } + else + { + H << nl << "using " << name << " = ::std::vector<" << s << ">;"; + } +} + +void +Slice::Gen::Cpp11TypesVisitor::visitDictionary(const DictionaryPtr& p) +{ + string name = fixKwd(p->name()); + string dictType = findMetaData(p->getMetaData()); + int typeCtx = p->isLocal() ? (_useWstring | TypeContextLocal) : _useWstring; + if(dictType.empty()) + { + // + // A default std::map dictionary + // + TypePtr keyType = p->keyType(); + TypePtr valueType = p->valueType(); + string ks = typeToString(keyType, p->keyMetaData(), typeCtx | TypeContextCpp11); + string vs = typeToString(valueType, p->valueMetaData(), typeCtx | TypeContextCpp11); + + H << sp << nl << "using " << name << " = ::std::map<" << ks << ", " << vs << ">;"; + } + else + { + // + // A custom dictionary + // + H << sp << nl << "using " << name << " = " << dictType << ';'; + } +} + +Slice::Gen::Cpp11ProxyVisitor::Cpp11ProxyVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllClassExport(toDllClassExport(dllExport)), _dllMemberExport(toDllMemberExport(dllExport)), + _useWstring(false) +{ +} + +bool +Slice::Gen::Cpp11ProxyVisitor::visitUnitStart(const UnitPtr& p) +{ + return true; +} + +void +Slice::Gen::Cpp11ProxyVisitor::visitUnitEnd(const UnitPtr&) +{ +} + +bool +Slice::Gen::Cpp11ProxyVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasNonLocalClassDefs()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + H << sp << nl << "namespace " << fixKwd(p->name()) << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11ProxyVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp << nl << '}'; + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal() || (!p->isInterface() && p->allOperations().empty())) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string name = fixKwd(p->name()); + string scope = fixKwd(p->scope()); + string scoped = fixKwd(p->scoped()); + ClassList bases = p->bases(); + + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + H << sp << nl << "class " << _dllClassExport << p->name() << "Prx : public virtual ::Ice::Proxy<" + << fixKwd(p->name() + "Prx") << ", "; + if(bases.empty() || (base && base->allOperations().empty())) + { + H << "::Ice::ObjectPrx"; + } + else + { + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + H << fixKwd((*q)->scoped() + "Prx"); + if(++q != bases.end()) + { + H << ", "; + } + } + } + H << ">"; + + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + return true; +} + +void +Slice::Gen::Cpp11ProxyVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string prx = fixKwd(p->name() + "Prx"); + + H << sp; + H << nl << _dllMemberExport << "static const ::std::string& ice_staticId();"; + + H.dec(); + H << sp << nl << "protected: "; + H.inc(); + H << sp << nl << prx << "() = default;"; + H << nl << "friend ::std::shared_ptr<" << prx << "> IceInternal::createProxy<" << prx << ">();"; + H << sp; + H << nl << _dllMemberExport << "virtual ::std::shared_ptr<::Ice::ObjectPrx> __newInstance() const override;"; + H << eb << ';'; + + string suffix = p->isInterface() ? "" : "Disp"; + string scoped = fixKwd(p->scoped() + "Prx"); + + C << sp; + C << nl << "::std::shared_ptr<::Ice::ObjectPrx>"; + C << nl << scoped.substr(2) << "::__newInstance() const"; + C << sb; + C << nl << "return ::IceInternal::createProxy<" << prx << ">();"; + C << eb; + C << sp; + C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()"; + C << sb; + C << nl << "return "<< fixKwd(p->scope() + p->name() + suffix).substr(2) << "::ice_staticId();"; + C << eb; + + _useWstring = resetUseWstring(_useWstringHist); +} + +void +Slice::Gen::Cpp11ProxyVisitor::visitOperation(const OperationPtr& p) +{ + string name = p->name(); + string flatName = p->flattenedScope() + p->name() + "_name"; + + TypePtr ret = p->returnType(); + + bool retIsOpt = p->returnIsOptional(); + string retS = returnTypeToString(ret, retIsOpt, p->getMetaData(), _useWstring | TypeContextCpp11); + + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + + vector<string> params; + vector<string> paramsDecl; + + vector<string> inParamsS; + vector<string> inParamsDecl; + + vector<string> futureOutParams; + vector<string> lambdaOutParams; + + ParamDeclList paramList = p->parameters(); + ParamDeclList inParams; + ParamDeclList outParams; + + string returnValueS = "returnValue"; + bool outParamsHasOpt = false; + + if(ret) + { + futureOutParams.push_back(typeToString(ret, retIsOpt, p->getMetaData(), _useWstring | TypeContextCpp11)); + + lambdaOutParams.push_back( + typeToString(ret, retIsOpt, p->getMetaData(), _useWstring | TypeContextInParam | TypeContextCpp11)); + + outParamsHasOpt |= p->returnIsOptional(); + } + + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string paramName = fixKwd(paramPrefix + (*q)->name()); + StringList metaData = (*q)->getMetaData(); + + if((*q)->isOutParam()) + { + futureOutParams.push_back(typeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextCpp11)); + lambdaOutParams.push_back(typeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextInParam | TypeContextCpp11)); + + string outputTypeString = outputTypeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextCpp11); + + params.push_back(outputTypeString); + paramsDecl.push_back(outputTypeString + ' ' + paramName); + + outParamsHasOpt |= (*q)->optional(); + outParams.push_back(*q); + + if((*q)->name() == "returnValue") + { + returnValueS = "_returnValue"; + } + } + else + { + string typeString = inputTypeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextCpp11); + + params.push_back(typeString); + paramsDecl.push_back(typeString + ' ' + paramName); + + inParamsS.push_back(typeString); + inParamsDecl.push_back(typeString + ' ' + paramName); + inParams.push_back(*q); + } + } + + string scoped = fixKwd(cl->scope() + cl->name() + "Prx" + "::").substr(2); + + string futureT; + if(futureOutParams.empty()) + { + futureT = "void"; + } + else if(futureOutParams.size() == 1) + { + futureT = futureOutParams[0]; + } + else + { + string resultScope = fixKwd(cl->scope() + cl->name()); + futureT = resultStructName(name, resultScope); + } + + string deprecateSymbol = getDeprecateSymbol(p, cl); + + // + // Synchronous operation + // + H << sp << nl << deprecateSymbol << retS << ' ' << fixKwd(name) << spar << paramsDecl; + H << "const ::Ice::Context& __ctx = Ice::noExplicitContext" << epar; + H << sb; + H << nl; + if(futureOutParams.size() == 1) + { + if(ret) + { + H << "return "; + } + else + { + H << paramPrefix << (*outParams.begin())->name() << " = "; + } + } + else if(futureOutParams.size() > 1) + { + H << "auto __result = "; + } + + H << "makePromiseOutgoing<" << futureT << ">"; + + H << spar << "true, this" << string("&" + scoped + "__" + name); + for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q) + { + H << fixKwd(paramPrefix + (*q)->name()); + } + H << "__ctx" << epar << ".get();"; + if(futureOutParams.size() > 1) + { + for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) + { + H << nl << paramPrefix << (*q)->name() << " = "; + H << condMove(isMovable((*q)->type()), "__result." + fixKwd((*q)->name())) + ";"; + } + if(ret) + { + H << nl << "return " + condMove(isMovable(ret), "__result." + returnValueS) + ";"; + } + } + H << eb; + + // + // Promise based asynchronous operation + // + H << sp; + H << nl << "template<template<typename> class P = ::std::promise>"; + H << nl << deprecateSymbol << "auto " << name << "Async" << spar << inParamsDecl; + H << "const ::Ice::Context& __ctx = Ice::noExplicitContext" << epar; + H.inc(); + H << nl << "-> decltype(::std::declval<P<" << futureT << ">>().get_future())"; + H.dec(); + H << sb; + + H << nl << "return makePromiseOutgoing<" << futureT << ", P>" << spar; + + H << "false, this" << string("&" + scoped + "__" + name); + for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q) + { + H << fixKwd(paramPrefix + (*q)->name()); + } + H << "__ctx" << epar << ";"; + H << eb; + + + // + // Lambda based asynchronous operation + // + bool lambdaCustomOut = (lambdaOutParams != futureOutParams); + + H << sp; + H << nl; + if(lambdaCustomOut) + { + H << _dllMemberExport; + } + H << "::std::function<void()>"; + H << nl << name << "Async("; + H.useCurrentPosAsIndent(); + if(!inParamsDecl.empty()) + { + if(lambdaCustomOut) + { + for(vector<string>::const_iterator q = inParamsS.begin(); q != inParamsS.end(); ++q) + { + H << *q << ", "; + } + } + else + { + for(vector<string>::const_iterator q = inParamsDecl.begin(); q != inParamsDecl.end(); ++q) + { + H << *q << ", "; + } + } + H << nl; + } + + H << "::std::function<void" << spar << lambdaOutParams << epar << ">" + + condString(!lambdaCustomOut, " __response") + ","; + H << nl << "::std::function<void(::std::exception_ptr)>" + + condString(!lambdaCustomOut, " __ex") + " = nullptr,"; + H << nl << "::std::function<void(bool)>" + + condString(!lambdaCustomOut," __sent") + " = nullptr,"; + H << nl << "const ::Ice::Context&" + + condString(!lambdaCustomOut, "__ctx") + " = Ice::noExplicitContext)" + condString(lambdaCustomOut, ";"); + + H.restoreIndent(); + if(lambdaCustomOut) + { + // + // "Custom" implementation in .cpp file + // + + C << sp; + C << nl << "::std::function<void()>"; + C << nl << scoped << name << "Async("; + C.useCurrentPosAsIndent(); + if(!inParamsDecl.empty()) + { + for(vector<string>::const_iterator q = inParamsDecl.begin(); q != inParamsDecl.end(); ++q) + { + C << *q << ", "; + } + C << nl; + } + C << "::std::function<void " << spar << lambdaOutParams << epar << "> __response,"; + C << nl << "::std::function<void(::std::exception_ptr)> __ex,"; + C << nl << "::std::function<void(bool)> __sent,"; + C << nl << "const ::Ice::Context& __ctx)"; + C.restoreIndent(); + C << sb; + if(p->returnsData()) + { + C << nl << "__checkTwowayOnly(" << flatName << ");"; + } + + C << nl << "::std::function<void(::Ice::InputStream*)> __read;"; + C << nl << "if(__response)"; + C << sb; + C << nl << "__read = [__response](::Ice::InputStream* __is)"; + C << sb; + C << nl << "__is->startEncapsulation();"; + writeAllocateCode(C, outParams, p, true, _useWstring | TypeContextInParam | TypeContextCpp11); + writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextInParam | TypeContextCpp11); + + if(p->returnsClasses(false)) + { + C << nl << "__is->readPendingValues();"; + } + C << nl << "__is->endEncapsulation();"; + C << nl << "try" << sb; + C << nl << "__response" << spar; + if(ret) + { + C << "__ret"; + } + for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) + { + C << fixKwd(paramPrefix + (*q)->name()); + } + C << epar << ";"; + C << eb; + C << nl << "catch(...)"; + C << sb; + C << nl << "throw ::std::current_exception();"; + C << eb; + C << eb << ";"; + C << eb; + C << nl << "auto __outAsync = ::std::make_shared<::IceInternal::CustomLambdaOutgoing>("; + C << "shared_from_this(), __read, __ex, __sent);"; + C << sp; + + C << nl << "__outAsync->invoke(" << flatName << ", "; + C << operationModeToString(p->sendMode(), true) << ", " << opFormatTypeToString(p) << ", __ctx, "; + C.inc(); + C << nl; + + writeInParamsLambda(C, p, inParams); + C << "," << nl; + throwUserExceptionLambda(C, p->throws()); + + C.dec(); + C << ");"; + C << nl << "return [__outAsync]() { __outAsync->cancel(); };"; + C << eb; + } + else + { + // + // Simple implementation directly in header file + // + + H << sb; + if(futureOutParams.size() > 1) + { + H << nl << "auto __responseCb = [__response](" << futureT << "&& result)"; + H << sb; + H << nl << "__response" << spar; + + if(ret) + { + H << condMove(isMovable(ret), string("result.") + returnValueS); + } + for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) + { + H << condMove(isMovable((*q)->type()), "result." + fixKwd((*q)->name())); + } + H << epar << ";" << eb << ";"; + } + + H << nl << "return makeLambdaOutgoing<" << futureT << ">" << spar; + + H << (futureOutParams.size() > 1 ? "__responseCb" : "__response") << "__ex" << "__sent" << "this"; + H << string("&" + scoped + "__" + name); + for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q) + { + H << fixKwd(paramPrefix + (*q)->name()); + } + H << "__ctx" << epar << ";"; + H << eb; + } + + // + // Private implementation + // + + H << sp; + H << nl << _dllMemberExport << "void __" << name << spar; + H << "const ::std::shared_ptr<::IceInternal::OutgoingAsyncT<" + futureT + ">>&"; + H << inParamsS; + H << "const ::Ice::Context&"; + H << epar << ";"; + + C << sp; + C << nl << "void" << nl << scoped << "__" << name << spar; + C << "const ::std::shared_ptr<::IceInternal::OutgoingAsyncT<" + futureT + ">>& __outAsync"; + C << inParamsDecl << "const ::Ice::Context& __ctx"; + C << epar; + C << sb; + if(p->returnsData()) + { + C << nl << "__checkTwowayOnly(" << flatName << ");"; + } + C << nl << "__outAsync->invoke(" << flatName << ", "; + C << operationModeToString(p->sendMode(), true) << ", " << opFormatTypeToString(p) << ", __ctx, "; + C.inc(); + C << nl; + + writeInParamsLambda(C, p, inParams); + C << "," << nl; + throwUserExceptionLambda(C, p->throws()); + + if(futureOutParams.size() > 1) + { + // + // Generate a read method if there are more than one ret/out parameter. If there's + // only one, we rely on the default read method from LambdaOutgoing + // except if the unique ret/out is optional or is an array/range. + // + C << "," << nl << "[](::Ice::InputStream* __is)"; + C << sb; + C << nl << futureT << " v;"; + writeUnmarshalCode(C, outParams, p, false, _useWstring | TypeContextCpp11, returnValueS, "v"); + + if(p->returnsClasses(false)) + { + C << nl << "__is->readPendingValues();"; + } + C << nl << "return v;"; + C << eb; + } + else if(outParamsHasOpt || p->returnsClasses(false)) + { + // + // If there's only one optional ret/out parameter, we still need to generate + // a read method, we can't rely on the default read method which wouldn't + // known which tag to use. + // + C << "," << nl << "[](::Ice::InputStream* __is)"; + C << sb; + + writeAllocateCode(C, outParams, p, true, _useWstring | TypeContextCpp11); + writeUnmarshalCode(C, outParams, p, true, _useWstring | TypeContextCpp11); + + if(p->returnsClasses(false)) + { + C << nl << "__is->readPendingValues();"; + } + + if(ret) + { + C << nl << "return __ret;"; + } + else + { + C << nl << "return " << fixKwd(paramPrefix + outParams.front()->name()) << ";"; + } + C << eb; + } + + C.dec(); + C << ");" << eb; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitEnum(const EnumPtr& p) +{ + bool unscoped = findMetaData(p->getMetaData(), TypeContextCpp11) == "%unscoped"; + H << sp << nl << "enum "; + if(!unscoped) + { + H << "class "; + } + H << fixKwd(p->name()); + if(!unscoped && p->maxValue() <= 0xFF) + { + H << " : unsigned char"; + } + H << sb; + + EnumeratorList enumerators = p->getEnumerators(); + // + // Check if any of the enumerators were assigned an explicit value. + // + const bool explicitValue = p->explicitValue(); + for(EnumeratorList::const_iterator en = enumerators.begin(); en != enumerators.end();) + { + H << nl << fixKwd((*en)->name()); + // + // If any of the enumerators were assigned an explicit value, we emit + // an explicit value for *all* enumerators. + // + if(explicitValue) + { + H << " = " << int64ToString((*en)->value()); + } + if(++en != enumerators.end()) + { + H << ','; + } + } + H << eb << ';'; +} + +void +Slice::Gen::Cpp11TypesVisitor::visitConst(const ConstPtr& p) +{ + H << sp; + H << nl << (isConstexprType(p->type()) ? "constexpr " : "const ") + << typeToString(p->type(), p->typeMetaData(), _useWstring | TypeContextCpp11) << " " << fixKwd(p->name()) + << " = "; + writeConstantValue(H, p->type(), p->valueType(), p->value(), _useWstring, p->typeMetaData(), true); + H << ';'; +} + +void +Slice::Gen::Cpp11TypesVisitor::emitUpcall(const ExceptionPtr& base, const string& call, bool isLocal) +{ + C << nl << (base ? fixKwd(base->scoped()) : string(isLocal ? "::Ice::LocalException" : "::Ice::UserException")) + << call; +} + +Slice::Gen::Cpp11ObjectVisitor::Cpp11ObjectVisitor(::IceUtilInternal::Output& h, + ::IceUtilInternal::Output& c, + const std::string& dllExport) : + H(h), + C(c), + _dllExport(dllExport), + _dllClassExport(toDllClassExport(dllExport)), _dllMemberExport(toDllMemberExport(dllExport)), + _doneStaticSymbol(false), + _useWstring(false) +{ +} + +void +Slice::Gen::Cpp11ObjectVisitor::emitDataMember(const DataMemberPtr& p) +{ + string name = fixKwd(p->name()); + H << nl << typeToString(p->type(), p->optional(), p->getMetaData(), + _useWstring | TypeContextCpp11) << ' ' << name; + + string defaultValue = p->defaultValue(); + if(!defaultValue.empty()) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(p->optional() && builtin && builtin->kind() == Builtin::KindString) + { + // + // = "<string literal>" doesn't work for optional<std::string> + // + H << '{'; + writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring, p->getMetaData(), true); + H << '}'; + } + else + { + H << " = "; + writeConstantValue(H, p->type(), p->defaultValueType(), defaultValue, _useWstring, p->getMetaData(), true); + } + } + H << ";"; +} + +void +Slice::Gen::Cpp11InterfaceVisitor::emitUpcall(const ClassDefPtr& base, const string& call) +{ + C << nl << (base ? fixKwd(base->scoped()) : string("::Ice::Object")) << call; +} + +void +Slice::Gen::Cpp11ValueVisitor::emitUpcall(const ClassDefPtr& base, const string& call) +{ + C << nl << (base ? fixKwd(base->scoped()) : string("::Ice::Value")) << call; +} + +Slice::Gen::Cpp11LocalObjectVisitor::Cpp11LocalObjectVisitor(::IceUtilInternal::Output& h, + ::IceUtilInternal::Output& c, + const std::string& dllExport) : + Cpp11ObjectVisitor(h, c, dllExport) +{ +} + +bool +Slice::Gen::Cpp11LocalObjectVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasLocalClassDefs()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + string name = fixKwd(p->name()); + H << sp << nl << "namespace " << name << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11LocalObjectVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp; + H << nl << '}'; + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11LocalObjectVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(!p->isLocal()) + { + return false; + } + if(p->isDelegate()) + { + return false; + } + + string name = fixKwd(p->name()); + string scope = fixKwd(p->scope()); + string scoped = fixKwd(p->scoped()); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + DataMemberList dataMembers = p->dataMembers(); + DataMemberList allDataMembers = p->allDataMembers(); + + H << sp << nl << "class " << _dllClassExport << name; + H.useCurrentPosAsIndent(); + if(!bases.empty()) + { + H << " : "; + ClassList::const_iterator q = bases.begin(); + bool virtualInheritance = p->isInterface(); + while(q != bases.end()) + { + if(virtualInheritance || (*q)->isInterface()) + { + H << "virtual "; + } + + H << "public " << fixKwd((*q)->scoped()); + if(++q != bases.end()) + { + H << ',' << nl; + } + } + } + + H.restoreIndent(); + H << sb; + H.dec(); + H << nl << "public:" << sp; + H.inc(); + + // + // Out of line virtual dtor to avoid weak vtable + // + H << sp << nl << _dllMemberExport << "virtual ~" << name << "();"; + C << sp << nl << scoped.substr(2) << "::~" << name << "()"; + C << sb; + C << eb; + + vector<string> params; + vector<string> allTypes; + vector<string> allParamDecls; + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + params.push_back(fixKwd((*q)->name())); + } + + for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q) + { + string typeName = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), _useWstring); + allTypes.push_back(typeName); + allParamDecls.push_back(typeName + " __ice_" + (*q)->name()); + } + + if(!p->isInterface()) + { + if(p->hasDefaultValues()) + { + H << sp << nl << name << "() :"; + H.inc(); + writeDataMemberInitializers(H, dataMembers, _useWstring | TypeContextCpp11); + H.dec(); + H << sb; + H << eb; + } + else + { + H << sp << nl << name << "() = default;"; + } + + emitOneShotConstructor(p); + } + + if(p->hasMetaData("cpp:comparable")) + { + H << sp; + H << nl << "virtual bool operator==(const " << p->name() << "&) const = 0;"; + H << nl << "virtual bool operator<(const " << p->name() << "&) const = 0;"; + } + return true; +} + +void +Slice::Gen::Cpp11LocalObjectVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + // + // Emit data members. Access visibility may be specified by metadata. + // + bool inProtected = false; + DataMemberList dataMembers = p->dataMembers(); + bool prot = p->hasMetaData("protected"); + bool needSp = true; + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(prot || (*q)->hasMetaData("protected")) + { + if(!inProtected) + { + H.dec(); + H << sp << nl << "protected:" << sp; + H.inc(); + inProtected = true; + needSp = false; + } + } + else + { + if(inProtected) + { + H.dec(); + H << sp << nl << "public:" << sp; + H.inc(); + inProtected = false; + needSp = false; + } + } + + if(needSp) + { + H << sp; + needSp = false; + } + + emitDataMember(*q); + } + + H << eb << ';'; +} + +bool +Slice::Gen::Cpp11LocalObjectVisitor::visitExceptionStart(const ExceptionPtr&) +{ + return false; +} + +bool +Slice::Gen::Cpp11LocalObjectVisitor::visitStructStart(const StructPtr&) +{ + return false; +} + +void +Slice::Gen::Cpp11LocalObjectVisitor::visitOperation(const OperationPtr& p) +{ + string name = p->name(); + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + + int typeCtx = _useWstring | TypeContextLocal | TypeContextCpp11; + TypePtr ret = p->returnType(); + string retS = returnTypeToString(ret, p->returnIsOptional(), p->getMetaData(), + typeCtx | TypeContextCpp11); + + string params = "("; + string paramsDecl = "("; + string args = "("; + + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string classScope = fixKwd(cl->scope()); + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + vector< string> outDecls; + for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string paramName = fixKwd(string(paramPrefix) + (*q)->name()); + TypePtr type = (*q)->type(); + bool isOutParam = (*q)->isOutParam(); + string typeString; + if(isOutParam) + { + outParams.push_back(*q); + typeString = outputTypeToString(type, (*q)->optional(), (*q)->getMetaData(), typeCtx); + } + else + { + inParams.push_back(*q); + typeString = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), typeCtx); + } + + if(q != paramList.begin()) + { + params += ", "; + paramsDecl += ", "; + args += ", "; + } + + params += typeString; + paramsDecl += typeString; + paramsDecl += ' '; + paramsDecl += paramName; + args += paramName; + + if(isOutParam) + { + outDecls.push_back(typeString); + } + } + + params += ')'; + paramsDecl += ')'; + args += ')'; + + string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : ""; + + string deprecateSymbol = getDeprecateSymbol(p, cl); + + H << sp; + H << nl << deprecateSymbol << "virtual " << retS << ' ' << fixKwd(name) << params << isConst << " = 0;"; + + if(cl->hasMetaData("async-oneway") || p->hasMetaData("async-oneway")) + { + vector<string> paramsDeclAMI; + vector<string> outParamsDeclAMI; + + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::const_iterator r = paramList.begin(); r != paramList.end(); ++r) + { + string paramName = fixKwd((*r)->name()); + + StringList metaData = (*r)->getMetaData(); + string typeString; + if(!(*r)->isOutParam()) + { + typeString = inputTypeToString((*r)->type(), (*r)->optional(), metaData, typeCtx); + paramsDeclAMI.push_back(typeString + ' ' + paramName); + } + } + + H << sp; + H << nl << "virtual ::std::function<void()>"; + H << nl << name << "Async("; + H.useCurrentPosAsIndent(); + for(vector<string>::const_iterator i = paramsDeclAMI.begin(); i != paramsDeclAMI.end(); ++i) + { + H << *i << ","; + } + if(!paramsDeclAMI.empty()) + { + H << nl; + } + H << "::std::function<void(::std::exception_ptr)> exception,"; + H << nl << "::std::function<void(bool)> sent = nullptr) = 0;"; + H.restoreIndent(); + + H << sp; + H << nl << "template<template<typename> class P = ::std::promise>"; + H << nl << deprecateSymbol << "auto " << name << "Async" << spar << paramsDeclAMI << epar; + H.inc(); + H << nl << "-> decltype(::std::declval<P<bool>>().get_future())"; + H.dec(); + H << sb; + H << nl << "using Promise = P<bool>;"; + H << nl << "auto __promise = ::std::make_shared<Promise>();"; + + H << nl << name << "Async("; + H.useCurrentPosAsIndent(); + for(vector<string>::const_iterator i = paramsDeclAMI.begin(); i != paramsDeclAMI.end(); ++i) + { + H << *i << ","; + } + if(!paramsDeclAMI.empty()) + { + H << nl; + } + H << "[__promise](::std::exception_ptr __ex)"; + H << sb; + H << nl << "__promise->set_exception(::std::move(__ex));"; + H << eb << ","; + H << nl << "[__promise](bool __b)"; + H << sb; + H << nl << "__promise->set_value(__b);"; + H << eb << ");"; + H.restoreIndent(); + + H << nl << "return __promise->get_future();"; + H << eb; + } +} + +Slice::Gen::Cpp11InterfaceVisitor::Cpp11InterfaceVisitor(::IceUtilInternal::Output& h, + ::IceUtilInternal::Output& c, + const std::string& dllExport) : + Cpp11ObjectVisitor(h, c, dllExport) +{ +} + +bool +Slice::Gen::Cpp11InterfaceVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasNonLocalInterfaceDefs()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + string name = fixKwd(p->name()); + H << sp << nl << "namespace " << name << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11InterfaceVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp; + H << nl << '}'; + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11InterfaceVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal() || (!p->isInterface() && p->allOperations().empty())) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string suffix = p->isInterface() ? "" : "Disp"; + + string name = fixKwd(p->name() + suffix); + string scope = fixKwd(p->scope()); + string scoped = fixKwd(p->scope() + p->name() + suffix); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + H << sp << nl << "class " << _dllExport << name << " : "; + H.useCurrentPosAsIndent(); + if(bases.empty() || (base && base->allOperations().empty())) + { + H << "public virtual ::Ice::Object"; + } + else + { + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + string baseSuffix = (*q)->isInterface() ? "" : "Disp"; + string baseScoped = fixKwd((*q)->scope() + (*q)->name() + baseSuffix); + + H << "public virtual " << baseScoped; + if(++q != bases.end()) + { + H << ',' << nl; + } + } + } + + H.restoreIndent(); + H << sb; + H.dec(); + H << nl << "public:" << sp; + H.inc(); + + // + // In C++, a nested type cannot have the same name as the enclosing type + // + if(name != "ProxyType") + { + H << nl << "using ProxyType = " << p->name() << "Prx;"; + } + + vector<string> params; + vector<string> allTypes; + vector<string> allParamDecls; + + ClassList allBases = p->allBases(); + StringList ids; + transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); + StringList other; + other.push_back(p->scoped()); + other.push_back("::Ice::Object"); + other.sort(); + ids.merge(other); + ids.unique(); + StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), p->scoped()); + assert(scopedIter != ids.end()); + + H << sp; + H << nl << "virtual bool ice_isA(::std::string, const ::Ice::Current& = ::Ice::noExplicitCurrent) const override;"; + H << nl + << "virtual ::std::vector<::std::string> ice_ids(const ::Ice::Current& = ::Ice::noExplicitCurrent) const override;"; + H << nl << "virtual ::std::string ice_id(const ::Ice::Current& = ::Ice::noExplicitCurrent) const override;"; + H << sp << nl << "static const ::std::string& ice_staticId();"; + + string flatName = p->flattenedScope() + p->name() + "_ids"; + + C << sp; + C << nl << "bool" << nl << scoped.substr(2) << "::ice_isA(::std::string _s, const ::Ice::Current&) const"; + C << sb; + C << nl << "return ::std::binary_search(" << flatName << ", " << flatName << " + " << ids.size() << ", _s);"; + C << eb; + + C << sp; + C << nl << "::std::vector<::std::string>" << nl << scoped.substr(2) << "::ice_ids(const ::Ice::Current&) const"; + C << sb; + C << nl << "return ::std::vector<::std::string>(&" << flatName << "[0], &" << flatName << '[' << ids.size() << "]);"; + C << eb; + + C << sp; + C << nl << "::std::string" << nl << scoped.substr(2) << "::ice_id(const ::Ice::Current&) const"; + C << sb; + C << nl << "return ice_staticId();"; + C << eb; + + C << sp; + C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()"; + C << sb; + // + // Use local static so that ice_staticId() is usable during static construction. + // + C << nl << "static const ::std::string typeId = \"" << *scopedIter << "\";"; + C << nl << "return typeId;"; + C << eb; + return true; +} + +void +Slice::Gen::Cpp11InterfaceVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string suffix = p->isInterface() ? "" : "Disp"; + string scoped = fixKwd(p->scope() + p->name() + suffix); + + string scope = fixKwd(p->scope()); + string name = fixKwd(p->name() + suffix); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + OperationList allOps = p->allOperations(); + if(!allOps.empty()) + { + StringList allOpNames; + transform(allOps.begin(), allOps.end(), back_inserter(allOpNames), ::IceUtil::constMemFun(&Contained::name)); + allOpNames.push_back("ice_id"); + allOpNames.push_back("ice_ids"); + allOpNames.push_back("ice_isA"); + allOpNames.push_back("ice_ping"); + allOpNames.sort(); + allOpNames.unique(); + + string flatName = p->flattenedScope() + p->name() + "_ops"; + + H << sp; + H << nl << "virtual bool __dispatch(::IceInternal::Incoming&, const ::Ice::Current&) override;"; + + C << sp; + C << nl << "bool"; + C << nl << scoped.substr(2) << "::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& c)"; + C << sb; + + C << nl << "::std::pair< const ::std::string*, const ::std::string*> r = " + << "::std::equal_range(" << flatName << ", " << flatName << " + " << allOpNames.size() << ", c.operation);"; + C << nl << "if(r.first == r.second)"; + C << sb; + C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, c.id, c.facet, c.operation);"; + C << eb; + C << sp; + C << nl << "switch(r.first - " << flatName << ')'; + C << sb; + int i = 0; + for(StringList::const_iterator q = allOpNames.begin(); q != allOpNames.end(); ++q) + { + C << nl << "case " << i++ << ':'; + C << sb; + C << nl << "return ___" << *q << "(in, c);"; + C << eb; + } + C << nl << "default:"; + C << sb; + C << nl << "assert(false);"; + C << nl << "throw ::Ice::OperationNotExistException(__FILE__, __LINE__, c.id, c.facet, c.operation);"; + C << eb; + C << eb; + C << eb; + } + + H << eb << ';'; + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11InterfaceVisitor::visitExceptionStart(const ExceptionPtr&) +{ + return false; +} + +bool +Slice::Gen::Cpp11InterfaceVisitor::visitStructStart(const StructPtr&) +{ + return false; +} + +void +Slice::Gen::Cpp11InterfaceVisitor::visitOperation(const OperationPtr& p) +{ + string name = p->name(); + + TypePtr ret = p->returnType(); + + vector<string> params; + vector<string> args; + + vector<string> responseParams; + vector<string> responseParamsDecl; + + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string classScope = fixKwd(cl->scope()); + + string suffix = cl->isInterface() ? "" : "Disp"; + string scope = fixKwd(cl->scope() + cl->name() + suffix + "::"); + string scoped = fixKwd(cl->scope() + cl->name() + suffix + "::" + p->name()); + + bool amd = (cl->hasMetaData("amd") || p->hasMetaData("amd")); + + if(p->hasMarshaledResult()) + { + + } + + if(ret) + { + string typeS = inputTypeToString(ret, p->returnIsOptional(), p->getMetaData(), _useWstring | TypeContextCpp11); + responseParams.push_back(typeS); + responseParamsDecl.push_back(typeS + " __ret"); + } + + string retS; + if(amd) + { + retS = "void"; + } + else if(p->hasMarshaledResult()) + { + retS = resultStructName(name, "", true); + } + else + { + retS = returnTypeToString(ret, p->returnIsOptional(), p->getMetaData(), _useWstring | TypeContextCpp11); + } + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q) + { + TypePtr type = (*q)->type(); + string paramName = fixKwd(string(paramPrefix) + (*q)->name()); + bool isOutParam = (*q)->isOutParam(); + string typeString; + int typeCtx = _useWstring | TypeContextCpp11; + if(!isOutParam) + { + inParams.push_back(*q); + params.push_back(typeToString(type, (*q)->optional(), (*q)->getMetaData(), typeCtx | TypeContextInParam)); + args.push_back(condMove(isMovable(type) && !isOutParam, paramName)); + } + else + { + outParams.push_back(*q); + if(!p->hasMarshaledResult() && !amd) + { + params.push_back(outputTypeToString(type, (*q)->optional(), (*q)->getMetaData(), typeCtx)); + args.push_back(condMove(isMovable(type) && !isOutParam, paramName)); + } + + string responseTypeS = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), typeCtx); + responseParams.push_back(responseTypeS); + responseParamsDecl.push_back(responseTypeS + " " + paramName); + } + } + if(amd) + { + if(p->hasMarshaledResult()) + { + string resultName = resultStructName(name, "", true); + params.push_back("::std::function<void(const " + resultName + "&)>"); + args.push_back("inS->response<" + resultName + ">()"); + } + else + { + params.push_back("::std::function<void(" + joinString(responseParams, ",") + ")>"); + args.push_back(ret || !outParams.empty() ? "__responseCB" : "inS->response()"); + } + params.push_back("::std::function<void(::std::exception_ptr)>"); + args.push_back("inS->exception()"); + } + params.push_back("const ::Ice::Current& = ::Ice::noExplicitCurrent"); + args.push_back("__current"); + + if(cl->isInterface()) + { + emitOpNameResult(H, p, _useWstring); + } + + if(p->hasMarshaledResult()) + { + string resultName = resultStructName(name, "", true); + H << sp; + H << nl << "class " << resultName << " : public ::Ice::MarshaledResult"; + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + H << nl << resultName << spar << responseParams << "const ::Ice::Current&" << epar << ";"; + H << eb << ';'; + + C << sp << nl << scope.substr(2) << resultName << "::" << resultName; + C << spar << responseParamsDecl << "const ::Ice::Current& __current" << epar << ":"; + C.inc(); + C << nl << "MarshaledResult(__current)"; + C.dec(); + C << sb; + C << nl << "__os->startEncapsulation(__current.encoding, " << opFormatTypeToString(p) << ");"; + writeMarshalCode(C, outParams, p, true, TypeContextCpp11); + if(p->returnsClasses(false)) + { + C << nl << "__os->writePendingValues();"; + } + C << nl << "__os->endEncapsulation();"; + C << eb; + } + + string isConst = ((p->mode() == Operation::Nonmutating) || p->hasMetaData("cpp:const")) ? " const" : ""; + + string opName = amd ? (name + "Async") : fixKwd(name); + string deprecateSymbol = getDeprecateSymbol(p, cl); + + H << sp; + H << nl << deprecateSymbol << "virtual " << retS << ' ' << opName << spar << params << epar << isConst << " = 0;"; + H << nl << "bool ___" << name << "(::IceInternal::Incoming&, const ::Ice::Current&)" << isConst << ';'; + + C << sp; + C << nl << "bool"; + C << nl << scope.substr(2); + C << "___" << name << "(::IceInternal::Incoming& __inS" << ", const ::Ice::Current& __current)" << isConst; + C << sb; + C << nl << "__checkMode(" << operationModeToString(p->mode(), true) << ", __current.mode);"; + + if(!inParams.empty()) + { + C << nl << "auto __is = __inS.startReadParams();"; + writeAllocateCode(C, inParams, 0, true, _useWstring | TypeContextInParam | TypeContextCpp11); + writeUnmarshalCode(C, inParams, 0, true, _useWstring | TypeContextInParam | TypeContextCpp11); + if(p->sendsClasses(false)) + { + C << nl << "__is->readPendingValues();"; + } + C << nl << "__inS.endReadParams();"; + } + else + { + C << nl << "__inS.readEmptyParams();"; + } + if(p->format() != DefaultFormat) + { + C << nl << "__inS.setFormat(" << opFormatTypeToString(p) << ");"; + } + + if(!amd) + { + writeAllocateCode(C, outParams, 0, true, _useWstring | TypeContextCpp11); + if(p->hasMarshaledResult()) + { + C << nl << "__inS.setMarshaledResult("; + } + else if(ret) + { + C << nl << retS << " __ret = "; + } + else + { + C << nl; + } + + C << opName << spar << args << epar; + if(p->hasMarshaledResult()) + { + C << ");"; + } + else + { + C << ";"; + if(ret || !outParams.empty()) + { + C << nl << "auto __os = __inS.startWriteParams();"; + writeMarshalCode(C, outParams, p, true, TypeContextCpp11); + if(p->returnsClasses(false)) + { + C << nl << "__os->writePendingValues();"; + } + C << nl << "__inS.endWriteParams();"; + } + else + { + C << nl << "__inS.writeEmptyParams();"; + } + } + C << nl << "return false;"; + } + else + { + C << nl << "auto inS = ::IceInternal::IncomingAsync::create(__inS);"; + if(!p->hasMarshaledResult() && (ret || !outParams.empty())) + { + C << nl << "auto __responseCB = [inS]" << spar << responseParamsDecl << epar; + C << sb; + C << nl << "auto __os = inS->startWriteParams();"; + writeMarshalCode(C, outParams, p, true, TypeContextCpp11); + if(p->returnsClasses(false)) + { + C << nl << "__os->writePendingValues();"; + } + C << nl << "inS->endWriteParams();"; + C << nl << "inS->completed();"; + C << eb << ';'; + } + C << nl << opName << spar << args << epar << ';'; + C << nl << "return true;"; + } + C << eb; +} + +Slice::Gen::Cpp11ValueVisitor::Cpp11ValueVisitor(::IceUtilInternal::Output& h, + ::IceUtilInternal::Output& c, + const std::string& dllExport) : + Cpp11ObjectVisitor(h, c, dllExport) +{ +} + +bool +Slice::Gen::Cpp11ValueVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasValueDefs()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + string name = fixKwd(p->name()); + H << sp << nl << "namespace " << name << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11ValueVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp; + H << nl << '}'; + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11ValueVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(p->isLocal() || p->isInterface()) + { + return false; + } + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string name = fixKwd(p->name()); + string scope = fixKwd(p->scope()); + string scoped = fixKwd(p->scoped()); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty()) + { + base = bases.front(); + } + DataMemberList dataMembers = p->dataMembers(); + DataMemberList allDataMembers = p->allDataMembers(); + + H << sp << nl << "class " << _dllClassExport << name << " : public ::Ice::ValueHelper<" << name << ", "; + + if(!base || (base && base->isInterface())) + { + H << "Ice::Value"; + } + else + { + H << fixKwd(base->scoped()); + } + H << ">"; + H << sb; + H.dec(); + H << nl << "public:" << sp; + H.inc(); + + // Out of line dtor to avoid weak vtable + H << nl << _dllMemberExport << "virtual ~" << name << "();"; + C << sp; + C << nl << scoped.substr(2) << "::~" << name << "()"; + C << sb; + C << eb; + + vector<string> params; + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + params.push_back(fixKwd((*q)->name())); + } + + H << sp << nl << name << "() = default;"; + + emitOneShotConstructor(p); + + writeIceTuple(H, p->allDataMembers(), _useWstring); + + H << sp << nl << _dllMemberExport << "static const ::std::string& ice_staticId();"; + return true; +} + +void +Slice::Gen::Cpp11ValueVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string scoped = fixKwd(p->scoped()); + string scope = fixKwd(p->scope()); + string name = fixKwd(p->name()); + ClassList bases = p->bases(); + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + bool basePreserved = p->inheritsMetaData("preserve-slice"); + bool preserved = p->hasMetaData("preserve-slice"); + + if(preserved && !basePreserved) + { + H << sp; + H << nl << "virtual void __write(::Ice::OutputStream*) const override;"; + H << nl << "virtual void __read(::Ice::InputStream*) override;"; + + C << sp; + C << nl << "void" << nl << scoped.substr(2) << "::__write(::Ice::OutputStream* __os) const"; + C << sb; + C << nl << "__os->startValue(__slicedData);"; + C << nl << "__writeImpl(__os);"; + C << nl << "__os->endValue();"; + C << eb; + + C << sp; + C << nl << "void" << nl << scoped.substr(2) << "::__read(::Ice::InputStream* __is)"; + C << sb; + C << nl << "__is->startValue();"; + C << nl << "__readImpl(__is);"; + C << nl << "__slicedData = __is->endValue(true);"; + C << eb; + } + + C << sp; + C << nl << "const ::std::string&" << nl << scoped.substr(2) << "::ice_staticId()"; + C << sb; + // + // Use local static so that ice_staticId() is usable during static construction. + // + C << nl << "static const ::std::string typeId = \"" << p->scoped() << "\";"; + C << nl << "return typeId;"; + C << eb; + + // + // Emit data members. Access visibility may be specified by metadata. + // + bool inProtected = false; + bool generateFriend = false; + DataMemberList dataMembers = p->dataMembers(); + bool prot = p->hasMetaData("protected"); + bool needSp = true; + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(prot || (*q)->hasMetaData("protected")) + { + if(!inProtected) + { + H.dec(); + H << sp << nl << "protected:" << sp; + H.inc(); + inProtected = true; + needSp = false; + } + generateFriend = true; + } + else + { + if(inProtected) + { + H.dec(); + H << sp << nl << "public:" << sp; + H.inc(); + inProtected = false; + needSp = false; + } + } + + if(needSp) + { + H << sp; + needSp = false; + } + + emitDataMember(*q); + } + + if(preserved && !basePreserved) + { + if(!inProtected) + { + H.dec(); + H << sp << nl << "protected:"; + H.inc(); + inProtected = true; + } + H << sp << nl << "::std::shared_ptr<::Ice::SlicedData> __slicedData;"; + } + + if(generateFriend) + { + if(!inProtected) + { + H.dec(); + H << sp << nl << "protected:"; + H.inc(); + inProtected = true; + } + + H << sp; + H << nl << "template<typename T, typename S>"; + H << nl << "friend struct Ice::StreamWriter;"; + H << nl << "template<typename T, typename S>"; + H << nl << "friend struct Ice::StreamReader;"; + } + + H << eb << ';'; + + if(!_doneStaticSymbol) + { + // + // We need an instance here to trigger initialization if the implementation is in a static library. + // But we do this only once per source file, because a single instance is sufficient to initialize + // all of the globals in a compilation unit. + // + _doneStaticSymbol = true; + H << sp << nl << "static " << fixKwd(p->name()) << " _" << p->name() << "_init;"; + } + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11ValueVisitor::visitExceptionStart(const ExceptionPtr&) +{ + return false; +} + +bool +Slice::Gen::Cpp11ValueVisitor::visitStructStart(const StructPtr&) +{ + return false; +} + +void +Slice::Gen::Cpp11ValueVisitor::visitOperation(const OperationPtr& p) +{ + emitOpNameResult(H, p, _useWstring); +} + +bool +Slice::Gen::Cpp11ObjectVisitor::emitVirtualBaseInitializers(const ClassDefPtr& derived, const ClassDefPtr& base) +{ + DataMemberList allDataMembers = base->allDataMembers(); + if(allDataMembers.empty()) + { + return false; + } + + string upcall = "("; + for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q) + { + if(q != allDataMembers.begin()) + { + upcall += ", "; + } + if(isMovable((*q)->type())) + { + upcall += "::std::move(__ice_" + (*q)->name() + ")"; + } + else + { + upcall += "__ice_" + (*q)->name(); + } + } + upcall += ")"; + + if(base->isLocal()) + { + H << nl << fixKwd(base->scoped()); + } + else + { + H << nl << "Ice::ValueHelper<" << fixKwd(derived->scoped()) << ", " << fixKwd(base->scoped()) << ">"; + } + H << upcall; + return true; +} + +void +Slice::Gen::Cpp11ObjectVisitor::emitOneShotConstructor(const ClassDefPtr& p) +{ + DataMemberList allDataMembers = p->allDataMembers(); + + if(!allDataMembers.empty()) + { + vector<string> allParamDecls; + DataMemberList dataMembers = p->dataMembers(); + + for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q) + { + string typeName = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), + _useWstring | TypeContextCpp11); + allParamDecls.push_back(typeName + " __ice_" + (*q)->name()); + } + + H << sp << nl; + if(allParamDecls.size() == 1) + { + H << "explicit "; + } + H << fixKwd(p->name()) << spar << allParamDecls << epar << " :"; + H.inc(); + + ClassList bases = p->bases(); + + if(!bases.empty() && !bases.front()->isInterface()) + { + if(emitVirtualBaseInitializers(p, bases.front())) + { + if(!dataMembers.empty()) + { + H << ','; + } + } + } + + if(!dataMembers.empty()) + { + H << nl; + } + + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(q != dataMembers.begin()) + { + H << ',' << nl; + } + string memberName = fixKwd((*q)->name()); + if(isMovable((*q)->type())) + { + H << memberName << "(::std::move(" << "__ice_" << (*q)->name() << "))"; + } + else + { + H << memberName << '(' << "__ice_" << (*q)->name() << ')'; + } + } + + H.dec(); + H << sb; + H << eb; + } +} + +Slice::Gen::Cpp11StreamVisitor::Cpp11StreamVisitor(Output& h, Output& c, const string& dllExport) : + H(h), + C(c), + _dllExport(dllExport) +{ +} + +bool +Slice::Gen::Cpp11StreamVisitor::visitModuleStart(const ModulePtr& m) +{ + if(!m->hasNonLocalContained(Contained::ContainedTypeStruct) && + !m->hasNonLocalContained(Contained::ContainedTypeEnum) && + !m->hasNonLocalContained(Contained::ContainedTypeException) && + !m->hasNonLocalContained(Contained::ContainedTypeClass)) + { + return false; + } + + if(UnitPtr::dynamicCast(m->container())) + { + // + // Only emit this for the top-level module. + // + H << sp; + H << nl << "namespace Ice" << nl << '{' << sp; + + if(m->hasNonLocalContained(Contained::ContainedTypeStruct)) + { + C << sp; + C << nl << "namespace Ice" << nl << '{'; + } + } + return true; +} + +void +Slice::Gen::Cpp11StreamVisitor::visitModuleEnd(const ModulePtr& m) +{ + if(UnitPtr::dynamicCast(m->container())) + { + // + // Only emit this for the top-level module. + // + H << nl << '}'; + if(m->hasNonLocalContained(Contained::ContainedTypeStruct)) + { + C << nl << '}'; + } + } +} + +bool +Slice::Gen::Cpp11StreamVisitor::visitStructStart(const StructPtr& p) +{ + if(p->isLocal()) + { + return false; + } + + string scoped = fixKwd(p->scoped()); + + H << nl << "template<>"; + H << nl << "struct StreamableTraits< " << scoped << ">"; + H << sb; + H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryStruct;"; + H << nl << "static const int minWireSize = " << p->minWireSize() << ";"; + H << nl << "static const bool fixedLength = " << (p->isVariableLength() ? "false" : "true") << ";"; + H << eb << ";" << nl; + + writeStreamHelpers(H, p, p->dataMembers(), false, false, true); + + return false; +} + +bool +Slice::Gen::Cpp11StreamVisitor::visitClassDefStart(const ClassDefPtr& c) +{ + if(!c->isLocal() && !c->isInterface()) + { + writeStreamHelpers(H,c, c->dataMembers(), c->hasBaseDataMembers(), true, true); + } + return false; +} + +void +Slice::Gen::Cpp11StreamVisitor::visitExceptionEnd(const ExceptionPtr& p) +{ + if(!p->isLocal()) + { + writeStreamHelpers(H,p, p->dataMembers(), p->hasBaseDataMembers(), true, true); + } +} + +void +Slice::Gen::Cpp11StreamVisitor::visitEnum(const EnumPtr& p) +{ + if(!p->isLocal()) + { + string scoped = fixKwd(p->scoped()); + H << nl << "template<>"; + H << nl << "struct StreamableTraits< " << scoped << ">"; + H << sb; + H << nl << "static const StreamHelperCategory helper = StreamHelperCategoryEnum;"; + H << nl << "static const int minValue = " << p->minValue() << ";"; + H << nl << "static const int maxValue = " << p->maxValue() << ";"; + H << nl << "static const int minWireSize = " << p->minWireSize() << ";"; + H << nl << "static const bool fixedLength = false;"; + H << eb << ";" << nl; + } +} + + +Slice::Gen::Cpp11CompatibilityVisitor::Cpp11CompatibilityVisitor(Output& h, Output&, const string& dllExport) : + H(h), + _dllExport(dllExport) +{ +} + +bool +Slice::Gen::Cpp11CompatibilityVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasClassDecls()) + { + return false; + } + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + return true; +} + +void +Slice::Gen::Cpp11CompatibilityVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp; + H << nl << '}'; +} + +void +Slice::Gen::Cpp11CompatibilityVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + if(p->definition() && p->definition()->isDelegate()) + { + return; + } + + string name = fixKwd(p->name()); + string scoped = fixKwd(p->scoped()); + + H << sp << nl << "using " << p->name() << "Ptr = ::std::shared_ptr<" << name << ">;"; + + if(!p->isLocal()) + { + ClassDefPtr def = p->definition(); + if(p->isInterface() || (def && !def->allOperations().empty())) + { + H << nl << "using " << p->name() << "PrxPtr = ::std::shared_ptr<" << p->name() << "Prx>;"; + } + } +} + +Slice::Gen::Cpp11ImplVisitor::Cpp11ImplVisitor(Output& h, Output& c, const string& dllExport) : + H(h), C(c), _dllExport(dllExport), _useWstring(false) +{ +} + +string +Slice::Gen::Cpp11ImplVisitor::defaultValue(const TypePtr& type, const StringList& metaData) const +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindBool: + { + return "false"; + } + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + { + return "0"; + } + case Builtin::KindFloat: + case Builtin::KindDouble: + { + return "0.0"; + } + case Builtin::KindString: + { + return "::std::string()"; + } + case Builtin::KindValue: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + return "nullptr"; + } + } + } + else + { + ProxyPtr prx = ProxyPtr::dynamicCast(type); + + if(ProxyPtr::dynamicCast(type) || ClassDeclPtr::dynamicCast(type)) + { + return "nullptr"; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + return fixKwd(st->scoped()) + "()"; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + EnumeratorList enumerators = en->getEnumerators(); + return fixKwd(en->scoped() + "::" + enumerators.front()->name()); + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return typeToString(seq, metaData, _useWstring | TypeContextCpp11) + "()"; + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(dict) + { + return fixKwd(dict->scoped()) + "()"; + } + } + + assert(false); + return "???"; +} + +void +Slice::Gen::Cpp11ImplVisitor::writeReturn(Output& out, const TypePtr& type, const StringList& metaData) +{ + out << nl << "return " << defaultValue(type, metaData) << ";"; +} + +bool +Slice::Gen::Cpp11ImplVisitor::visitModuleStart(const ModulePtr& p) +{ + if(!p->hasClassDefs()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string name = fixKwd(p->name()); + + H << sp << nl << "namespace " << name << nl << '{'; + + return true; +} + +void +Slice::Gen::Cpp11ImplVisitor::visitModuleEnd(const ModulePtr&) +{ + H << sp; + H << nl << '}'; + + _useWstring = resetUseWstring(_useWstringHist); +} + +bool +Slice::Gen::Cpp11ImplVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + if(!p->isAbstract()) + { + return false; + } + + _useWstring = setUseWstring(p, _useWstringHist, _useWstring); + + string name = p->name(); + string scope = fixKwd(p->scope()); + string cls = scope.substr(2) + name + "I"; + ClassList bases = p->bases(); + + H << sp; + H << nl << "class " << name << "I : "; + H.useCurrentPosAsIndent(); + H << "public virtual "; + + if(p->isInterface() || p->isLocal()) + { + H << fixKwd(name); + } + else + { + H << fixKwd(name + "Disp"); + } + H.restoreIndent(); + + H << sb; + H.dec(); + H << nl << "public:"; + H.inc(); + + OperationList ops = p->allOperations(); + + for(OperationList::const_iterator r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = (*r); + string opName = op->name(); + + TypePtr ret = op->returnType(); + string retS = returnTypeToString(ret, op->returnIsOptional(), op->getMetaData(), + _useWstring | TypeContextCpp11); + + ParamDeclList params = op->parameters(); + ParamDeclList outParams; + ParamDeclList inParams; + for(ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q) + { + if((*q)->isOutParam()) + { + outParams.push_back(*q); + } + else + { + inParams.push_back(*q); + } + } + + if(!p->isLocal() && (p->hasMetaData("amd") || op->hasMetaData("amd"))) + { + string responseParams; + string responseParamsDecl; + + H << sp << nl << "virtual void " << opName << "Async("; + H.useCurrentPosAsIndent(); + for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q) + { + H << typeToString((*q)->type(), (*q)->optional(), + (*q)->getMetaData(), _useWstring | TypeContextInParam | TypeContextCpp11) + << "," << nl; + } + + if(ret) + { + string typeS = inputTypeToString(ret, op->returnIsOptional(), op->getMetaData(), + _useWstring | TypeContextCpp11); + responseParams = typeS; + responseParamsDecl = typeS + " __ret"; + if(!outParams.empty()) + { + responseParams += ", "; + responseParamsDecl += ", "; + } + } + + for(ParamDeclList::iterator q = outParams.begin(); q != outParams.end(); ++q) + { + if(q != outParams.begin()) + { + responseParams += ", "; + responseParamsDecl += ", "; + } + string typeS = inputTypeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), + _useWstring | TypeContextCpp11); + responseParams += typeS; + responseParamsDecl += typeS + " " + fixKwd(string(paramPrefix) + (*q)->name()); + } + + string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : ""; + + H << "std::function<void(" << responseParams << ")>,"; + H << nl << "std::function<void(std::exception_ptr)>,"; + H << nl << "const Ice::Current&)" << isConst << " override;"; + H.restoreIndent(); + + C << sp << nl << "void" << nl << scope << name << "I::" << opName << "Async("; + C.useCurrentPosAsIndent(); + for(ParamDeclList::const_iterator q = inParams.begin(); q != inParams.end(); ++q) + { + C << typeToString((*q)->type(), (*q)->optional(), (*q)->getMetaData(), + _useWstring | TypeContextInParam | TypeContextCpp11); + C << ' ' << fixKwd((*q)->name()) << "," << nl; + } + + C << "std::function<void(" << responseParams << ")> " << opName << "_response,"; + C << nl << "std::function<void(std::exception_ptr)>,"; + C << nl << "const Ice::Current& current)" << isConst; + C.restoreIndent(); + C << sb; + + string result = "r"; + for(ParamDeclList::const_iterator q = params.begin(); q != params.end(); ++q) + { + if((*q)->name() == result) + { + result = "_" + result; + break; + } + } + + C << nl << opName << "_response("; + if(ret) + { + C << defaultValue(ret, op->getMetaData()); + } + for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) + { + if(ret || q != outParams.begin()) + { + C << ", "; + } + C << defaultValue((*q)->type(), op->getMetaData()); + } + C << ");"; + + C << eb; + } + else + { + H << sp << nl << "virtual " << retS << ' ' << fixKwd(opName) << '('; + H.useCurrentPosAsIndent(); + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(q != paramList.begin()) + { + H << ',' << nl; + } + StringList metaData = (*q)->getMetaData(); + string typeString; + if((*q)->isOutParam()) + { + typeString = outputTypeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextCpp11); + } + else + { + typeString = typeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextInParam | TypeContextCpp11); + } + H << typeString; + } + if(!p->isLocal()) + { + if(!paramList.empty()) + { + H << ',' << nl; + } + H << "const Ice::Current&"; + } + H.restoreIndent(); + + string isConst = ((op->mode() == Operation::Nonmutating) || op->hasMetaData("cpp:const")) ? " const" : ""; + + H << ")" << isConst << " override;"; + + C << sp << nl << retS << nl; + C << scope.substr(2) << name << "I::" << fixKwd(opName) << '('; + C.useCurrentPosAsIndent(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(q != paramList.begin()) + { + C << ',' << nl; + } + StringList metaData = (*q)->getMetaData(); + string typeString; + if((*q)->isOutParam()) + { + C << outputTypeToString((*q)->type(), (*q)->optional(), metaData, _useWstring | TypeContextCpp11) + << " " + << fixKwd((*q)->name()); + } + else + { + C << typeToString((*q)->type(), (*q)->optional(), metaData, + _useWstring | TypeContextInParam | TypeContextCpp11) + << " /*" << fixKwd((*q)->name()) << "*/"; + } + } + if(!p->isLocal()) + { + if(!paramList.empty()) + { + C << ',' << nl; + } + C << "const Ice::Current& current"; + } + C.restoreIndent(); + C << ')'; + C << isConst; + C << sb; + + for(ParamDeclList::const_iterator q = outParams.begin(); q != outParams.end(); ++q) + { + C << nl << fixKwd((*q)->name()) << " = " << defaultValue((*q)->type(), op->getMetaData()) << ";"; + } + + if(ret) + { + writeReturn(C, ret, op->getMetaData()); + } + + C << eb; + } + } + + H << eb << ';'; + + _useWstring = resetUseWstring(_useWstringHist); + + return true; +} |