diff options
author | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-17 20:44:43 +0000 |
---|---|---|
committer | Sean Hunt <scshunt@csclub.uwaterloo.ca> | 2011-05-17 20:44:43 +0000 |
commit | be63122e65ea06010c4ce06a77276bcb29a575b6 (patch) | |
tree | 888c018fc020a8092531c23c1429662d8c4612c5 | |
parent | f1922d299be143f65b9c349e7f7b4ed5d0a90965 (diff) |
Fix some minor bugs and add a lot more test cases for defaulted
constructors, including two more FIXMEs (one of which I don't actually
understand).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131487 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-cursory-default-delete.cpp | 69 |
3 files changed, 84 insertions, 8 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b40aa61ba5..513ad0ea73 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3644,6 +3644,9 @@ def err_defaulted_copy_assign_params : Error< def err_defaulted_copy_assign_return_type : Error< "an explicitly-defaulted copy assignment operator must return an unqualified " "lvalue reference to its class type">; +def err_defaulted_copy_assign_not_ref : Error< + "the parameter for an explicitly-defaulted copy assignment operator must be an " + "lvalue reference type">; def err_defaulted_copy_assign_volatile_param : Error< "the parameter for an explicitly-defaulted copy assignment operator may not " "be volatile">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e280972f02..406f4df16f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3187,17 +3187,21 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { *ExceptionType = Context.getFunctionType( Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); - // Check for parameter type matching. - // This is a copy ctor so we know it's a cv-qualified reference to T. QualType ArgType = OperType->getArgType(0); - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified() && !Const) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + if (!ArgType->isReferenceType()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; + } else { + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified() && !Const) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + HadError = true; + } } + if (OperType->getTypeQuals()) { Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); HadError = true; diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp new file mode 100644 index 0000000000..61aee0e456 --- /dev/null +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct non_copiable { + non_copiable(const non_copiable&) = delete; // expected-note {{marked deleted here}} + non_copiable& operator = (const non_copiable&) = delete; // expected-note {{explicitly deleted}} + non_copiable() = default; +}; + +struct non_const_copy { + non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} + non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} + non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} + non_const_copy() = default; // expected-note {{not viable}} +}; + +void fn1 () { + non_copiable nc; + non_copiable nc2 = nc; // expected-error {{deleted constructor}} + nc = nc; // expected-error {{deleted operator}} + + non_const_copy ncc; + non_const_copy ncc2 = ncc; + ncc = ncc2; + const non_const_copy cncc; + non_const_copy ncc3 = cncc; // expected-error {{no matching}} + ncc = cncc; // expected-error {{no viable overloaded}} +}; + +struct non_const_derived : non_const_copy { + non_const_derived(const non_const_derived&) = default; // expected-error {{requires it to be non-const}} + non_const_derived& operator =(non_const_derived&) = default; +}; + +struct bad_decls { + bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls&& operator = (bad_decls) = default; // expected-error 2{{lvalue reference}} + bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const' or 'volatile' qualifiers}} +}; + +struct A {}; struct B {}; + +struct except_spec_a { + virtual ~except_spec_a() throw(A); + except_spec_a() throw(A); +}; +struct except_spec_b { + virtual ~except_spec_b() throw(B); + except_spec_b() throw(B); +}; + +struct except_spec_d_good : except_spec_a, except_spec_b { + ~except_spec_d_good(); +}; +except_spec_d_good::~except_spec_d_good() = default; +// FIXME: This should error in the virtual override check. +// It doesn't because we generate the implicit specification later than +// appropriate. +struct except_spec_d_bad : except_spec_a, except_spec_b { + ~except_spec_d_bad() = default; +}; + +// FIXME: This should error because the exceptions spec doesn't match. +struct except_spec_d_mismatch : except_spec_a, except_spec_b { + except_spec_d_mismatch() throw(A) = default; +}; +struct except_spec_d_match : except_spec_a, except_spec_b { + except_spec_d_match() throw(A, B) = default; +}; |