Skip to content

Commit bf3cf4d

Browse files
committed
[CUDA][HIP] warn incompatible redeclare (llvm#77359)
This PR was already merged in trunk: llvm#77359 However, it was reverted in amd-staging due to ck issue ROCm/composable_kernel#1330 Now try relanding it in amd-staging after ck issue fixed by ROCm/composable_kernel#1342 Fixes: SWDEV-431838 Original commit message: nvcc warns about the following code: `void f(); __device__ void f() {}` but clang does not since clang allows device function to overload host function. Users want clang to emit similar warning to help code to be compatible with nvcc. Since this may cause regression with existing code, the warning is off by default and can be enabled by -Wnvcc-compat. It won't cause warning in system headers, even with -Wnvcc-compat. Change-Id: Ia370700eb3eb1b1928d04ec59e2ec63506f85545
1 parent fb72962 commit bf3cf4d

File tree

4 files changed

+60
-16
lines changed

4 files changed

+60
-16
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9067,6 +9067,11 @@ def err_cuda_ovl_target : Error<
90679067
"cannot overload %select{__device__|__global__|__host__|__host__ __device__}2 function %3">;
90689068
def note_cuda_ovl_candidate_target_mismatch : Note<
90699069
"candidate template ignored: target attributes do not match">;
9070+
def warn_offload_incompatible_redeclare : Warning<
9071+
"target-attribute based function overloads are not supported by NVCC and will be treated as a function redeclaration:"
9072+
"new declaration is %select{__device__|__global__|__host__|__host__ __device__}0 function, "
9073+
"old declaration is %select{__device__|__global__|__host__|__host__ __device__}1 function">,
9074+
InGroup<DiagGroup<"nvcc-compat">>, DefaultIgnore;
90709075

90719076
def err_cuda_device_builtin_surftex_cls_template : Error<
90729077
"illegal device builtin %select{surface|texture}0 reference "

clang/lib/Sema/SemaCUDA.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,24 +1018,33 @@ void SemaCUDA::checkTargetOverload(FunctionDecl *NewFD,
10181018
// HD/global functions "exist" in some sense on both the host and device, so
10191019
// should have the same implementation on both sides.
10201020
if (NewTarget != OldTarget &&
1021-
((NewTarget == CUDAFunctionTarget::HostDevice &&
1022-
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1023-
isImplicitHostDeviceFunction(NewFD) &&
1024-
OldTarget == CUDAFunctionTarget::Device)) ||
1025-
(OldTarget == CUDAFunctionTarget::HostDevice &&
1026-
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1027-
isImplicitHostDeviceFunction(OldFD) &&
1028-
NewTarget == CUDAFunctionTarget::Device)) ||
1029-
(NewTarget == CUDAFunctionTarget::Global) ||
1030-
(OldTarget == CUDAFunctionTarget::Global)) &&
10311021
!SemaRef.IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false,
10321022
/* ConsiderCudaAttrs = */ false)) {
1033-
Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
1034-
<< llvm::to_underlying(NewTarget) << NewFD->getDeclName()
1035-
<< llvm::to_underlying(OldTarget) << OldFD;
1036-
Diag(OldFD->getLocation(), diag::note_previous_declaration);
1037-
NewFD->setInvalidDecl();
1038-
break;
1023+
if ((NewTarget == CUDAFunctionTarget::HostDevice &&
1024+
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1025+
isImplicitHostDeviceFunction(NewFD) &&
1026+
OldTarget == CUDAFunctionTarget::Device)) ||
1027+
(OldTarget == CUDAFunctionTarget::HostDevice &&
1028+
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1029+
isImplicitHostDeviceFunction(OldFD) &&
1030+
NewTarget == CUDAFunctionTarget::Device)) ||
1031+
(NewTarget == CUDAFunctionTarget::Global) ||
1032+
(OldTarget == CUDAFunctionTarget::Global)) {
1033+
Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
1034+
<< llvm::to_underlying(NewTarget) << NewFD->getDeclName()
1035+
<< llvm::to_underlying(OldTarget) << OldFD;
1036+
Diag(OldFD->getLocation(), diag::note_previous_declaration);
1037+
NewFD->setInvalidDecl();
1038+
break;
1039+
}
1040+
if ((NewTarget == CUDAFunctionTarget::Host &&
1041+
OldTarget == CUDAFunctionTarget::Device) ||
1042+
(NewTarget == CUDAFunctionTarget::Device &&
1043+
OldTarget == CUDAFunctionTarget::Host)) {
1044+
Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)
1045+
<< llvm::to_underlying(NewTarget) << llvm::to_underlying(OldTarget);
1046+
Diag(OldFD->getLocation(), diag::note_previous_declaration);
1047+
}
10391048
}
10401049
}
10411050
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only \
2+
// RUN: -isystem %S/Inputs -verify %s
3+
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only \
4+
// RUN: -isystem %S/Inputs -fcuda-is-device -verify %s
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only \
6+
// RUN: -isystem %S/Inputs -verify=redecl -Wnvcc-compat %s
7+
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only \
8+
// RUN: -isystem %S/Inputs -fcuda-is-device -Wnvcc-compat -verify=redecl %s
9+
10+
// expected-no-diagnostics
11+
#include "cuda.h"
12+
13+
__device__ void f(); // redecl-note {{previous declaration is here}}
14+
15+
void f() {} // redecl-warning {{target-attribute based function overloads are not supported by NVCC and will be treated as a function redeclaration:new declaration is __host__ function, old declaration is __device__ function}}
16+
17+
void g(); // redecl-note {{previous declaration is here}}
18+
19+
__device__ void g() {} // redecl-warning {{target-attribute based function overloads are not supported by NVCC and will be treated as a function redeclaration:new declaration is __device__ function, old declaration is __host__ function}}

llvm/docs/CompileCudaWithLLVM.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,17 @@ the compiler chooses to inline ``host_only``.
418418
Member functions, including constructors, may be overloaded using H and D
419419
attributes. However, destructors cannot be overloaded.
420420

421+
Clang Warnings for Host and Device Function Declarations
422+
--------------------------------------------------------
423+
424+
Clang can emit warnings when it detects that host (H) and device (D) functions are declared or defined with the same signature. These warnings are not enabled by default.
425+
426+
To enable these warnings, use the following compiler flag:
427+
428+
.. code-block:: console
429+
430+
-Wnvcc-compat
431+
421432
Using a Different Class on Host/Device
422433
--------------------------------------
423434

0 commit comments

Comments
 (0)