Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,7 @@ RISC-V Support

CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed a bug about overriding a constexpr pure-virtual member function with a non-constexpr virtual member function which causes compilation failure when including standard C++ header `format`.

CUDA Support
^^^^^^^^^^^^
Expand Down
21 changes: 20 additions & 1 deletion clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
return Ovl_Overload;
}

template <typename AttrT> static bool hasExplicitAttr(const FunctionDecl *D) {
assert(D && "function decl should not be null");
if (auto *A = D->getAttr<AttrT>())
return !A->isImplicit();
return false;
}

static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
FunctionDecl *Old,
bool UseMemberUsingDeclRules,
Expand Down Expand Up @@ -1583,6 +1590,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
return true;
}

// At this point, it is known that the two functions have the same signature.
if (SemaRef.getLangOpts().CUDA && ConsiderCudaAttrs) {
// Don't allow overloading of destructors. (In theory we could, but it
// would be a giant change to clang.)
Expand All @@ -1595,8 +1603,19 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,

// Allow overloading of functions with same signature and different CUDA
// target attributes.
if (NewTarget != OldTarget)
if (NewTarget != OldTarget) {
// Special case: non-constexpr function is allowed to override
// constexpr virtual function
if (OldMethod && NewMethod && OldMethod->isVirtual() &&
OldMethod->isConstexpr() && !NewMethod->isConstexpr() &&
!hasExplicitAttr<CUDAHostAttr>(Old) &&
!hasExplicitAttr<CUDADeviceAttr>(Old) &&
!hasExplicitAttr<CUDAHostAttr>(New) &&
!hasExplicitAttr<CUDADeviceAttr>(New)) {
return false;
}
return true;
}
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions clang/test/SemaCUDA/constexpr-virtual-func.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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();
}
Loading