================
@@ -0,0 +1,261 @@
+// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify=expected,dev %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x hip -fcuda-is-device -fsyntax-only -verify=expected,dev 
%s
+// RUN: %clang_cc1 -x hip -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+namespace std {
+class type_info {};
+} // namespace std
+
+struct B {
+  __host__ __device__ virtual ~B() {}
+};
+struct D : B {};
+
+void host(B *b) {
+  (void)dynamic_cast<D *>(b);
+  (void)typeid(*b);
+}
+
+__host__ void explicit_host(B *b) {
+  (void)dynamic_cast<D *>(b);
+  (void)typeid(*b);
+}
+
+__device__ void device(B *b, D *d) {
+  (void)dynamic_cast<D *>(b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  (void)dynamic_cast<D &>(*b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  (void)typeid(D);
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+  (void)typeid(*b);
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+  (void)sizeof(typeid(int));
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+  (void)sizeof(dynamic_cast<D *>(b));
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  decltype(dynamic_cast<D *>(b)) ptr = d;
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  (void)ptr;
+
+  // As with -fno-rtti, these don't use RTTI and are allowed.
+  (void)dynamic_cast<void *>(b);
+  (void)dynamic_cast<B *>(d);
+}
+
+__global__ void kernel(B *b) {
+  (void)dynamic_cast<D *>(b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __global__ function as 
RTTI is not available in device code}}
+  (void)typeid(*b);
+  // expected-error@-1 {{cannot use 'typeid' in __global__ function as RTTI is 
not available in device code}}
+}
+
+struct S {
+  __device__ D *member(B *b) { return dynamic_cast<D *>(b); }
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+};
+
+// A __device__ lambda is device code, and an unannotated lambda is
+// __host__ __device__, so it is device code when called from device code.
+__device__ void lambdas(B *b) {
+  auto dev = [] __device__ (B *p) { return dynamic_cast<D *>(p); };
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  auto hd = [](B *p) { return dynamic_cast<D *>(p); };
+  // dev-error@-1 {{cannot use 'dynamic_cast' in __host__ __device__ function 
as RTTI is not available in device code}}
+  dev(b);
+  hd(b);
+  // dev-note@-1 {{called by 'lambdas'}}
+}
+
+// Check that it's an error to use RTTI from a __host__ __device__ function if
+// and only if it's codegen'ed for device.
+
+__host__ __device__ void hd1(B *b) {
+  (void)dynamic_cast<D *>(b);
+  // dev-error@-1 {{cannot use 'dynamic_cast' in __host__ __device__ function 
as RTTI is not available in device code}}
+}
+
+// No error, never instantiated on device.
+inline __host__ __device__ void hd2(B *b) { (void)typeid(*b); }
+void call_hd2(B *b) { hd2(b); }
+
+// Error, instantiated on device.
+inline __host__ __device__ void hd3(B *b) {
+  (void)typeid(*b);
+  // dev-error@-1 {{cannot use 'typeid' in __host__ __device__ function as 
RTTI is not available in device code}}
+}
+__device__ void call_hd3(B *b) { hd3(b); }
+// dev-note@-1 {{called by 'call_hd3'}}
+
+// Templates are checked when they are instantiated.
+template <class T> __device__ T *tmpl_unused(B *b) {
+  return dynamic_cast<T *>(b);
+}
+
+template <class T> __device__ T *tmpl(B *b) {
+  return dynamic_cast<T *>(b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+}
+__device__ void call_tmpl(B *b) { tmpl<D>(b); }
+// expected-note@-1 {{in instantiation of function template specialization 
'tmpl<D>' requested here}}
+
+template <class T> __device__ void tmpl_typeid(T *t) {
+  (void)typeid(*t);
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+}
+__device__ void call_tmpl_typeid(B *b) { tmpl_typeid(b); }
+// expected-note@-1 {{in instantiation of function template specialization 
'tmpl_typeid<B>' requested here}}
+
+template <class T> __device__ void tmpl_typeid_unused(T *t) {
+  (void)typeid(*t);
+}
+
+// A non-dependent operand is checked once, in the template definition.
+template <class T> __device__ void tmpl_nondependent() {
+  (void)typeid(int);
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+}
+__device__ void call_tmpl_nondependent() { tmpl_nondependent<int>(); }
+
+template <class T> __device__ T *explicit_inst(B *b) {
+  return dynamic_cast<T *>(b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+}
+template __device__ D *explicit_inst<D>(B *);
+// expected-note@-1 {{in instantiation of function template specialization 
'explicit_inst<D>' requested here}}
+
+template <class T> __global__ void kernel_tmpl(B *b) {
+  (void)typeid(*static_cast<T *>(b));
+  // expected-error@-1 {{cannot use 'typeid' in __global__ function as RTTI is 
not available in device code}}
+}
+template __global__ void kernel_tmpl<D>(B *);
+// expected-note@-1 {{in instantiation of function template specialization 
'kernel_tmpl<D>' requested here}}
+
+// A host virtual function in a class that also has device virtual functions
+// is not device code.
+struct Fix {
+  __device__ virtual void run() {}
+  virtual D *init(B *b) { return dynamic_cast<D *>(b); }
+};
+__device__ void use_fix() { Fix f; f.run(); }
+
+// Outside a function, the initializer of a device variable is device code.
+__device__ const std::type_info *device_var = &typeid(int);
+// expected-error@-1 {{cannot use 'typeid' in the initializer of a device 
variable as RTTI is not available in device code}}
+__constant__ const std::type_info *constant_var = &typeid(int);
+// expected-error@-1 {{cannot use 'typeid' in the initializer of a device 
variable as RTTI is not available in device code}}
+const std::type_info *host_var = &typeid(int);
+
+// A default member initializer is checked where it is used.
+struct MemberInit { // #member_init_struct
+  const std::type_info *t = &typeid(int); // #member_init
+};
+// expected-error@#member_init {{cannot use 'typeid' in __device__ function as 
RTTI is not available in device code}}
+// dev-error@#member_init {{cannot use 'typeid' in __host__ __device__ 
function as RTTI is not available in device code}}
+// dev-note@#member_init_struct {{default member initializer used here}}
+
+__device__ void member_init_ctor() {
+  MemberInit m;
+  // dev-note@-1 {{called by 'member_init_ctor'}}
+  (void)m;
+}
+__device__ void member_init_aggregate() {
+  MemberInit m{};
+  // expected-note@-1 {{default member initializer used here}}
+  (void)m;
+}
+void member_init_host() {
+  MemberInit m;
+  MemberInit n{};
+  (void)m;
+  (void)n;
+}
+
+struct MemberInitDeviceCtor {
+  B *b = nullptr;
+  D *d = dynamic_cast<D *>(b);
+  // expected-error@-1 {{cannot use 'dynamic_cast' in __device__ function as 
RTTI is not available in device code}}
+  __device__ MemberInitDeviceCtor() {}
+  // expected-note@-1 {{default member initializer used here}}
+};
+
+// No error, the constructor is never used on device.
+struct MemberInitHDCtor {
+  const std::type_info *t = &typeid(int);
+  __host__ __device__ MemberInitHDCtor() {}
+};
+void member_init_hd_ctor_host() { MemberInitHDCtor m; }
+
+template <class T> struct MemberInitTmpl { // #member_init_tmpl
+  const std::type_info *t = &typeid(T);
+  // dev-error@-1 {{cannot use 'typeid' in __host__ __device__ function as 
RTTI is not available in device code}}
+};
+// dev-note@#member_init_tmpl {{default member initializer used here}}
+__device__ void member_init_tmpl() {
+  MemberInitTmpl<int> m;
+  // dev-note@-1 {{called by 'member_init_tmpl'}}
+  (void)m;
+}
+
+// A default argument is checked where it is used.
+__device__ void default_arg(const std::type_info *t = &typeid(int)); // 
#default_arg
+// expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+__device__ void use_default_arg() {
+  default_arg();
+  // expected-note@-1 {{default argument used here}}
+}
+
+inline __host__ __device__ void hd_default_arg(const std::type_info *t = 
&typeid(int)) {}
+// expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+void use_hd_default_arg_host() { hd_default_arg(); }
+__device__ void use_hd_default_arg_device() {
+  hd_default_arg();
+  // expected-note@-1 {{default argument used here}}
+}
+
+// Diagnosed once, at the use, although the default argument is parsed in a
+// __device__ function.
+__device__ void local_default_arg() {
+  __device__ void local(const std::type_info *t = &typeid(int));
+  // expected-error@-1 {{cannot use 'typeid' in __device__ function as RTTI is 
not available in device code}}
+  local();
+  // expected-note@-1 {{default argument used here}}
+}
+
+// A default argument used in a default member initializer.
+struct NestedDefaultArg { // #nested_struct
+  const std::type_info *t = (default_arg(), nullptr);
+};
+// dev-error@#default_arg {{cannot use 'typeid' in __host__ __device__ 
function as RTTI is not available in device code}}
+// dev-note@#nested_struct {{default member initializer used here}}
+__device__ void nested_default_arg() {
+  NestedDefaultArg n;
+  // dev-note@-1 {{called by 'nested_default_arg'}}
+  (void)n;
+}
+
+// A lambda body is checked as a function of its own, while the initializer of
+// a capture is part of the default member initializer.
+struct LambdaBody {
+  const std::type_info *t = [] { return &typeid(int); }(); // #lambda_body
+};
+// dev-error@#lambda_body {{cannot use 'typeid' in __host__ __device__ 
function as RTTI is not available in device code}}
+// dev-note@#lambda_body {{called by 'lambda_body'}}
+__device__ void lambda_body() {
+  LambdaBody l;
+  (void)l;
+}
+
+struct LambdaCapture { // #lambda_capture_struct
+  const std::type_info *t = [p = &typeid(int)] { return p; }();
+  // dev-error@-1 {{cannot use 'typeid' in __host__ __device__ function as 
RTTI is not available in device code}}
+};
+// dev-note@#lambda_capture_struct {{default member initializer used here}}
+__device__ void lambda_capture() {
+  LambdaCapture l;
+  // dev-note@-1 {{called by 'lambda_capture'}}
+  (void)l;
+}
----------------
steffenlarsen wrote:

Added!

https://github.com/llvm/llvm-project/pull/228469
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to