[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-02-01 Thread Akira Hatanaka via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
ahatanak marked an inline comment as done.
Closed by commit rC352949: [Sema][ObjC] Allow declaring ObjC pointer members 
with non-trivial (authored by ahatanak, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D57438?vs=184851=184879#toc

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/DeclCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaObjCXX/arc-0x.mm
  test/SemaObjCXX/objc-weak.mm

Index: test/SemaObjCXX/arc-0x.mm
===
--- test/SemaObjCXX/arc-0x.mm
+++ test/SemaObjCXX/arc-0x.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -verify -fblocks -fobjc-exceptions %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -fobjc-weak -verify -fblocks -fobjc-exceptions %s
 
 // "Move" semantics, trivial version.
 void move_it(__strong id &) {
@@ -111,3 +111,160 @@
 func(^(A *a[]){}); // expected-error{{must explicitly describe intended ownership of an object array parameter}}
   }
 }
+
+namespace test_union {
+  // Implicitly-declared special functions of a union are deleted by default if
+  // ARC is enabled and the union has an ObjC pointer field.
+  union U0 {
+id f0; // expected-note 6 {{'U0' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  };
+
+  union U1 {
+__weak id f0; // expected-note 12 {{'U1' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}}
+U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}}
+  };
+
+  id getStrong();
+
+  // If the ObjC pointer field of a union has a default member initializer, the
+  // implicitly-declared default constructor of the union is not deleted by
+  // default.
+  union U2 {
+id f0 = getStrong(); // expected-note 4 {{'U2' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+~U2();
+  };
+
+  // It's fine if the user has explicitly defined the special functions.
+  union U3 {
+id f0;
+U3();
+~U3();
+U3(const U3 &);
+U3(U3 &&);
+U3 & operator=(const U3 &);
+U3 & operator=(U3 &&);
+  };
+
+  // ObjC pointer fields in anonymous union fields delete the defaulted special
+  // functions of the containing class.
+  struct S0 {
+union {
+  id f0; // expected-note 6 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  char f1;
+};
+  };
+
+  struct S1 {
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+char f1;
+  };
+  int f2;
+};
+  };
+
+  struct S2 {
+union {
+  // FIXME: the note should say 'f0' is causing the special functions to be deleted.
+  struct { // expected-note 6 {{'S2' is implicitly deleted because variant field '' has a non-trivial}}
+id f0;
+int f1;
+  };
+  int f2;
+};
+int f3;
+  };
+
+  U0 *x0;
+  U1 *x1;
+  U2 *x2;
+  U3 *x3;
+  S0 *x4;
+  S1 *x5;
+  S2 *x6;
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+id g0; // expected-note {{default constructor of '' is implicitly deleted because variant field 'g0' is an ObjC pointer}}
+  };
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+union { // expected-note {{default constructor of '' is implicitly deleted because field '' has a deleted default constructor}}
+  union { // expected-note {{default constructor of '' is implicitly deleted because field '' has a deleted 

[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-02-01 Thread John McCall via Phabricator via cfe-commits
rjmccall added a comment.

Asking for a minor tweak, but feel free to commit with that.




Comment at: lib/Sema/SemaDeclCXX.cpp:7084
 
+  if (FD->getParent()->isUnion() &&
+  shouldDeleteForVariantObjCPtrMember(FD, FieldType))

ahatanak wrote:
> rjmccall wrote:
> > rjmccall wrote:
> > > I believe the right check for variant-ness is `inUnion()`, not 
> > > `FD->getParent()->isUnion()`, since the latter can miss cases with e.g. 
> > > anonymous `struct`s.
> > Can you try adding a test case here for an anonymous struct nested within 
> > an anonymous union?
> Added a test case for an anonymous struct nested within an anonymous union 
> (`struct S2` in arc-0x.mm).
> 
> I found out that the diagnostic messages clang prints for arc-0x.mm are the 
> same whether `inUnion()` or `FD->getParent()->isUnion()` is called. This is 
> what I discovered:
> 
> `SpecialMemberDeletionInfo` is used in two cases:
> 
> 1. To find the deletedness of the special functions in the AST after a class 
> is parsed.
> 
> 2. When a deleted special function is used, provide more details on why the 
> function is deleted and print note diagnostics.
> 
> Since the nested classes are parsed before the enclosing classes, we have all 
> the information we need about the members that are directly contained to 
> correctly infer the deletedness of a class' special functions. So the first 
> case should work fine regardless of which method is called.
> 
> It doesn't make a difference for the second case either because 
> `SpecialMemberDeletionInfo` doesn't try to find out which member of an 
> anonymous struct is causing the special function to be deleted; it only does 
> so for anonymous unions (which happens inside the if statement near comment 
> "// Some additional restrictions exist on the variant members." at line 7140).
Alright.  Another place where we could generally improve diagnostics, then.



Comment at: test/SemaObjCXX/arc-0x.mm:174
+union {
+  struct { // expected-note 6 {{'S2' is implicitly deleted because variant 
field '' has a non-trivial}}
+id f0;

Worth adding a FIXME saying that this note should go on `f1`?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-02-01 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 184851.
ahatanak marked an inline comment as done.
ahatanak added a comment.

Add a test case for an anonymous struct nested inside an anonymous union.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/DeclCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaObjCXX/arc-0x.mm
  test/SemaObjCXX/objc-weak.mm

Index: test/SemaObjCXX/objc-weak.mm
===
--- test/SemaObjCXX/objc-weak.mm
+++ test/SemaObjCXX/objc-weak.mm
@@ -13,7 +13,7 @@
 };
 
 union U {
-  __weak id a; // expected-error {{ARC forbids Objective-C objects in union}}
+  __weak id a;
   S b; // expected-error {{union member 'b' has a non-trivial copy constructor}}
 };
 
Index: test/SemaObjCXX/arc-0x.mm
===
--- test/SemaObjCXX/arc-0x.mm
+++ test/SemaObjCXX/arc-0x.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -verify -fblocks -fobjc-exceptions %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -fobjc-weak -verify -fblocks -fobjc-exceptions %s
 
 // "Move" semantics, trivial version.
 void move_it(__strong id &) {
@@ -111,3 +111,159 @@
 func(^(A *a[]){}); // expected-error{{must explicitly describe intended ownership of an object array parameter}}
   }
 }
+
+namespace test_union {
+  // Implicitly-declared special functions of a union are deleted by default if
+  // ARC is enabled and the union has an ObjC pointer field.
+  union U0 {
+id f0; // expected-note 6 {{'U0' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  };
+
+  union U1 {
+__weak id f0; // expected-note 12 {{'U1' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}}
+U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}}
+  };
+
+  id getStrong();
+
+  // If the ObjC pointer field of a union has a default member initializer, the
+  // implicitly-declared default constructor of the union is not deleted by
+  // default.
+  union U2 {
+id f0 = getStrong(); // expected-note 4 {{'U2' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+~U2();
+  };
+
+  // It's fine if the user has explicitly defined the special functions.
+  union U3 {
+id f0;
+U3();
+~U3();
+U3(const U3 &);
+U3(U3 &&);
+U3 & operator=(const U3 &);
+U3 & operator=(U3 &&);
+  };
+
+  // ObjC pointer fields in anonymous union fields delete the defaulted special
+  // functions of the containing class.
+  struct S0 {
+union {
+  id f0; // expected-note 6 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  char f1;
+};
+  };
+
+  struct S1 {
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+char f1;
+  };
+  int f2;
+};
+  };
+
+  struct S2 {
+union {
+  struct { // expected-note 6 {{'S2' is implicitly deleted because variant field '' has a non-trivial}}
+id f0;
+int f1;
+  };
+  int f2;
+};
+int f3;
+  };
+
+  U0 *x0;
+  U1 *x1;
+  U2 *x2;
+  U3 *x3;
+  S0 *x4;
+  S1 *x5;
+  S2 *x6;
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+id g0; // expected-note {{default constructor of '' is implicitly deleted because variant field 'g0' is an ObjC pointer}}
+  };
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+union { // expected-note {{default constructor of '' is implicitly deleted because field '' has a deleted default constructor}}
+  union { // expected-note 

[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-02-01 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak marked 2 inline comments as done.
ahatanak added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:7084
 
+  if (FD->getParent()->isUnion() &&
+  shouldDeleteForVariantObjCPtrMember(FD, FieldType))

rjmccall wrote:
> rjmccall wrote:
> > I believe the right check for variant-ness is `inUnion()`, not 
> > `FD->getParent()->isUnion()`, since the latter can miss cases with e.g. 
> > anonymous `struct`s.
> Can you try adding a test case here for an anonymous struct nested within an 
> anonymous union?
Added a test case for an anonymous struct nested within an anonymous union 
(`struct S2` in arc-0x.mm).

I found out that the diagnostic messages clang prints for arc-0x.mm are the 
same whether `inUnion()` or `FD->getParent()->isUnion()` is called. This is 
what I discovered:

`SpecialMemberDeletionInfo` is used in two cases:

1. To find the deletedness of the special functions in the AST after a class is 
parsed.

2. When a deleted special function is used, provide more details on why the 
function is deleted and print note diagnostics.

Since the nested classes are parsed before the enclosing classes, we have all 
the information we need about the members that are directly contained to 
correctly infer the deletedness of a class' special functions. So the first 
case should work fine regardless of which method is called.

It doesn't make a difference for the second case either because 
`SpecialMemberDeletionInfo` doesn't try to find out which member of an 
anonymous struct is causing the special function to be deleted; it only does so 
for anonymous unions (which happens inside the if statement near comment "// 
Some additional restrictions exist on the variant members." at line 7140).


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-31 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:7084
 
+  if (FD->getParent()->isUnion() &&
+  shouldDeleteForVariantObjCPtrMember(FD, FieldType))

rjmccall wrote:
> I believe the right check for variant-ness is `inUnion()`, not 
> `FD->getParent()->isUnion()`, since the latter can miss cases with e.g. 
> anonymous `struct`s.
Can you try adding a test case here for an anonymous struct nested within an 
anonymous union?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-31 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 184665.
ahatanak marked 3 inline comments as done.
ahatanak added a comment.

Address review comments.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/DeclCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaObjCXX/arc-0x.mm
  test/SemaObjCXX/objc-weak.mm

Index: test/SemaObjCXX/objc-weak.mm
===
--- test/SemaObjCXX/objc-weak.mm
+++ test/SemaObjCXX/objc-weak.mm
@@ -13,7 +13,7 @@
 };
 
 union U {
-  __weak id a; // expected-error {{ARC forbids Objective-C objects in union}}
+  __weak id a;
   S b; // expected-error {{union member 'b' has a non-trivial copy constructor}}
 };
 
Index: test/SemaObjCXX/arc-0x.mm
===
--- test/SemaObjCXX/arc-0x.mm
+++ test/SemaObjCXX/arc-0x.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -verify -fblocks -fobjc-exceptions %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -fobjc-weak -verify -fblocks -fobjc-exceptions %s
 
 // "Move" semantics, trivial version.
 void move_it(__strong id &) {
@@ -111,3 +111,141 @@
 func(^(A *a[]){}); // expected-error{{must explicitly describe intended ownership of an object array parameter}}
   }
 }
+
+namespace test_union {
+  // Implicitly-declared special functions of a union are deleted by default if
+  // ARC is enabled and the union has an ObjC pointer field.
+  union U0 {
+id f0; // expected-note 6 {{'U0' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  };
+
+  union U1 {
+__weak id f0; // expected-note 12 {{'U1' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}}
+U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}}
+  };
+
+  id getStrong();
+
+  // If the ObjC pointer field of a union has a default member initializer, the
+  // implicitly-declared default constructor of the union is not deleted by
+  // default.
+  union U2 {
+id f0 = getStrong(); // expected-note 4 {{'U2' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+~U2();
+  };
+
+  // It's fine if the user has explicitly defined the special functions.
+  union U3 {
+id f0;
+U3();
+~U3();
+U3(const U3 &);
+U3(U3 &&);
+U3 & operator=(const U3 &);
+U3 & operator=(U3 &&);
+  };
+
+  // ObjC pointer fields in anonymous union fields delete the defaulted special
+  // functions of the containing class.
+  struct S0 {
+union {
+  id f0; // expected-note 6 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  char f1;
+};
+  };
+
+  struct S1 {
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+char f1;
+  };
+  int f2;
+};
+  };
+
+  U0 *x0;
+  U1 *x1;
+  U2 *x2;
+  U3 *x3;
+  S0 *x4;
+  S1 *x5;
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+id g0; // expected-note {{default constructor of '' is implicitly deleted because variant field 'g0' is an ObjC pointer}}
+  };
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+union { // expected-note {{default constructor of '' is implicitly deleted because field '' has a deleted default constructor}}
+  union { // expected-note {{default constructor of '' is implicitly deleted because field '' has a deleted default constructor}}
+__weak id g1; // expected-note {{default constructor of '' is implicitly deleted because variant field 'g1' is an ObjC pointer}}
+int g2;
+  };
+  int g3;
+   

[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-31 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak added inline comments.



Comment at: test/SemaObjCXX/arc-0x.mm:164
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant 
field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted 
because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant 
field 'f0' is an ObjC pointer}}

