aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-03-22 23:49:27 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-03-22 23:49:27 +0000
commitf2e21e5ad5e816d88e048c89dc775a9d4547c089 (patch)
treee36f53c864c4d99201d2fc8f215284bcc750b3ac
parent04831aa3271edc5f00a651bf7152c2902981d7c3 (diff)
Disallow catching exceptions by rvalue reference.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67492 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td1
-rw-r--r--lib/Sema/SemaDeclCXX.cpp10
-rw-r--r--lib/Sema/SemaOverload.cpp23
-rw-r--r--test/SemaCXX/rval-references.cpp5
4 files changed, 30 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index f4a8470ecb..51fb9829db 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1040,6 +1040,7 @@ def err_catch_incomplete_ptr : Error<
def err_catch_incomplete_ref : Error<
"cannot catch reference to incomplete type %0">;
def err_catch_incomplete : Error<"cannot catch incomplete type %0">;
+def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">;
def err_qualified_catch_declarator : Error<
"exception declarator cannot be qualified">;
def err_early_catch_all : Error<"catch-all handler must come last">;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 95e282ae25..6be2052fdf 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2320,6 +2320,11 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
// C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
// The exception-declaration shall not denote a pointer or reference to an
// incomplete type, other than [cv] void*.
+ // N2844 forbids rvalue references.
+ if(ExDeclType->isRValueReferenceType()) {
+ Diag(Begin, diag::err_catch_rvalue_ref) << D.getSourceRange();
+ Invalid = true;
+ }
QualType BaseType = ExDeclType;
int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
unsigned DK = diag::err_catch_incomplete;
@@ -2328,16 +2333,15 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
Mode = 1;
DK = diag::err_catch_incomplete_ptr;
} else if(const ReferenceType *Ref = BaseType->getAsReferenceType()) {
+ // For the purpose of error recovery, we treat rvalue refs like lvalue refs.
BaseType = Ref->getPointeeType();
Mode = 2;
DK = diag::err_catch_incomplete_ref;
}
- if ((Mode == 0 || !BaseType->isVoidType()) &&
+ if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
RequireCompleteType(Begin, BaseType, DK))
Invalid = true;
- // FIXME: C++0x [except.handle] names the handler as cv T or cv T&, i.e.
- // rvalue references aren't there. Oversight or intentional?
// FIXME: Need to test for ability to copy-construct and destroy the
// exception variable.
// FIXME: Need to check for abstract classes.
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 5321935cfc..9f88a87474 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1584,15 +1584,26 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
= CompareQualificationConversions(SCS1, SCS2))
return QualCK;
- // C++ [over.ics.rank]p3b4:
- // -- S1 and S2 are reference bindings (8.5.3), and the types to
- // which the references refer are the same type except for
- // top-level cv-qualifiers, and the type to which the reference
- // initialized by S2 refers is more cv-qualified than the type
- // to which the reference initialized by S1 refers.
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ // C++0x [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
+ // implicit object parameter of a non-static member function declared
+ // without a ref-qualifier, and S1 binds an rvalue reference to an
+ // rvalue and S2 binds an lvalue reference.
+ // FIXME: We have far too little information for this check. We don't know
+ // if the bound object is an rvalue. We don't know if the binding type is
+ // an rvalue or lvalue reference. We don't know if we're dealing with the
+ // implicit object parameter, or if the member function in this case has
+ // a ref qualifier.
+
+ // C++ [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3), and the types to
+ // which the references refer are the same type except for
+ // top-level cv-qualifiers, and the type to which the reference
+ // initialized by S2 refers is more cv-qualified than the type
+ // to which the reference initialized by S1 refers.
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) {
diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp
index 59be9f50f6..df46814753 100644
--- a/test/SemaCXX/rval-references.cpp
+++ b/test/SemaCXX/rval-references.cpp
@@ -45,4 +45,9 @@ void f() {
conv_to_not_int_rvalue cnir;
not_int &&ni4 = cnir;
not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot be initialized with a value of type 'struct conv_to_not_int_rvalue'}}
+
+
+ try {
+ } catch(int&&) { // expected-error {{cannot catch exceptions by rvalue reference}}
+ }
}