From f2a04bf1689cd88dd04012c311ba86e9d8b2b1b2 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 22 Jan 2010 17:37:20 +0000 Subject: [PATCH] No need to canonicalize the type and use dyn_cast. Also, correctly diagnose trying to override a function returning an lvalue reference with a function overriding an rvalue reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94183 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 22 ++++++++--------- test/SemaCXX/virtual-override.cpp | 41 ++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 289c0e024d..9ec95f3d17 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5611,26 +5611,24 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, QualType NewTy = New->getType()->getAs()->getResultType(); QualType OldTy = Old->getType()->getAs()->getResultType(); - QualType CNewTy = Context.getCanonicalType(NewTy); - QualType COldTy = Context.getCanonicalType(OldTy); - - if (CNewTy == COldTy && - CNewTy.getLocalCVRQualifiers() == COldTy.getLocalCVRQualifiers()) + if (Context.hasSameType(NewTy, OldTy)) return false; // Check if the return types are covariant QualType NewClassTy, OldClassTy; /// Both types must be pointers or references to classes. - if (PointerType *NewPT = dyn_cast(CNewTy)) { - if (PointerType *OldPT = dyn_cast(COldTy)) { + if (const PointerType *NewPT = NewTy->getAs()) { + if (const PointerType *OldPT = OldTy->getAs()) { NewClassTy = NewPT->getPointeeType(); OldClassTy = OldPT->getPointeeType(); } - } else if (ReferenceType *NewRT = dyn_cast(CNewTy)) { - if (ReferenceType *OldRT = dyn_cast(COldTy)) { - NewClassTy = NewRT->getPointeeType(); - OldClassTy = OldRT->getPointeeType(); + } else if (const ReferenceType *NewRT = NewTy->getAs()) { + if (const ReferenceType *OldRT = OldTy->getAs()) { + if (NewRT->getTypeClass() == OldRT->getTypeClass()) { + NewClassTy = NewRT->getPointeeType(); + OldClassTy = OldRT->getPointeeType(); + } } } @@ -5678,7 +5676,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, } // The qualifiers of the return types must be the same. - if (CNewTy.getLocalCVRQualifiers() != COldTy.getLocalCVRQualifiers()) { + if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) { Diag(New->getLocation(), diag::err_covariant_return_type_different_qualifications) << New->getDeclName() << NewTy << OldTy; diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp index a3d3f20f14..5e1e9b0899 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s +// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s -std=c++0x namespace T1 { class A { @@ -214,3 +214,42 @@ namespace PR6110 { template class Y1 : public Y { virtual T1 f(); }; Y1 y; } + +namespace T10 { + struct A { }; + struct B : A { }; + + struct C { + virtual A&& f(); + }; + + struct D : C { + virtual B&& f(); + }; +}; + +namespace T11 { + struct A { }; + struct B : A { }; + + struct C { + virtual A& f(); // expected-note {{overridden virtual function is here}} + }; + + struct D : C { + virtual B&& f(); // expected-error {{virtual function 'f' has a different return type ('struct T11::B &&') than the function it overrides (which has return type 'struct T11::A &')}} + }; +}; + +namespace T12 { + struct A { }; + struct B : A { }; + + struct C { + virtual A&& f(); // expected-note {{overridden virtual function is here}} + }; + + struct D : C { + virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('struct T12::B &') than the function it overrides (which has return type 'struct T12::A &&')}} + }; +}; -- 2.40.0