rjmccall wrote:
> ahatanak wrote:
> > The diagnostic message here should say the special function is deleted 
> > because the anonymous union's corresponding special function is deleted, 
> > but when diagnosing a deleted copy assignment operator, it says the 
> > anonymous union's special function is non-trivial. I'm not sure this is a 
> > bug, but I see the same diagnostic message when I compile the following 
> > non-ObjC code:
> > 
> > ```
> > struct S0 {
> >   S0(const S0 &);
> >   S0 =(const S0 &);
> >   int *p;
> > };
> > 
> > struct S1 {
> >   union {
> > union { // copy assignment operator of 'S1' is implicitly deleted 
> > because variant field '' has a non-trivial copy assignment operator
> >   S0 s10;
> >   int b;
> > };
> > int c;
> >   };
> >   ~S1();
> > };
> > 
> > S1 *x0;
> > 
> > void testC1(S1 *a0) {
> >   *a0 = *x0; // error: object of type 'S1' cannot be assigned because its 
> > copy assignment operator is implicitly deleted
> >   *a0 = static_cast(*x0); // error: object of type 'S1' cannot be 
> > assigned because its copy assignment operator is implicitly deleted
> > }
> > ```
> > 
> > It seems that this happens because the following code in 
> > `Sema::ShouldDeleteSpecialMember` is preventing the method declaration from 
> > being marked as deleted:
> > 
> > ```
> >   // For an anonymous struct or union, the copy and assignment special 
> > members
> >   // will never be used, so skip the check. For an anonymous union declared 
> > at
> >   // namespace scope, the constructor and destructor are used.
> >   if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
> >   RD->isAnonymousStructOrUnion())
> > return false;
> > ```
> Well, if it's not different from the ordinary C++ treatment, I think we can 
> justify just improving QoI there separately.
I filed PR40555 to fix the C++ case.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-31 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:7033
+  // member of an ObjC pointer type, except when it has an in-class 
initializer,
+  // it doesn't make the defaulted default constructor defined as deleted.
+  if (!FieldType.hasNonTrivialObjCLifetime() ||

This comment should be talking about non-trivial ownership rather than just 
general ObjC pointer-ish-ness.



Comment at: lib/Sema/SemaDeclCXX.cpp:7036
+  (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()))
+return false;
+

