https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/101218
>From 78961fbfbd791844b1622aa305664199e3451260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Tue, 30 Jul 2024 20:11:37 +0200 Subject: [PATCH] [clang][Interp] Handle virtual calls with covariant return types --- clang/lib/AST/Interp/Interp.h | 24 +++++++++++++++++++++++- clang/test/AST/Interp/cxx2a.cpp | 21 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index d128988a480e1..63e9966b831db 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2628,7 +2628,29 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, } } - return Call(S, OpPC, Func, VarArgSize); + if (!Call(S, OpPC, Func, VarArgSize)) + return false; + + // Covariant return types. The return type of Overrider is a pointer + // or reference to a class type. + if (Overrider != InitialFunction && + Overrider->getReturnType()->isPointerOrReferenceType() && + InitialFunction->getReturnType()->isPointerOrReferenceType()) { + QualType OverriderPointeeType = + Overrider->getReturnType()->getPointeeType(); + QualType InitialPointeeType = + InitialFunction->getReturnType()->getPointeeType(); + // We've called Overrider above, but calling code expects us to return what + // InitialFunction returned. According to the rules for covariant return + // types, what InitialFunction returns needs to be a base class of what + // Overrider returns. So, we need to do an upcast here. + unsigned Offset = S.getContext().collectBaseOffset( + InitialPointeeType->getAsRecordDecl(), + OverriderPointeeType->getAsRecordDecl()); + return GetPtrBasePop(S, OpPC, Offset); + } + + return true; } inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func, diff --git a/clang/test/AST/Interp/cxx2a.cpp b/clang/test/AST/Interp/cxx2a.cpp index 27d1aa1a27f75..ad021b30cfd3c 100644 --- a/clang/test/AST/Interp/cxx2a.cpp +++ b/clang/test/AST/Interp/cxx2a.cpp @@ -13,3 +13,24 @@ consteval int aConstevalFunction() { // both-error {{consteval function never pr return 0; } /// We're NOT calling the above function. The diagnostics should appear anyway. + +namespace Covariant { + struct A { + virtual constexpr char f() const { return 'Z'; } + char a = f(); + }; + + struct D : A {}; + struct Covariant1 { + D d; + virtual const A *f() const; + }; + + struct Covariant3 : Covariant1 { + constexpr virtual const D *f() const { return &this->d; } + }; + + constexpr Covariant3 cb; + constexpr const Covariant1 *cb1 = &cb; + static_assert(cb1->f()->a == 'Z'); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits