Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

id<1> overloaded operator '*' is ambiguous #40

Open
Pennycook opened this issue Feb 3, 2025 · 4 comments
Open

id<1> overloaded operator '*' is ambiguous #40

Pennycook opened this issue Feb 3, 2025 · 4 comments

Comments

@Pennycook
Copy link

The following code fails to compile with SimSYCL:

#include <sycl/sycl.hpp>

int foo(sycl::id<1> i, int j)
{
    return i * j;
}

I think this should work, because SYCL 2020 defines an implicit conversion of id<1> to size_t.

The error message is impressively long, but points to an ambiguous overload of *:

test.cpp:5:14: error: use of overloaded operator '*' is ambiguous (with operand types 'sycl::id<1>' and 'int')
    5 |     return i * j;
      |            ~ ^ ~
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:59:5: note: candidate function
   59 |     SIMSYCL_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(*)
      |     ^
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:51:32: note: expanded from macro 'SIMSYCL_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR'
   51 |     friend constexpr Interface operator op(const Interface &lhs, const size_t &rhs) {                                  \
      |                                ^
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:59:5: note: candidate function
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:46:32: note: expanded from macro 'SIMSYCL_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR'
   46 |     friend constexpr Interface operator op(const Interface &lhs, const Interface &rhs) {                               \
      |                                ^
test.cpp:5:14: note: built-in candidate operator*(unsigned long, int)
    5 |     return i * j;
      |              ^
test.cpp:5:14: note: built-in candidate operator*(unsigned long, float)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, double)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, long double)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, __float128)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long, unsigned __int128)
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:108:5: note: candidate function
  108 |     SIMSYCL_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(*)
      |     ^
