[clang] 996075d - [clang][Interp] Handle virtual calls with covariant return types (#101218)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 31 00:47:49 PDT 2024
Author: Timm Baeder
Date: 2024-07-31T09:47:45+02:00
New Revision: 996075d68357d15b9bdbbafee002e50563532cb6
URL: https://github.com/llvm/llvm-project/commit/996075d68357d15b9bdbbafee002e50563532cb6
DIFF: https://github.com/llvm/llvm-project/commit/996075d68357d15b9bdbbafee002e50563532cb6.diff
LOG: [clang][Interp] Handle virtual calls with covariant return types (#101218)
Added:
Modified:
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/cxx2a.cpp
Removed:
################################################################################
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');
+}
More information about the cfe-commits
mailing list