blob: cc37837e70791f93d07fda923f8cd19cfb2b019a [file] [log] [blame]
// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify=host
// RUN: %clang_cc1 %s -std=c++20 -fcuda-is-device -fsyntax-only -verify=dev
// host-no-diagnostics
#include "Inputs/cuda.h"
// Virtual dtor ~B() of explicit instantiation B<float> must
// be emitted, which causes host_fun() called.
namespace ExplicitInstantiationExplicitDevDtor {
void host_fun() // dev-note {{'host_fun' declared here}}
{}
template <unsigned>
constexpr void hd_fun() {
host_fun(); // dev-error {{reference to __host__ function 'host_fun' in __host__ __device__ function}}
}
struct A {
constexpr ~A() { // dev-note {{called by '~B'}}
hd_fun<8>(); // dev-note {{called by '~A'}}
}
};
template <typename T>
struct B {
public:
virtual __device__ ~B() = default;
A _a;
};
template class B<float>;
}
// The implicit host/device attrs of virtual dtor ~B() should be
// conservatively inferred, where constexpr member dtor's should
// not be considered device since they may call host functions.
// Therefore B<float>::~B() should not have implicit device attr.
// However C<float>::~C() should have implicit device attr since
// it is trivial.
namespace ExplicitInstantiationDtorNoAttr {
void host_fun()
{}
template <unsigned>
constexpr void hd_fun() {
host_fun();
}
struct A {
constexpr ~A() {
hd_fun<8>();
}
};
template <typename T>
struct B {
public:
virtual ~B() = default;
A _a;
};
template <typename T>
struct C {
public:
virtual ~C() = default;
};
template class B<float>;
template class C<float>;
__device__ void foo() {
C<float> x;
}
}
// Dtors of implicit template class instantiation are not
// conservatively inferred because the invalid usage can
// be diagnosed.
namespace ImplicitInstantiation {
void host_fun() // dev-note {{'host_fun' declared here}}
{}
template <unsigned>
constexpr void hd_fun() {
host_fun(); // dev-error {{reference to __host__ function 'host_fun' in __host__ __device__ function}}
}
struct A {
constexpr ~A() { // dev-note {{called by '~B'}}
hd_fun<8>(); // dev-note {{called by '~A'}}
}
};
template <typename T>
struct B {
public:
~B() = default; // dev-note {{called by 'foo'}}
A _a;
};
__device__ void foo() {
B<float> x;
}
}