I feel like this would be clearer as separate `if` statements; you can put 
separate comments on each.



Comment at: lib/Sema/SemaDeclCXX.cpp:7084
 
+  if (FD->getParent()->isUnion() &&
+  shouldDeleteForVariantObjCPtrMember(FD, FieldType))

I believe the right check for variant-ness is `inUnion()`, not 
`FD->getParent()->isUnion()`, since the latter can miss cases with e.g. 
anonymous `struct`s.



Comment at: test/SemaObjCXX/arc-0x.mm:164
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant 
field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted 
because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant 
field 'f0' is an ObjC pointer}}

ahatanak wrote:
> The diagnostic message here should say the special function is deleted 
> because the anonymous union's corresponding special function is deleted, but 
> when diagnosing a deleted copy assignment operator, it says the anonymous 
> union's special function is non-trivial. I'm not sure this is a bug, but I 
> see the same diagnostic message when I compile the following non-ObjC code:
> 
> ```
> struct S0 {
>   S0(const S0 &);
>   S0 =(const S0 &);
>   int *p;
> };
> 
> struct S1 {
>   union {
> union { // copy assignment operator of 'S1' is implicitly deleted because 
> variant field '' has a non-trivial copy assignment operator
>   S0 s10;
>   int b;
> };
> int c;
>   };
>   ~S1();
> };
> 
> S1 *x0;
> 
> void testC1(S1 *a0) {
>   *a0 = *x0; // error: object of type 'S1' cannot be assigned because its 
> copy assignment operator is implicitly deleted
>   *a0 = static_cast(*x0); // error: object of type 'S1' cannot be 
> assigned because its copy assignment operator is implicitly deleted
> }
> ```
> 
> It seems that this happens because the following code in 
> `Sema::ShouldDeleteSpecialMember` is preventing the method declaration from 
> being marked as deleted:
> 
> ```
>   // For an anonymous struct or union, the copy and assignment special members
>   // will never be used, so skip the check. For an anonymous union declared at
>   // namespace scope, the constructor and destructor are used.
>   if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
>   RD->isAnonymousStructOrUnion())
> return false;
> ```
Well, if it's not different from the ordinary C++ treatment, I think we can 
justify just improving QoI there separately.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-29 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak marked an inline comment as done.
ahatanak added inline comments.



