
In C++20 constexpr virtual function is allowed. In C++17 although non-pure virtual function is not allowed to be constexpr, pure virtual function is allowed to be constexpr and is allowed to be overriden by non-constexpr virtual function in the derived class. The following code compiles as C++: ``` class A { public: constexpr virtual int f() = 0; }; class B : public A { public: int f() override { return 42; } }; ``` However, it fails to compile as CUDA or HIP code. The reason: A::f() is implicitly host device function whereas B::f() is a host function. Since they have different targets, clang does not treat B::f() as an override of A::f(). Instead, it treats B::f() as a name-hiding non-virtual function for A::f(), and diagnoses it. This causes any CUDA/HIP program using C++ standard header file `<format>` from g++-13 to fail to compile since such usage patten show up there: ``` /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/format:3564:34: error: non-virtual member function marked 'override' hides virtual member function 3564 | _M_format_arg(size_t __id) override | ^ /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/format:3538:30: note: hidden overloaded virtual function 'std::__format::_Scanner<char>::_M_format_arg' declared here 3538 | constexpr virtual void _M_format_arg(size_t __id) = 0; | ^ ``` This is a serious issue and there is no workaround. This patch allows non-constexpr function to override constexpr virtual function for CUDA and HIP. This should be OK since non-constexpr function without explicit host or device attribute can only be called in host functions. Fixes: SWDEV-507350
29 lines
410 B
Plaintext
29 lines
410 B
Plaintext
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only \
|
|
// RUN: -fcuda-is-device %s
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only %s
|
|
|
|
// expected-no-diagnostics
|
|
|
|
#include "Inputs/cuda.h"
|
|
|
|
class A
|
|
{
|
|
public:
|
|
constexpr virtual int f() = 0;
|
|
};
|
|
|
|
class B : public A
|
|
{
|
|
public:
|
|
int f() override
|
|
{
|
|
return 42;
|
|
}
|
|
};
|
|
|
|
int test()
|
|
{
|
|
B b;
|
|
return b.f();
|
|
}
|