From 16b7312e60a560cb255ab560fddb4f906645adfc Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 12 Feb 2010 17:13:23 +0000 Subject: [PATCH] Keep track of whether a final overrider needs a return type adjustment. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95985 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGVtable.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 0904f28d22..360201e088 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -125,7 +125,11 @@ public: /// Method - The method decl of the overrider. const CXXMethodDecl *Method; - OverriderInfo() : Method(0) { } + /// NeedsReturnAdjustment - Whether this overrider needs to adjust its + /// return type. + bool NeedsReturnAdjustment; + + OverriderInfo() : Method(0), NeedsReturnAdjustment(false) { } }; private: @@ -273,9 +277,23 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD, OverriddenMD)]; assert(Overrider.Method && "Did not find existing overrider!"); - assert(!ReturnTypeConversionRequiresAdjustment(Context, NewMD, - OverriddenMD) && - "FIXME: Covariant return types not handled yet!"); + /// We only need to do the return type check if the overrider doesn't + /// already need a return adjustment. Consider: + /// + /// struct A { virtual V1 *f(); } + /// struct B : A { virtual V2 *f(); } + /// struct C : B { virtual V2 *f(); } + /// + /// If we assume that that V2->V1 needs an adjustment, then when we + /// know that since A::f -> B::f needs an adjustment, then all classes + /// that eventually override B::f (and by transitivity A::f) are going to + /// need to have their return types adjusted. + if (!Overrider.NeedsReturnAdjustment) { + Overrider.NeedsReturnAdjustment = + ReturnTypeConversionRequiresAdjustment(Context, NewMD, + OverriddenMD); + } + // Set the new overrider. Overrider.Method = NewMD; @@ -369,7 +387,10 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const { OverriderInfo Overrider = getOverrider(Base, MD); Out << " " << MD->getQualifiedNameAsString() << " - "; - Out << Overrider.Method->getQualifiedNameAsString() << "\n"; + Out << Overrider.Method->getQualifiedNameAsString(); + if (Overrider.NeedsReturnAdjustment) + Out << " [ret-adj]"; + Out << "\n"; } } -- 2.40.0