diff options
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | clang/test/CXX/special/class.dtor/p5-implicit.cpp | 21 |
3 files changed, 37 insertions, 2 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index e2391d785d9..d85ace9dda0 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -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 { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 063a0b262b2..33f02c5b7f4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15119,8 +15119,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, 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()) { diff --git a/clang/test/CXX/special/class.dtor/p5-implicit.cpp b/clang/test/CXX/special/class.dtor/p5-implicit.cpp new file mode 100644 index 00000000000..703be15b70c --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p5-implicit.cpp @@ -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 |