Skip to content

Commit

Permalink
Fix overloads coming from overridable interfaces
Browse files Browse the repository at this point in the history
Fixes #1457
  • Loading branch information
sylveon committed Nov 23, 2024
1 parent fa079fb commit ca44055
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 6 deletions.
16 changes: 10 additions & 6 deletions cppwinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2150,6 +2150,10 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable<T, D, %>
w.write("\n friend impl::consume_t<D, %>;", name);
w.write("\n friend impl::require_one<D, %>;", name);
}
else if (info.overridable)
{
w.write("\n friend impl::produce<D, %>;", name);
}
}
}

Expand Down Expand Up @@ -2275,13 +2279,13 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable<T, D, %>

static void write_class_override_usings(writer& w, get_interfaces_t const& required_interfaces)
{
std::map<std::string_view, std::set<std::string>> method_usage;
std::map<std::string_view, std::map<std::string, interface_info>> method_usage;

for (auto&& [interface_name, info] : required_interfaces)
for (auto&& interface_desc : required_interfaces)
{
for (auto&& method : info.type.MethodList())
for (auto&& method : interface_desc.second.type.MethodList())
{
method_usage[get_name(method)].insert(interface_name);
method_usage[get_name(method)].insert(interface_desc);
}
}

Expand All @@ -2292,9 +2296,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable<T, D, %>
continue;
}

for (auto&& interface_name : interfaces)
for (auto&& [interface_name, info] : interfaces)
{
w.write(" using impl::consume_t<D, %>::%;\n",
w.write(info.overridable ? " using %T<D>::%;\n" : " using impl::consume_t<D, %>::%;\n",
interface_name,
method_name);
}
Expand Down
23 changes: 23 additions & 0 deletions test/test_component/OverloadClass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "pch.h"
#include "OverloadClass.h"
#include "OverloadClass.g.cpp"

namespace winrt::test_component::implementation
{
void OverloadClass::Overload()
{
throw hresult_not_implemented();
}
void OverloadClass::Overload(int a)
{
throw hresult_not_implemented();
}
void OverloadClass::Overload(int a, int b)
{
throw hresult_not_implemented();
}
void OverloadClass::Overload(int a, int b, int c)
{
throw hresult_not_implemented();
}
}
21 changes: 21 additions & 0 deletions test/test_component/OverloadClass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "OverloadClass.g.h"

namespace winrt::test_component::implementation
{
struct OverloadClass : OverloadClassT<OverloadClass>
{
OverloadClass() = default;

void Overload();
void Overload(int a);
void Overload(int a, int b);
void Overload(int a, int b, int c);
};
}
namespace winrt::test_component::factory_implementation
{
struct OverloadClass : OverloadClassT<OverloadClass, implementation::OverloadClass>
{
};
}
47 changes: 47 additions & 0 deletions test/test_component/test_component.idl
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,51 @@ namespace test_component

delegate void Delegate();
}

[exclusiveto(test_component.OverloadClass)]
[version(1), uuid(EF902013-00F3-4549-9032-49E86D536C07)]
interface IOverloadClass : IInspectable
{
HRESULT Overload();
}

[exclusiveto(test_component.OverloadClass)]
[version(1), uuid(DFDFFB61-EA72-4977-B1A7-3F0D2C32BB58)]
interface IOverloadClassFactory : IInspectable
{
HRESULT CreateInstance([in] IInspectable* baseInterface, [out] IInspectable** innerInterface, [out][retval] test_component.OverloadClass** value);
}

[exclusiveto(test_component.OverloadClass)]
[version(1), uuid(32510F72-9229-4C69-95BD-DE7B8189C85C)]
interface IOverloadClassOverrides : IInspectable
{
[overload("Overload")] HRESULT OverloadWithOne(int a);
}

[exclusiveto(test_component.OverloadClass)]
[version(1), uuid(50205BCE-FAD3-4C66-801F-17AAD007B26C)]
interface IOverloadClassOverrides2 : IInspectable
{
[overload("Overload")] HRESULT OverloadWithTwo(int a, int b);
}

[exclusiveto(test_component.OverloadClass)]
[version(1), uuid(6EDD1A3F-2616-45B7-9731-F84DA9CCECA1)]
interface IOverloadClassProtected : IInspectable
{
[overload("Overload")] HRESULT OverloadWithThree(int a, int b, int c);
}

[composable(test_component.IOverloadClassFactory, public, 1)]
[marshaling_behavior(agile)]
[threading(both)]
[version(1)]
runtimeclass OverloadClass
{
[default] interface test_component.IOverloadClass;
[protected] interface test_component.IOverloadClassProtected;
[overridable] interface test_component.IOverloadClassOverrides;
[overridable] interface test_component.IOverloadClassOverrides2;
}
}
3 changes: 3 additions & 0 deletions test/test_component/test_component.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@
<ClCompile Include="Generated Files\module.g.cpp" />
<ClCompile Include="module.cpp" />
<ClCompile Include="Optional.cpp" />
<ClCompile Include="OverloadClass.cpp" />
<ClCompile Include="test_overload.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
Expand All @@ -397,6 +399,7 @@
<ItemGroup>
<ClInclude Include="Class.h" />
<ClInclude Include="Optional.h" />
<ClInclude Include="OverloadClass.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="Simple.h" />
<ClInclude Include="Velocity.Class1.h" />
Expand Down
19 changes: 19 additions & 0 deletions test/test_component/test_overload.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "pch.h"
#include "winrt/test_component.h"

// Simple compile-only test to validate overloads coming from overridable interfaces compile.

using namespace winrt;
using namespace test_component;

struct DerivedClass : OverloadClassT<DerivedClass>
{
void Foo()
{
// make sure we can actually call the overloads (no ambiguous call errors)
Overload();
Overload(1);
Overload(1, 2);
Overload(1, 2, 3);
}
};

0 comments on commit ca44055

Please sign in to comment.