Comment at: test/SemaObjCXX/arc-0x.mm:164
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant 
field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted 
because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant 
field 'f0' is an ObjC pointer}}

The diagnostic message here should say the special function is deleted because 
the anonymous union's corresponding special function is deleted, but when 
diagnosing a deleted copy assignment operator, it says the anonymous union's 
special function is non-trivial. I'm not sure this is a bug, but I see the same 
diagnostic message when I compile the following non-ObjC code:

```
struct S0 {
  S0(const S0 &);
  S0 =(const S0 &);
  int *p;
};

struct S1 {
  union {
union { // copy assignment operator of 'S1' is implicitly deleted because 
variant field '' has a non-trivial copy assignment operator
  S0 s10;
  int b;
};
int c;
  };
  ~S1();
};

S1 *x0;

void testC1(S1 *a0) {
  *a0 = *x0; // error: object of type 'S1' cannot be assigned because its copy 
assignment operator is implicitly deleted
  *a0 = static_cast(*x0); // error: object of type 'S1' cannot be 
assigned because its copy assignment operator is implicitly deleted
}
```

It seems that this happens because the following code in 
`Sema::ShouldDeleteSpecialMember` is preventing the method declaration from 
being marked as deleted:

```
  // For an anonymous struct or union, the copy and assignment special members
  // will never be used, so skip the check. For an anonymous union declared at
  // namespace scope, the constructor and destructor are used.
  if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
  RD->isAnonymousStructOrUnion())
return false;
```


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57438/new/

