ahatanak updated this revision to Diff 163612.
ahatanak marked 3 inline comments as done.
ahatanak added a comment.

Move the call that checks the element's destructor into 
InitListChecker::CheckStructUnionTypes.


Repository:
  rC Clang

https://reviews.llvm.org/D45898

Files:
  lib/Sema/SemaInit.cpp
  test/CodeGenObjCXX/arc-list-init-destruct.mm
  test/SemaCXX/aggregate-initialization.cpp

Index: test/SemaCXX/aggregate-initialization.cpp
===================================================================
--- test/SemaCXX/aggregate-initialization.cpp
+++ test/SemaCXX/aggregate-initialization.cpp
@@ -186,3 +186,51 @@
   // amount of time.
   struct A { int n; int arr[1000 * 1000 * 1000]; } a = {1, {2}};
 }
+
+namespace ElementDestructor {
+  // The destructor for each element of class type is potentially invoked
+  // (15.4 [class.dtor]) from the context where the aggregate initialization
+  // occurs. Produce a diagnostic if an element's destructor isn't accessible.
+
+  class X { int f; ~X(); }; // expected-note {{implicitly declared private here}}
+  struct Y { X x; };
+
+  void test0() {
+    auto *y = new Y {}; // expected-error {{temporary of type 'ElementDestructor::X' has private destructor}}
+  }
+
+  struct S0 { int f; ~S0() = delete; }; // expected-note 3 {{'~S0' has been explicitly marked deleted here}}
+  struct S1 { S0 s0; int f; };
+
+  S1 test1() {
+    auto *t = new S1 { .f = 1 }; // expected-error {{attempt to use a deleted function}}
+    return {2}; // expected-error {{attempt to use a deleted function}}
+  }
+
+  // Check if the type of an array element has a destructor.
+  struct S2 { S0 a[4]; };
+
+  void test2() {
+    auto *t = new S2 {1,2,3,4}; // expected-error {{attempt to use a deleted function}}
+  }
+
+#if __cplusplus >= 201703L
+  namespace BaseDestructor {
+     struct S0 { int f; ~S0() = delete; }; // expected-note {{'~S0' has been explicitly marked deleted here}}
+
+    // Check destructor of base class.
+    struct S3 : S0 {};
+
+    void test3() {
+      S3 s3 = {1}; // expected-error {{attempt to use a deleted function}}
+    }
+  }
+#endif
+
+  // A's destructor doesn't have to be accessible from the context of C's
+  // initialization.
+  struct A { friend struct B; private: ~A(); };
+  struct B { B(); A a; };
+  struct C { B b; };
+  C c = { B() };
+}
Index: test/CodeGenObjCXX/arc-list-init-destruct.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/arc-list-init-destruct.mm
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -std=c++1z -fobjc-arc -fobjc-exceptions -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %[[V0:.*]] = type opaque
+// CHECK: %[[STRUCT_CLASS1:.*]] = type { %[[V0]]* }
+
+@interface Class0;
+@end
+
+struct Class1 {
+  Class0 *f;
+};
+
+struct Container {
+  Class1 a;
+  bool b;
+};
+
+bool getBool() {
+  return false;
+}
+
+Class0 *g;
+
+// CHECK: define {{.*}} @_Z4testv()
+// CHECK: invoke zeroext i1 @_Z7getBoolv()
+// CHECK: landingpad { i8*, i32 }
+// CHECK: call void @_ZN6Class1D1Ev(%[[STRUCT_CLASS1]]* %{{.*}})
+// CHECK: br label
+
+// CHECK: define linkonce_odr void @_ZN6Class1D1Ev(
+
+Container test() {
+  return {{g}, getBool()};
+}
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -1818,6 +1818,17 @@
   return FlexArrayDiag != diag::ext_flexible_array_init;
 }
 
+static bool checkElementDestructor(CXXRecordDecl *CXXRD, QualType RecType,
+                                   SourceLocation Loc, Sema &SemaRef) {
+  CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD);
+  SemaRef.CheckDestructorAccess(
+      Loc, Destructor, SemaRef.PDiag(diag::err_access_dtor_temp) << RecType);
+  SemaRef.MarkFunctionReferenced(Loc, Destructor);
+  if (SemaRef.DiagnoseUseOfDecl(Destructor, Loc))
+    return false;
+  return true;
+}
+
 void InitListChecker::CheckStructUnionTypes(
     const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
     CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field,
@@ -1835,6 +1846,32 @@
     return;
   }
 
+  // Check if destructors of base classes and members are accessible.
+  //
+  // The destructor for each element of class type is potentially invoked
+  // (15.4 [class.dtor]) from the context where the aggregate
+  // initialization occurs.
+  if (!VerifyOnly)
+    if (auto *CXXRD = DeclType->getAsCXXRecordDecl()) {
+      SourceLocation Loc = IList->getBeginLoc();
+      for (auto &Base : Bases)
+        if (auto *CXXRDMember = Base.getType()->getAsCXXRecordDecl())
+          if (!checkElementDestructor(CXXRDMember, Base.getType(), Loc,
+                                      SemaRef)) {
+            hadError = true;
+            return;
+          }
+
+      for (FieldDecl *FD : CXXRD->fields()) {
+        QualType ET = SemaRef.Context.getBaseElementType(FD->getType());
+        if (auto *CXXRDMember = ET->getAsCXXRecordDecl())
+          if (!checkElementDestructor(CXXRDMember, ET, Loc, SemaRef)) {
+            hadError = true;
+            return;
+          }
+      }
+    }
+
   if (DeclType->isUnionType() && IList->getNumInits() == 0) {
     RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to