aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-01-22 17:37:20 +0000
committerAnders Carlsson <andersca@mac.com>2010-01-22 17:37:20 +0000
commitf2a04bf1689cd88dd04012c311ba86e9d8b2b1b2 (patch)
tree08e28aa48c4ea5c75cd013fecfbe7129e4c4e85b
parent568bb2d3189108b6d510a6233d1e6e003a47cbdc (diff)
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
-rw-r--r--lib/Sema/SemaDeclCXX.cpp22
-rw-r--r--test/SemaCXX/virtual-override.cpp41
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<FunctionType>()->getResultType();
QualType OldTy = Old->getType()->getAs<FunctionType>()->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<PointerType>(CNewTy)) {
- if (PointerType *OldPT = dyn_cast<PointerType>(COldTy)) {
+ if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
+ if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
NewClassTy = NewPT->getPointeeType();
OldClassTy = OldPT->getPointeeType();
}
- } else if (ReferenceType *NewRT = dyn_cast<ReferenceType>(CNewTy)) {
- if (ReferenceType *OldRT = dyn_cast<ReferenceType>(COldTy)) {
- NewClassTy = NewRT->getPointeeType();
- OldClassTy = OldRT->getPointeeType();
+ } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
+ if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
+ 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 <typename T1, typename T> class Y1 : public Y<T> { virtual T1 f(); };
Y1<Derived*, Base*> 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 &&')}}
+ };
+};