/usr/local/include/sycl/../simsycl/sycl/../detail/coordinate.hh:100:32: note: expanded from macro 'SIMSYCL_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR'
  100 |     friend constexpr Interface operator op(const size_t &lhs, const Interface &rhs) {                                  \
      |                                ^
test.cpp:5:14: note: built-in candidate operator*(float, int)
    5 |     return i * j;
      |              ^
test.cpp:5:14: note: built-in candidate operator*(double, int)
test.cpp:5:14: note: built-in candidate operator*(long double, int)
test.cpp:5:14: note: built-in candidate operator*(__float128, int)
test.cpp:5:14: note: built-in candidate operator*(int, int)
test.cpp:5:14: note: built-in candidate operator*(long, int)
test.cpp:5:14: note: built-in candidate operator*(long long, int)
test.cpp:5:14: note: built-in candidate operator*(__int128, int)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, int)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, int)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, int)
test.cpp:5:14: note: built-in candidate operator*(float, float)
test.cpp:5:14: note: built-in candidate operator*(float, double)
test.cpp:5:14: note: built-in candidate operator*(float, long double)
test.cpp:5:14: note: built-in candidate operator*(float, __float128)
test.cpp:5:14: note: built-in candidate operator*(float, long)
test.cpp:5:14: note: built-in candidate operator*(float, long long)
test.cpp:5:14: note: built-in candidate operator*(float, __int128)
test.cpp:5:14: note: built-in candidate operator*(float, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(float, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(float, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(float, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(double, float)
test.cpp:5:14: note: built-in candidate operator*(double, double)
test.cpp:5:14: note: built-in candidate operator*(double, long double)
test.cpp:5:14: note: built-in candidate operator*(double, __float128)
test.cpp:5:14: note: built-in candidate operator*(double, long)
test.cpp:5:14: note: built-in candidate operator*(double, long long)
test.cpp:5:14: note: built-in candidate operator*(double, __int128)
test.cpp:5:14: note: built-in candidate operator*(double, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(double, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(double, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(double, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(long double, float)
test.cpp:5:14: note: built-in candidate operator*(long double, double)
test.cpp:5:14: note: built-in candidate operator*(long double, long double)
test.cpp:5:14: note: built-in candidate operator*(long double, __float128)
test.cpp:5:14: note: built-in candidate operator*(long double, long)
test.cpp:5:14: note: built-in candidate operator*(long double, long long)
test.cpp:5:14: note: built-in candidate operator*(long double, __int128)
test.cpp:5:14: note: built-in candidate operator*(long double, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(long double, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(long double, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(long double, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(__float128, float)
test.cpp:5:14: note: built-in candidate operator*(__float128, double)
test.cpp:5:14: note: built-in candidate operator*(__float128, long double)
test.cpp:5:14: note: built-in candidate operator*(__float128, __float128)
test.cpp:5:14: note: built-in candidate operator*(__float128, long)
test.cpp:5:14: note: built-in candidate operator*(__float128, long long)
test.cpp:5:14: note: built-in candidate operator*(__float128, __int128)
test.cpp:5:14: note: built-in candidate operator*(__float128, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(__float128, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(__float128, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(__float128, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(int, float)
test.cpp:5:14: note: built-in candidate operator*(int, double)
test.cpp:5:14: note: built-in candidate operator*(int, long double)
test.cpp:5:14: note: built-in candidate operator*(int, __float128)
test.cpp:5:14: note: built-in candidate operator*(int, long)
test.cpp:5:14: note: built-in candidate operator*(int, long long)
test.cpp:5:14: note: built-in candidate operator*(int, __int128)
test.cpp:5:14: note: built-in candidate operator*(int, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(int, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(int, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(int, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(long, float)
test.cpp:5:14: note: built-in candidate operator*(long, double)
test.cpp:5:14: note: built-in candidate operator*(long, long double)
test.cpp:5:14: note: built-in candidate operator*(long, __float128)
test.cpp:5:14: note: built-in candidate operator*(long, long)
test.cpp:5:14: note: built-in candidate operator*(long, long long)
test.cpp:5:14: note: built-in candidate operator*(long, __int128)
test.cpp:5:14: note: built-in candidate operator*(long, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(long, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(long, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(long, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(long long, float)
test.cpp:5:14: note: built-in candidate operator*(long long, double)
test.cpp:5:14: note: built-in candidate operator*(long long, long double)
test.cpp:5:14: note: built-in candidate operator*(long long, __float128)
test.cpp:5:14: note: built-in candidate operator*(long long, long)
test.cpp:5:14: note: built-in candidate operator*(long long, long long)
test.cpp:5:14: note: built-in candidate operator*(long long, __int128)
test.cpp:5:14: note: built-in candidate operator*(long long, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(long long, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(long long, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(long long, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(__int128, float)
test.cpp:5:14: note: built-in candidate operator*(__int128, double)
test.cpp:5:14: note: built-in candidate operator*(__int128, long double)
test.cpp:5:14: note: built-in candidate operator*(__int128, __float128)
test.cpp:5:14: note: built-in candidate operator*(__int128, long)
test.cpp:5:14: note: built-in candidate operator*(__int128, long long)
test.cpp:5:14: note: built-in candidate operator*(__int128, __int128)
test.cpp:5:14: note: built-in candidate operator*(__int128, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(__int128, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(__int128, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(__int128, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, float)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, double)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, long double)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, __float128)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, long)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned int, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, float)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, double)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, long double)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, __float128)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned long long, unsigned __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, float)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, double)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, long double)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, __float128)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, long)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, __int128)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, unsigned int)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, unsigned long)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, unsigned long long)
test.cpp:5:14: note: built-in candidate operator*(unsigned __int128, unsigned __int128)
1 error generated.
@fknorr
Copy link
Collaborator

fknorr commented Feb 3, 2025

I believe this is correctly diagnosed, because there also exists an implicit conversion constructor from size_t to id<1>. The compiler could either convert the LHS id<1> to size_t and call built-in operator*(size_t, int) or convert the RHS int to size_t and call friend operator*(id<1>, size_t). To my understanding both these paths have equal weight because they require one implicit argument conversion each. Making j a size_t should solve the problem.

@Pennycook
Copy link
Author

This code compiles with DPC++. Maybe we need a Khronos issue to determine which behavior is desired?

@fknorr
Copy link
Collaborator

fknorr commented Feb 3, 2025

DPC++ has an explicit workaround for this ambiguity. I'm pretty sure the spec doesn't disallow this, but I also could not find any wording that requires it. I agree this needs clarification, the disambiguating overloads seem like a good idea to me.

@Pennycook
Copy link
Author

I've opened KhronosGroup/SYCL-Docs#711 to discuss this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants