Commit 12ae2b6e authored by Kenton Varda's avatar Kenton Varda

MSVC: Work around some cases where templates nested in templates trigger compiler bugs.

parent 8d6ca6e0
...@@ -217,6 +217,10 @@ public: ...@@ -217,6 +217,10 @@ public:
needsTypename = false; needsTypename = false;
} }
bool hasDisambiguatedTemplate() {
return hasDisambiguatedTemplate_;
}
void addMemberTemplate(kj::StringPtr innerName, kj::Array<CppTypeName>&& params) { void addMemberTemplate(kj::StringPtr innerName, kj::Array<CppTypeName>&& params) {
// Append "::innerName<params, ...>". // Append "::innerName<params, ...>".
// //
...@@ -224,6 +228,7 @@ public: ...@@ -224,6 +228,7 @@ public:
bool parentIsArgDependent = isArgDependent; bool parentIsArgDependent = isArgDependent;
needsTypename = parentIsArgDependent; needsTypename = parentIsArgDependent;
hasDisambiguatedTemplate_ = hasDisambiguatedTemplate_ || parentIsArgDependent;
name = kj::strTree(kj::mv(name), name = kj::strTree(kj::mv(name),
parentIsArgDependent ? "::template " : "::", parentIsArgDependent ? "::template " : "::",
...@@ -231,6 +236,7 @@ public: ...@@ -231,6 +236,7 @@ public:
kj::StringTree(KJ_MAP(p, params) { kj::StringTree(KJ_MAP(p, params) {
if (p.isArgDependent) isArgDependent = true; if (p.isArgDependent) isArgDependent = true;
if (p.hasInterfaces_) hasInterfaces_ = true; if (p.hasInterfaces_) hasInterfaces_ = true;
if (p.hasDisambiguatedTemplate_) hasDisambiguatedTemplate_ = true;
return kj::strTree(kj::mv(p)); return kj::strTree(kj::mv(p));
}, ", "), }, ", "),
'>'); '>');
...@@ -257,9 +263,15 @@ private: ...@@ -257,9 +263,15 @@ private:
// Does this type name refer to any interface types? If so it may need to be #ifdefed out in // Does this type name refer to any interface types? If so it may need to be #ifdefed out in
// lite mode. // lite mode.
bool hasDisambiguatedTemplate_;
// Whether the type name contains a template type that had to be disambiguated using the
// "template" keyword, e.g. "Foo<T>::template Bar<U>".
//
// TODO(msvc): We only track this because MSVC seems to get confused by it in some weird cases.
inline CppTypeName(kj::StringTree&& name, bool isArgDependent) inline CppTypeName(kj::StringTree&& name, bool isArgDependent)
: name(kj::mv(name)), isArgDependent(isArgDependent), needsTypename(false), : name(kj::mv(name)), isArgDependent(isArgDependent), needsTypename(false),
hasInterfaces_(false) {} hasInterfaces_(false), hasDisambiguatedTemplate_(false) {}
friend kj::StringTree KJ_STRINGIFY(CppTypeName&& typeName); friend kj::StringTree KJ_STRINGIFY(CppTypeName&& typeName);
friend kj::String KJ_STRINGIFY(const CppTypeName& typeName); friend kj::String KJ_STRINGIFY(const CppTypeName& typeName);
...@@ -360,7 +372,11 @@ private: ...@@ -360,7 +372,11 @@ private:
if (params.size() > 0) { if (params.size() > 0) {
auto args = brand.getBrandArgumentsAtScope(node.getId()); auto args = brand.getBrandArgumentsAtScope(node.getId());
#if 0
// Figure out exactly how many params are not bound to AnyPointer. // Figure out exactly how many params are not bound to AnyPointer.
// TODO(msvc): In a few obscure cases, MSVC does not like empty template pramater lists,
// even if all parameters have defaults. So, we give in and explicitly list all
// parameters in our generated code for now. Try again later.
uint paramCount = 0; uint paramCount = 0;
for (uint i: kj::indices(params)) { for (uint i: kj::indices(params)) {
auto arg = args[i]; auto arg = args[i];
...@@ -369,6 +385,9 @@ private: ...@@ -369,6 +385,9 @@ private:
paramCount = i + 1; paramCount = i + 1;
} }
} }
#else
uint paramCount = params.size();
#endif
result.addMemberTemplate(unqualifiedName, result.addMemberTemplate(unqualifiedName,
KJ_MAP(i, kj::range(0u, paramCount)) { KJ_MAP(i, kj::range(0u, paramCount)) {
...@@ -1600,12 +1619,16 @@ private: ...@@ -1600,12 +1619,16 @@ private:
" ::capnp::_::PointerHelpers<", type, ">::adopt(\n" " ::capnp::_::PointerHelpers<", type, ">::adopt(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS), kj::mv(value));\n" " _builder.getPointerField(", offset, " * ::capnp::POINTERS), kj::mv(value));\n"
"}\n", "}\n",
COND(type.hasDisambiguatedTemplate(),
"#if !_MSC_VER\n"
"// Excluded under MSVC because bugs may make it unable to compile this method.\n"),
templateContext.allDecls(), templateContext.allDecls(),
"inline ::capnp::Orphan<", type, "> ", scope, "Builder::disown", titleCase, "() {\n", "inline ::capnp::Orphan<", type, "> ", scope, "Builder::disown", titleCase, "() {\n",
unionDiscrim.check, unionDiscrim.check,
" return ::capnp::_::PointerHelpers<", type, ">::disown(\n" " return ::capnp::_::PointerHelpers<", type, ">::disown(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS));\n" " _builder.getPointerField(", offset, " * ::capnp::POINTERS));\n"
"}\n", "}\n",
COND(type.hasDisambiguatedTemplate(), "#endif // !_MSC_VER\n"),
COND(shouldExcludeInLiteMode, "#endif // !CAPNP_LITE\n"), COND(shouldExcludeInLiteMode, "#endif // !CAPNP_LITE\n"),
"\n") "\n")
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment