diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 93915e5db7d13..6a3da7f38d975 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7589701fb81de..3be9ade80f1d9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1309,6 +1309,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } +template static bool hasExplicitAttr(const FunctionDecl *D) { + assert(D && "function decl should not be null"); + if (auto *A = D->getAttr()) + return !A->isImplicit(); + return false; +} + static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, FunctionDecl *Old, bool UseMemberUsingDeclRules, @@ -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.) @@ -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(Old) && + !hasExplicitAttr(Old) && + !hasExplicitAttr(New) && + !hasExplicitAttr(New)) { + return false; + } return true; + } } } } diff --git a/clang/test/SemaCUDA/constexpr-virtual-func.cu b/clang/test/SemaCUDA/constexpr-virtual-func.cu new file mode 100644 index 0000000000000..89d909181cd94 --- /dev/null +++ b/clang/test/SemaCUDA/constexpr-virtual-func.cu @@ -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(); +}