From: John McCall Date: Fri, 12 Feb 2010 06:15:07 +0000 (+0000) Subject: Fix a bug causing an assertion when a covariant return type differed from X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=96058953c72355efb266abe8e333db4f5715dbd2;p=clang Fix a bug causing an assertion when a covariant return type differed from an overriden type only by reduced qualification. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95968 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 1c5384767e..e2ea4736d3 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -64,8 +64,8 @@ static bool TypeConversionRequiresAdjustment(ASTContext &Ctx, QualType DerivedType, QualType BaseType) { // Canonicalize the types. - QualType CanDerivedType = Ctx.getCanonicalType(DerivedType); - QualType CanBaseType = Ctx.getCanonicalType(BaseType); + CanQualType CanDerivedType = Ctx.getCanonicalType(DerivedType); + CanQualType CanBaseType = Ctx.getCanonicalType(BaseType); assert(CanDerivedType->getTypeClass() == CanBaseType->getTypeClass() && "Types must have same type class!"); @@ -75,26 +75,29 @@ TypeConversionRequiresAdjustment(ASTContext &Ctx, return false; } - if (const ReferenceType *RT = CanDerivedType->getAs()) { - CanDerivedType = RT->getPointeeType(); + if (isa(CanDerivedType)) { + CanDerivedType = CanDerivedType->getAs()->getPointeeType(); CanBaseType = CanBaseType->getAs()->getPointeeType(); - } else if (const PointerType *PT = CanDerivedType->getAs()) { - CanDerivedType = PT->getPointeeType(); + } else if (isa(CanDerivedType)) { + CanDerivedType = CanDerivedType->getAs()->getPointeeType(); CanBaseType = CanBaseType->getAs()->getPointeeType(); } else { assert(false && "Unexpected return type!"); } - if (CanDerivedType == CanBaseType) { + // We need to compare unqualified types here; consider + // const T *Base::foo(); + // T *Derived::foo(); + if (CanDerivedType.getUnqualifiedType() == CanBaseType.getUnqualifiedType()) { // No adjustment needed. return false; } const CXXRecordDecl *DerivedDecl = - cast(CanDerivedType->getAs()->getDecl()); + cast(cast(CanDerivedType)->getDecl()); const CXXRecordDecl *BaseDecl = - cast(CanBaseType->getAs()->getDecl()); + cast(cast(CanBaseType)->getDecl()); return TypeConversionRequiresAdjustment(Ctx, DerivedDecl, BaseDecl); } diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index f7db2135d2..6cc1b0b691 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -113,3 +113,13 @@ struct D : B { void D::f() { } } + +// For now, just verify this doesn't crash. +namespace test0 { + struct Obj {}; + + struct Base { virtual const Obj *foo() = 0; }; + struct Derived : Base { virtual Obj *foo() { return new Obj(); } }; + + void test(Derived *D) { D->foo(); } +}