diff options
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 29 | ||||
-rw-r--r-- | test/CodeGenCXX/destructors.cpp | 11 | ||||
-rw-r--r-- | test/SemaCXX/destructor.cpp | 4 | ||||
-rw-r--r-- | www/compatibility.html | 5 |
6 files changed, 34 insertions, 19 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5588db79e3..93e6a06ef8 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2672,7 +2672,7 @@ public: QualType CheckConstructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC); void CheckConstructor(CXXConstructorDecl *Constructor); - QualType CheckDestructorDeclarator(Declarator &D, + QualType CheckDestructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC); bool CheckDestructor(CXXDestructorDecl *Destructor); void CheckConversionDeclarator(Declarator &D, QualType &R, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ba84f7c223..500d73eb9b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3023,7 +3023,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { - R = CheckDestructorDeclarator(D, SC); + R = CheckDestructorDeclarator(D, R, SC); NewFD = CXXDestructorDecl::Create(Context, cast<CXXRecordDecl>(DC), diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1c0a72bf11..c59575f13b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2990,9 +2990,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, // Rebuild the function type "R" without any type qualifiers (in // case any of the errors above fired) and with "void" as the - // return type, since constructors don't have return types. We - // *always* have to do this, because GetTypeForDeclarator will - // put in a result type of "int" when none was specified. + // return type, since constructors don't have return types. const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), Proto->getNumArgs(), @@ -3087,7 +3085,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { /// emit diagnostics and set the declarator to invalid. Even if this happens, /// will be updated to reflect a well-formed type for the destructor and /// returned. -QualType Sema::CheckDestructorDeclarator(Declarator &D, +QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC) { // C++ [class.dtor]p1: // [...] A typedef-name that names a class is a class-name @@ -3095,11 +3093,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); - if (isa<TypedefType>(DeclaratorType)) { + if (isa<TypedefType>(DeclaratorType)) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType; - D.setInvalidType(); - } // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A @@ -3113,9 +3109,10 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) - << SourceRange(D.getIdentifierLoc()); + << SourceRange(D.getIdentifierLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + SC = FunctionDecl::None; - D.setInvalidType(); } if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { // Destructors don't have return types, but the parser will @@ -3163,11 +3160,17 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // Rebuild the function type "R" without any type qualifiers or // parameters (in case any of the errors above fired) and with // "void" as the return type, since destructors don't have return - // types. We *always* have to do this, because GetTypeForDeclarator - // will put in a result type of "int" when none was specified. - // FIXME: Exceptions! + // types. + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); + if (!Proto) + return QualType(); + return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, - false, false, 0, 0, FunctionType::ExtInfo()); + Proto->hasExceptionSpec(), + Proto->hasAnyExceptionSpec(), + Proto->getNumExceptions(), + Proto->exception_begin(), + Proto->getExtInfo()); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 1442e37403..62621f6e98 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -32,6 +32,17 @@ struct C { C::~C() { } +namespace PR7526 { + extern void foo(); + struct allocator { + ~allocator() throw(); + }; + + // CHECK: define void @_ZN6PR75269allocatorD2Ev + // CHECK: call void @__cxa_call_unexpected + allocator::~allocator() throw() { foo(); } +} + // PR5084 template<typename T> class A1 { diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index ae3dc86e97..1d36ceab23 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -19,7 +19,9 @@ struct D { // expected-error{{type qualifier is not allowed on this function}} \ // expected-error{{destructor cannot be declared 'static'}} \ // expected-error{{destructor cannot have any parameters}} \ - // expected-error{{destructor cannot be variadic}} + // expected-error{{destructor cannot be variadic}} \ + // expected-error{{destructor cannot have a return type}} \ + // expected-error{{'const' qualifier is not allowed on a destructor}} }; struct D2 { diff --git a/www/compatibility.html b/www/compatibility.html index 85133fbca2..0f8409b953 100644 --- a/www/compatibility.html +++ b/www/compatibility.html @@ -590,9 +590,8 @@ void g(Base *base) { downcast.mm:6:3: error: no matching function for call to 'f' f(base); ^ -downcast.mm:4:6: note: candidate function not viable: cannot convert from base - class pointer 'Base *' to derived class pointer 'Derived *' for 1st - argument +downcast.mm:4:6: note: candidate function not viable: cannot convert from + superclass 'Base *' to subclass 'Derived *' for 1st argument void f(Derived *); ^ </pre> |