https://reviews.llvm.org/D57438



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57438: [Sema][ObjC] Allow declaring ObjC pointer members in C++ unions under ARC

2019-01-29 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak created this revision.
ahatanak added reviewers: rsmith, rjmccall, doug.gregor.
ahatanak added a project: clang.
Herald added subscribers: dexonsmith, jkorous.

ObjC pointer members are currently not allowed in unions in either C or C++ 
mode. This patch lifts the restriction in C++ mode.

This patch essentially treats ObjC pointer members the same way a non-static 
data member of a class type that has non-trivial special functions is treated. 
The ObjC pointer member causes all of the defaulted special functions of the 
union that directly contains the member to be defined as deleted, except when 
the member has an in-class initializer, the default constructor isn't defined 
as deleted.

rdar://problem/34213306


Repository:
  rC Clang

https://reviews.llvm.org/D57438

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/DeclCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaObjCXX/arc-0x.mm
  test/SemaObjCXX/objc-weak.mm

Index: test/SemaObjCXX/objc-weak.mm
===
--- test/SemaObjCXX/objc-weak.mm
+++ test/SemaObjCXX/objc-weak.mm
@@ -13,7 +13,7 @@
 };
 
 union U {
-  __weak id a; // expected-error {{ARC forbids Objective-C objects in union}}
+  __weak id a;
   S b; // expected-error {{union member 'b' has a non-trivial copy constructor}}
 };
 
