Skip to content

Commit 3450a62

Browse files
authored
[CUDA][HIP] warn incompatible redeclare (llvm#77359) (llvm#1260)
2 parents 7aa0aca + 50feef5 commit 3450a62

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
@@ -9056,6 +9056,11 @@ def err_cuda_ovl_target : Error<
90569056
"cannot overload %select{__device__|__global__|__host__|__host__ __device__}2 function %3">;
90579057
def note_cuda_ovl_candidate_target_mismatch : Note<
90589058
"candidate template ignored: target attributes do not match">;
9059+
def warn_offload_incompatible_redeclare : Warning<
9060+
"target-attribute based function overloads are not supported by NVCC and will be treated as a function redeclaration:"
9061+
"new declaration is %select{__device__|__global__|__host__|__host__ __device__}0 function, "
9062+
"old declaration is %select{__device__|__global__|__host__|__host__ __device__}1 function">,
9063+
InGroup<DiagGroup<"nvcc-compat">>, DefaultIgnore;
90599064

90609065
def err_cuda_device_builtin_surftex_cls_template : Error<
90619066
"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)