ahatanak updated this revision to Diff 157373.
ahatanak added a comment.

Check if destructors are accessible from InitListChecker's constructor. Add 
test cases for designated initializer and brace elision.


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,24 @@
   // 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 2 {{'~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}}
+  }
+}
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
@@ -815,6 +815,27 @@
   }
 }
 
+static bool checkMemberDestructor(CXXRecordDecl *CXXRD, QualType RecType,
+                                  SourceLocation Loc, bool IsMember,
+                                  Sema &SemaRef) {
+  if (IsMember) {
+    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;
+  }
+
+  for (FieldDecl *FD : CXXRD->fields())
+    if (auto *CXXRDMember = FD->getType()->getAsCXXRecordDecl())
+      if (!checkMemberDestructor(CXXRDMember, FD->getType(), Loc, true,
+                                 SemaRef))
+        return false;
+
+  return true;
+}
+
 InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
                                  InitListExpr *IL, QualType &T,
                                  bool VerifyOnly,
@@ -838,6 +859,16 @@
     if (RequiresSecondPass && !hadError)
       FillInEmptyInitializations(Entity, FullyStructuredList,
                                  RequiresSecondPass, nullptr, 0);
+
+    // Check if destructors of 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 (auto *CXXRD = T->getAsCXXRecordDecl())
+      if (!checkMemberDestructor(CXXRD, T, IL->getLocStart(),
+                                 /*IsMember*/ false, S))
+        hadError = true;
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to