Index: test/SemaObjCXX/arc-0x.mm
===
--- test/SemaObjCXX/arc-0x.mm
+++ test/SemaObjCXX/arc-0x.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -verify -fblocks -fobjc-exceptions %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -fobjc-weak -verify -fblocks -fobjc-exceptions %s
 
 // "Move" semantics, trivial version.
 void move_it(__strong id &) {
@@ -111,3 +111,141 @@
 func(^(A *a[]){}); // expected-error{{must explicitly describe intended ownership of an object array parameter}}
   }
 }
+
+namespace test_union {
+  // Implicitly-declared special functions of a union are deleted by default if
+  // ARC is enabled and the union has an ObjC pointer field.
+  union U0 {
+id f0; // expected-note 6 {{'U0' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  };
+
+  union U1 {
+__weak id f0; // expected-note 12 {{'U1' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+U1() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+~U1() = default; // expected-warning {{explicitly defaulted destructor is implicitly deleted}} expected-note {{explicitly defaulted function was implicitly deleted here}}
+U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}}
+U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}}
+U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}}
+  };
+
+  id getStrong();
+
+  // If the ObjC pointer field of a union has a default member initializer, the
+  // implicitly-declared default constructor of the union is not deleted by
+  // default.
+  union U2 {
+id f0 = getStrong(); // expected-note 4 {{'U2' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+~U2();
+  };
+
+  // It's fine if the user has explicitly defined the special functions.
+  union U3 {
+id f0;
+U3();
+~U3();
+U3(const U3 &);
+U3(U3 &&);
+U3 & operator=(const U3 &);
+U3 & operator=(U3 &&);
+  };
+
+  // ObjC pointer fields in anonymous union fields delete the defaulted special
+  // functions of the containing class.
+  struct S0 {
+union {
+  id f0; // expected-note 6 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+  char f1;
+};
+  };
+
+  struct S1 {
+union {
+  union { // expected-note 2 {{'S1' is implicitly deleted because variant field '' has a non-trivial}} expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}}
+id f0; // expected-note 2 {{'' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
+char f1;
+  };
+  int f2;
+};
+  };
+
+  U0 *x0;
+  U1 *x1;
+  U2 *x2;
+  U3 *x3;
+  S0 *x4;
+  S1 *x5;
+
+  static union { // expected-error {{call to implicitly-deleted default constructor of}}
+id g0; // expected-note {{default constructor of '' is implicitly deleted because variant field 'g0' is an ObjC pointer}}
+  };
+
+  static union {