Author: rsmith Date: Thu Sep 21 18:04:22 2017 New Revision: 313948 URL: http://llvm.org/viewvc/llvm-project?rev=313948&view=rev Log: Fix tracking of whether a destructor would be deleted.
I've been unable to find any cases whose behavior is actually changed by this, but only because an implicitly deleted destructor also results in it being impossible to have a trivial (non-deleted) copy constructor, which the place where this really matters (choosing whether to pass a class in registers) happens to also check. Added: cfe/trunk/test/CXX/special/class.dtor/p5-implicit.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/lib/Sema/SemaDecl.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=313948&r1=313947&r2=313948&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Sep 21 18:04:22 2017 @@ -838,7 +838,10 @@ public: /// \brief \c true if a defaulted destructor for this class would be deleted. bool defaultedDestructorIsDeleted() const { - return !data().DefaultedDestructorIsDeleted; + assert((!needsOverloadResolutionForDestructor() || + (data().DeclaredSpecialMembers & SMF_Destructor)) && + "this property has not yet been computed by Sema"); + return data().DefaultedDestructorIsDeleted; } /// \brief \c true if we know for sure that this class has a single, @@ -985,6 +988,15 @@ public: data().DefaultedMoveConstructorIsDeleted = true; } + /// \brief Set that we attempted to declare an implicit destructor, + /// but overload resolution failed so we deleted it. + void setImplicitDestructorIsDeleted() { + assert((data().DefaultedDestructorIsDeleted || + needsOverloadResolutionForDestructor()) && + "destructor should not be deleted"); + data().DefaultedDestructorIsDeleted = true; + } + /// \brief Determine whether this class should get an implicit move /// constructor or if any existing special member function inhibits this. bool needsImplicitMoveConstructor() const { Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=313948&r1=313947&r2=313948&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 21 18:04:22 2017 @@ -15119,8 +15119,10 @@ void Sema::ActOnFields(Scope *S, SourceL if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && - ShouldDeleteSpecialMember(Dtor, CXXDestructor)) + ShouldDeleteSpecialMember(Dtor, CXXDestructor)) { + CXXRecord->setImplicitDestructorIsDeleted(); SetDeclDeleted(Dtor, CXXRecord->getLocation()); + } } if (Record->hasAttrs()) { Added: cfe/trunk/test/CXX/special/class.dtor/p5-implicit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.dtor/p5-implicit.cpp?rev=313948&view=auto ============================================================================== --- cfe/trunk/test/CXX/special/class.dtor/p5-implicit.cpp (added) +++ cfe/trunk/test/CXX/special/class.dtor/p5-implicit.cpp Thu Sep 21 18:04:22 2017 @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++11 %s -ast-dump | FileCheck %s + +struct A { ~A() = delete; }; +// CHECK-LABEL: CXXRecordDecl {{.*}} struct A +// CHECK: Destructor trivial user_declared + +struct B : A {}; +// CHECK-LABEL: CXXRecordDecl {{.*}} struct B +// CHECK: Destructor trivial needs_overload_resolution + +struct C : B {}; +// CHECK-LABEL: CXXRecordDecl {{.*}} struct C +// CHECK: Destructor trivial needs_overload_resolution + +struct D { ~D(); }; +struct E : D {}; +union U { + E e; +}; +// CHECK-LABEL: CXXRecordDecl {{.*}} union U +// CHECK: Destructor non_trivial needs_implicit defaulted_is_deleted _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits