[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-07 Thread Akira Hatanaka via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL355662: [ObjC] Emit a boxed expression as a compile-time 
constant if the (authored by ahatanak, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D58729?vs=189809=189811#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D58729

Files:
  cfe/trunk/include/clang/AST/ExprObjC.h
  cfe/trunk/include/clang/Basic/DiagnosticGroups.td
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/lib/AST/ExprConstant.cpp
  cfe/trunk/lib/CodeGen/CGExprConstant.cpp
  cfe/trunk/lib/CodeGen/CGObjC.cpp
  cfe/trunk/lib/Sema/SemaExprObjC.cpp
  cfe/trunk/test/CodeGenObjC/boxing.m
  cfe/trunk/test/SemaObjC/boxing-illegal.m
  cfe/trunk/test/SemaObjC/objc-literal-sig.m
  cfe/trunk/test/SemaObjC/transfer-boxed-string-nullability.m
  cfe/trunk/test/SemaObjCXX/literals.mm

Index: cfe/trunk/include/clang/AST/ExprObjC.h
===
--- cfe/trunk/include/clang/AST/ExprObjC.h
+++ cfe/trunk/include/clang/AST/ExprObjC.h
@@ -138,6 +138,12 @@
 return BoxingMethod;
   }
 
+  // Indicates whether this boxed expression can be emitted as a compile-time
+  // constant.
+  bool isExpressibleAsConstantInitializer() const {
+return !BoxingMethod && SubExpr;
+  }
+
   SourceLocation getAtLoc() const { return Range.getBegin(); }
 
   SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
Index: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
===
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td
@@ -404,6 +404,7 @@
 def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
 def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
 def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">;
+def ObjCBoxing : DiagGroup<"objc-boxing">;
 def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
 def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
 def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
===
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
@@ -918,6 +918,9 @@
   "inconsistent number of instance variables specified">;
 def warn_undef_method_impl : Warning<"method definition for %0 not found">,
   InGroup>;
+def warn_objc_boxing_invalid_utf8_string : Warning<
+  "string is ill-formed as UTF-8 and will become a null %0 when boxed">,
+  InGroup;
 
 def warn_conflicting_overriding_ret_types : Warning<
   "conflicting return type in "
Index: cfe/trunk/test/SemaObjC/boxing-illegal.m
===
--- cfe/trunk/test/SemaObjC/boxing-illegal.m
+++ cfe/trunk/test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
@@ -57,6 +57,19 @@
   box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}}
 }
 
+@interface NSString
+@end
+
+void testStringLiteral() {
+  NSString *s;
+  s = @("abc");
+  s = @(u8"abc");
+  s = @(u"abc"); // expected-error {{illegal type 'unsigned short *' used in a boxed expression}}
+  s = @(U"abc"); // expected-error {{illegal type 'unsigned int *' used in a boxed expression}}
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a boxed expression}}
+}
+
 // rdar://1205
 @class NSMutableDictionary;
 
Index: cfe/trunk/test/SemaObjC/objc-literal-sig.m
===
--- cfe/trunk/test/SemaObjC/objc-literal-sig.m
+++ cfe/trunk/test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

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



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:922
+def warn_objc_boxing_invalid_utf8_string : Warning<
+  "string is ill-formed as UTF-8 and will become a null NSString* when boxed">,
+  InGroup;

rjmccall wrote:
> ahatanak wrote:
> > rjmccall wrote:
> > > Might as well use the `NSStringPointer` type we stash on Sema so that 
> > > this will be the right type even in more obscure environments.
> > I wasn't exactly sure when `NSStringPointer` can be anything other than 
> > `NSString *`.
> Hmm.  It's possible that it can't be for boxing, but I'm pretty sure it can 
> be overridden for string literals, and it's not ridiculous that we'd allow 
> that to be changed for arbitrary boxing as well, so this is good idea 
> regardless.
I agree, it's probably a good idea.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-07 Thread John McCall via Phabricator via cfe-commits
rjmccall accepted this revision.
rjmccall added inline comments.
This revision is now accepted and ready to land.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:922
+def warn_objc_boxing_invalid_utf8_string : Warning<
+  "string is ill-formed as UTF-8 and will become a null NSString* when boxed">,
+  InGroup;

ahatanak wrote:
> rjmccall wrote:
> > Might as well use the `NSStringPointer` type we stash on Sema so that this 
> > will be the right type even in more obscure environments.
> I wasn't exactly sure when `NSStringPointer` can be anything other than 
> `NSString *`.
Hmm.  It's possible that it can't be for boxing, but I'm pretty sure it can be 
overridden for string literals, and it's not ridiculous that we'd allow that to 
be changed for arbitrary boxing as well, so this is good idea regardless.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-07 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak added inline comments.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:922
+def warn_objc_boxing_invalid_utf8_string : Warning<
+  "string is ill-formed as UTF-8 and will become a null NSString* when boxed">,
+  InGroup;

rjmccall wrote:
> Might as well use the `NSStringPointer` type we stash on Sema so that this 
> will be the right type even in more obscure environments.
I wasn't exactly sure when `NSStringPointer` can be anything other than 
`NSString *`.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

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

Use the type of `NSStringPointer` in the diagnostic string.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/boxing-illegal.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,13 +16,23 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+  takesNonNull(@(u8"hey"));
+
+  // If the string isn't a valid UTF-8 string, a diagnostic is emitted since the
+  // boxed expression turns into a message send.
+  takesNonNull(@(u8"\xFF")); // expected-warning {{string is ill-formed as UTF-8}}
+  takesNonNull(@(u8"\xC0\x80")); // expected-warning {{string is ill-formed as UTF-8}}
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
 #ifndef NOWARN
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-#else
-  // expected-no-diagnostics
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
 #endif
 }
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/SemaObjC/boxing-illegal.m
===
--- test/SemaObjC/boxing-illegal.m
+++ test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-07 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: include/clang/Basic/DiagnosticGroups.td:407
 def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">;
+def ObjCBoxing : DiagGroup<"objc-boxing">;
 def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;

Sure.  If we decide to add more things to this warning group, we can pull this 
one out into a sub-group with a more targeted name.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:922
+def warn_objc_boxing_invalid_utf8_string : Warning<
+  "string is ill-formed as UTF-8 and will become a null NSString* when boxed">,
+  InGroup;

Might as well use the `NSStringPointer` type we stash on Sema so that this will 
be the right type even in more obscure environments.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-06 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 189657.
ahatanak marked 2 inline comments as done.
ahatanak added a comment.

Improve diagnostic message.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/boxing-illegal.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,13 +16,23 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+  takesNonNull(@(u8"hey"));
+
+  // If the string isn't a valid UTF-8 string, a diagnostic is emitted since the
+  // boxed expression turns into a message send.
+  takesNonNull(@(u8"\xFF")); // expected-warning {{string is ill-formed as UTF-8}}
+  takesNonNull(@(u8"\xC0\x80")); // expected-warning {{string is ill-formed as UTF-8}}
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
 #ifndef NOWARN
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-#else
-  // expected-no-diagnostics
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
 #endif
 }
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/SemaObjC/boxing-illegal.m
===
--- test/SemaObjC/boxing-illegal.m
+++ test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
@@ 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-06 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: include/clang/Basic/DiagnosticGroups.td:322
 def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
+def InvalidUTF8String : DiagGroup<"invalid-utf8-string">;
 def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;

I think this warning group should mention that this is specific to ObjC boxing 
somehow.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:5807
   "Clang encodes unprefixed narrow string literals as UTF-8">;
+def warn_invalid_utf8_string : Warning<"invalid UTF-8 string">, 
InGroup;
 def err_array_init_different_type : Error<

Maybe "string is ill-formed as UTF-8 and will become a null NSString* when 
boxed", where the type is whatever the type of the box-expression would be?


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-06 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 189630.
ahatanak added a comment.

Diagnose invalid UTF-8 strings in boxed expressions.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/boxing-illegal.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,13 +16,23 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+  takesNonNull(@(u8"hey"));
+
+  // If the string isn't a valid UTF-8 string, a diagnostic is emitted since the
+  // boxed expression turns into a message send.
+  takesNonNull(@(u8"\xFF")); // expected-warning {{invalid UTF-8 string}}
+  takesNonNull(@(u8"\xC0\x80")); // expected-warning {{invalid UTF-8 string}}
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
 #ifndef NOWARN
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-#else
-  // expected-no-diagnostics
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
 #endif
 }
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/SemaObjC/boxing-illegal.m
===
--- test/SemaObjC/boxing-illegal.m
+++ test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
@@ -57,6 +57,19 @@
   box = @(*(enum 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-05 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: test/SemaObjC/boxing-illegal.m:70
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed 
expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a 
boxed expression}}
+}

ahatanak wrote:
> ahatanak wrote:
> > rjmccall wrote:
> > > I don't know what `\p` is supposed to be or why it apparently changes the 
> > > type of the literal to `unsigned char *`, but none of these are ordinary 
> > > string literals that are invalid as UTF-8.  I mean something like "\xFF", 
> > > which still has type `char *` but will fail to parse as UTF-8, which will 
> > > cause normal boxing to fail and return `nil`.
> > Fixed and added test cases. Boxed expressions now have to be valid UTF-8 
> > string literals in order to be emitted as compile-time constants.
> > 
> > If the string literal in a boxed expression is an invalid UTF-8 string, 
> > should we reject it the same way we reject other kinds of string literals 
> > (e.g., UTF-16)?
> Or at least warn about it.
Thanks, fix looks good.  I think a warning would be extremely reasonable. 


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

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



Comment at: test/SemaObjC/boxing-illegal.m:70
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed 
expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a 
boxed expression}}
+}

ahatanak wrote:
> rjmccall wrote:
> > I don't know what `\p` is supposed to be or why it apparently changes the 
> > type of the literal to `unsigned char *`, but none of these are ordinary 
> > string literals that are invalid as UTF-8.  I mean something like "\xFF", 
> > which still has type `char *` but will fail to parse as UTF-8, which will 
> > cause normal boxing to fail and return `nil`.
> Fixed and added test cases. Boxed expressions now have to be valid UTF-8 
> string literals in order to be emitted as compile-time constants.
> 
> If the string literal in a boxed expression is an invalid UTF-8 string, 
> should we reject it the same way we reject other kinds of string literals 
> (e.g., UTF-16)?
Or at least warn about it.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-05 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak added inline comments.



Comment at: test/SemaObjC/boxing-illegal.m:70
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed 
expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a 
boxed expression}}
+}

rjmccall wrote:
> I don't know what `\p` is supposed to be or why it apparently changes the 
> type of the literal to `unsigned char *`, but none of these are ordinary 
> string literals that are invalid as UTF-8.  I mean something like "\xFF", 
> which still has type `char *` but will fail to parse as UTF-8, which will 
> cause normal boxing to fail and return `nil`.
Fixed and added test cases. Boxed expressions now have to be valid UTF-8 string 
literals in order to be emitted as compile-time constants.

If the string literal in a boxed expression is an invalid UTF-8 string, should 
we reject it the same way we reject other kinds of string literals (e.g., 
UTF-16)?


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-05 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 189436.
ahatanak marked 2 inline comments as done.
ahatanak added a comment.

If the string literal used for the boxed expression isn't a valid UTF-8 string, 
don't emit a compile-time constant.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/boxing-illegal.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,12 +16,24 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+  takesNonNull(@(u8"hey"));
+
+  // If the string isn't a valid UTF-8 string, a diagnostic is emitted since the
+  // boxed expression turns into a message send.
+  takesNonNull(@(u8"\xFF"));
+  takesNonNull(@(u8"\xC8"));
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
 #ifndef NOWARN
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
-  // expected-warning@-3 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-7 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
+  // expected-warning@-5 {{implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'}}
 #else
   // expected-no-diagnostics
 #endif
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/SemaObjC/boxing-illegal.m
===
--- test/SemaObjC/boxing-illegal.m
+++ test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
@@ -57,6 +57,19 @@
   box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-03-04 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: test/SemaObjC/boxing-illegal.m:70
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed 
expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a 
boxed expression}}
+}

I don't know what `\p` is supposed to be or why it apparently changes the type 
of the literal to `unsigned char *`, but none of these are ordinary string 
literals that are invalid as UTF-8.  I mean something like "\xFF", which still 
has type `char *` but will fail to parse as UTF-8, which will cause normal 
boxing to fail and return `nil`.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-02-28 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak added inline comments.



Comment at: lib/Sema/SemaExprObjC.cpp:534
+NSStringPointer, NSStringPointer);
+return new (Context) ObjCBoxedExpr(SL, BoxedType, nullptr, SR);
+  }

rjmccall wrote:
> ahatanak wrote:
> > rjmccall wrote:
> > > You're implicitly dropping sugar from the source expression here; I 
> > > really think you should preserve that, and if it means you end up having 
> > > to look through array-decay expressions, that's not the end of the world.
> > > 
> > > The need for a special case here is just to allow us to compile these 
> > > even if there isn't a boxing method available?
> > > 
> > > Do you need to restrict the type of the string literal so that it doesn't 
> > > apply to e.g. wide strings?
> > Line 516 checks that the pointee type has the same unqualified type as 
> > 'char'. If the string literal inside the parentheses is of a wider type 
> > (e.g., `@(u"abc")`), this piece of code won't be executed, and a diagnostic 
> > is emitted later ("illegal type 'const char16_t *' used in a boxed 
> > expression").
> > 
> > The original motivation for special-casing string literals inside boxed 
> > expressions was to silence the `-Wnullable-to-nonnull-conversion` warning 
> > mentioned here: https://oleb.net/2018/@keypath/. The warning is issued 
> > because the return type of `stringWithUTF8String` is nullable.
> > 
> > ```
> > ...
> > + (nullable instancetype)stringWithUTF8String:(const char 
> > *)nullTerminatedCString;
> > ...
> > 
> > NSString * _Nonnull ptr = @("abc");  // expected-error {{implicit 
> > conversion from nullable pointer 'NSString * _Nullable' to non-nullable 
> > pointer type 'NSString * _Nonnull'}}
> > ```
> I see.  So in addition to guaranteeing to skip the boxing call, you'd like to 
> adjust the type to report the result as non-null, which we can do because 
> we're unconditionally making a constant string.  Makes sense.
> 
> However, I think you need to check that the string is valid UTF-8 or else 
> this is semantics-changing, since such strings are rejected by 
> `+stringWithUTF8String:` (which is why it returns a nullable pointer at all). 
>  It should be alright to warn about strings that are statically known to be 
> invalid UTF-8, but you'll then need to emit them using the normal boxing 
> method.
clang already rejects boxed expressions that are string literals with a 
character encoding incompatible with UTF-8. Also, we reach this part of the 
code only if the string is UTF-8 or ASCII (see the assertion I added). I added 
a test case to test/SemaObjC/boxing-illegal.m that shows clang rejects strings 
incompatible with UTF-8.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-02-28 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak updated this revision to Diff 188794.
ahatanak marked 4 inline comments as done.
ahatanak added a comment.

Address review comments.

- Preserve sugar when creating an `ObjCBoxedExpr` in `Sema::BuildObjCBoxedExpr`.
- Add a test case to test/SemaObjC/boxing-illegal.m that shows clang rejects a 
string literal in a boxed expression if its character encoding is incompatible 
with UTF-8.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/boxing-illegal.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,6 +16,11 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+  takesNonNull(@(u8"hey"));
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/SemaObjC/boxing-illegal.m
===
--- test/SemaObjC/boxing-illegal.m
+++ test/SemaObjC/boxing-illegal.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes -fpascal-strings %s
 
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
@@ -57,6 +57,19 @@
   box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}}
 }
 
+@interface NSString
+@end
+
+void testStringLiteral() {
+  NSString *s;
+  s = @("abc");
+  s = @(u8"abc");
+  s = @(u"abc"); // expected-error {{illegal type 'unsigned short *' used in a boxed expression}}
+  s = @(U"abc"); // expected-error {{illegal type 'unsigned int *' used in a boxed expression}}
+  s = @(L"abc"); // expected-error {{illegal type 'int *' used in a boxed expression}}
+  s = @("\pabc"); // expected-error {{illegal type 'unsigned char *' used in a boxed expression}}
+}
+
 // rdar://1205
 @class NSMutableDictionary;
 
Index: test/CodeGenObjC/boxing.m
===
--- test/CodeGenObjC/boxing.m
+++ test/CodeGenObjC/boxing.m
@@ -53,6 +53,9 @@
 + (id)stringWithUTF8String:(const char *)nullTerminatedCString;
 @end
 
+// CHECK: [[V0:%.*]] = type opaque
+// CHECK: [[STRUCT_NSCONSTANT_STRING_TAG:%.*]] = type { i32*, i32, i8*, i64 }
+
 // CHECK: [[WithIntMeth:@.*]] = 

[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-02-27 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/Sema/SemaExprObjC.cpp:534
+NSStringPointer, NSStringPointer);
+return new (Context) ObjCBoxedExpr(SL, BoxedType, nullptr, SR);
+  }

ahatanak wrote:
> rjmccall wrote:
> > You're implicitly dropping sugar from the source expression here; I really 
> > think you should preserve that, and if it means you end up having to look 
> > through array-decay expressions, that's not the end of the world.
> > 
> > The need for a special case here is just to allow us to compile these even 
> > if there isn't a boxing method available?
> > 
> > Do you need to restrict the type of the string literal so that it doesn't 
> > apply to e.g. wide strings?
> Line 516 checks that the pointee type has the same unqualified type as 
> 'char'. If the string literal inside the parentheses is of a wider type 
> (e.g., `@(u"abc")`), this piece of code won't be executed, and a diagnostic 
> is emitted later ("illegal type 'const char16_t *' used in a boxed 
> expression").
> 
> The original motivation for special-casing string literals inside boxed 
> expressions was to silence the `-Wnullable-to-nonnull-conversion` warning 
> mentioned here: https://oleb.net/2018/@keypath/. The warning is issued 
> because the return type of `stringWithUTF8String` is nullable.
> 
> ```
> ...
> + (nullable instancetype)stringWithUTF8String:(const char 
> *)nullTerminatedCString;
> ...
> 
> NSString * _Nonnull ptr = @("abc");  // expected-error {{implicit conversion 
> from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 
> 'NSString * _Nonnull'}}
> ```
I see.  So in addition to guaranteeing to skip the boxing call, you'd like to 
adjust the type to report the result as non-null, which we can do because we're 
unconditionally making a constant string.  Makes sense.

However, I think you need to check that the string is valid UTF-8 or else this 
is semantics-changing, since such strings are rejected by 
`+stringWithUTF8String:` (which is why it returns a nullable pointer at all).  
It should be alright to warn about strings that are statically known to be 
invalid UTF-8, but you'll then need to emit them using the normal boxing method.


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

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



Comment at: lib/Sema/SemaExprObjC.cpp:534
+NSStringPointer, NSStringPointer);
+return new (Context) ObjCBoxedExpr(SL, BoxedType, nullptr, SR);
+  }

rjmccall wrote:
> You're implicitly dropping sugar from the source expression here; I really 
> think you should preserve that, and if it means you end up having to look 
> through array-decay expressions, that's not the end of the world.
> 
> The need for a special case here is just to allow us to compile these even if 
> there isn't a boxing method available?
> 
> Do you need to restrict the type of the string literal so that it doesn't 
> apply to e.g. wide strings?
Line 516 checks that the pointee type has the same unqualified type as 'char'. 
If the string literal inside the parentheses is of a wider type (e.g., 
`@(u"abc")`), this piece of code won't be executed, and a diagnostic is emitted 
later ("illegal type 'const char16_t *' used in a boxed expression").

The original motivation for special-casing string literals inside boxed 
expressions was to silence the `-Wnullable-to-nonnull-conversion` warning 
mentioned here: https://oleb.net/2018/@keypath/. The warning is issued because 
the return type of `stringWithUTF8String` is nullable.

```
...
+ (nullable instancetype)stringWithUTF8String:(const char 
*)nullTerminatedCString;
...

NSString * _Nonnull ptr = @("abc");  // expected-error {{implicit conversion 
from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 
'NSString * _Nonnull'}}
```


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-02-27 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/CodeGen/CGExprConstant.cpp:1793
+ "this boxed expression can't be emitted as a compile-time constant");
+  return emitConstantObjCStringLiteral(cast(E->getSubExpr()),
+   E->getType(), CGM);

`IgnoreParens`.



Comment at: lib/Sema/SemaExprObjC.cpp:534
+NSStringPointer, NSStringPointer);
+return new (Context) ObjCBoxedExpr(SL, BoxedType, nullptr, SR);
+  }

You're implicitly dropping sugar from the source expression here; I really 
think you should preserve that, and if it means you end up having to look 
through array-decay expressions, that's not the end of the world.

The need for a special case here is just to allow us to compile these even if 
there isn't a boxing method available?

Do you need to restrict the type of the string literal so that it doesn't apply 
to e.g. wide strings?


Repository:
  rC Clang

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

https://reviews.llvm.org/D58729



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


[PATCH] D58729: Emit boxed expression as a compile-time constant if the expression inside the parentheses is a string literal

2019-02-27 Thread Akira Hatanaka via Phabricator via cfe-commits
ahatanak created this revision.
ahatanak added reviewers: rjmccall, arphaman.
ahatanak added a project: clang.
Herald added subscribers: jdoerfert, dexonsmith, jkorous.

clang currently emits an expression like `@("abc")` as a message send to 
`stringWithUTF8String`. This patch makes changes so that a compile-time 
constant is emitted instead when the expression inside the parentheses is a 
string literal. I think it's possible to do the same optimization for constant 
expressions that evaluate to zero-terminated strings (see the example below), 
but I'm leaving that for future work.

  constexpr const char *foo() { return "abc"; }
  
  void test() {
NSString *s = @(foo());
  }

The original motivation for the patch is to silence the 
`-Wnullable-to-nonnull-conversion` warning that clang started emitting after 
r317727:
The https://oleb.net/2018/@keypath/.

rdar://problem/42684601


Repository:
  rC Clang

https://reviews.llvm.org/D58729

Files:
  include/clang/AST/ExprObjC.h
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGObjC.cpp
  lib/Sema/SemaExprObjC.cpp
  test/CodeGenObjC/boxing.m
  test/SemaObjC/objc-literal-sig.m
  test/SemaObjC/transfer-boxed-string-nullability.m
  test/SemaObjCXX/literals.mm

Index: test/SemaObjCXX/literals.mm
===
--- test/SemaObjCXX/literals.mm
+++ test/SemaObjCXX/literals.mm
@@ -50,6 +50,9 @@
 + (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
 @end
 
+@interface NSString
+@end
+
 template
 struct ConvertibleTo {
   operator T();
@@ -185,3 +188,8 @@
 void test_dictionary_colon() {
   id dict = @{ key : value };
 }
+
+void testConstExpr() {
+  constexpr NSString *t0 = @"abc";
+  constexpr NSString *t1 = @("abc");
+}
Index: test/SemaObjC/transfer-boxed-string-nullability.m
===
--- test/SemaObjC/transfer-boxed-string-nullability.m
+++ test/SemaObjC/transfer-boxed-string-nullability.m
@@ -16,6 +16,10 @@
 void takesNonNull(NSString * _Nonnull ptr);
 
 void testBoxedString() {
+  // No diagnostic emitted as this doesn't need a stringWithUTF8String message
+  // send.
+  takesNonNull(@("hey"));
+
   const char *str = "hey";
   takesNonNull([NSString stringWithUTF8String:str]);
   takesNonNull(@(str));
Index: test/SemaObjC/objc-literal-sig.m
===
--- test/SemaObjC/objc-literal-sig.m
+++ test/SemaObjC/objc-literal-sig.m
@@ -39,6 +39,8 @@
 
 // All tests are doubled to make sure that a bad method is not saved
 // and then used un-checked.
+const char *getStr(void);
+
 void test_sig() {
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
   (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
@@ -46,6 +48,6 @@
   id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
   id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
   id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
-  id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
-  id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+  id str2 = @(getStr()); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
 }
Index: test/CodeGenObjC/boxing.m
===
--- test/CodeGenObjC/boxing.m
+++ test/CodeGenObjC/boxing.m
@@ -53,6 +53,9 @@
 + (id)stringWithUTF8String:(const char *)nullTerminatedCString;
 @end
 
+// CHECK: [[V0:%.*]] = type opaque
+// CHECK: [[STRUCT_NSCONSTANT_STRING_TAG:%.*]] = type { i32*, i32, i8*, i64 }
+
 // CHECK: [[WithIntMeth:@.*]] = private unnamed_addr constant [15 x i8] c"numberWithInt:\00"
 // CHECK: [[WithIntSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[WithIntMeth]]
 // CHECK: [[WithCharMeth:@.*]] = private unnamed_addr constant [16 x i8] c"numberWithChar:\00"
@@ -65,8 +68,12 @@
 // CHECK: [[WithUnsignedIntegerSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([27 x i8], [27 x i8]* [[WithUnsignedIntegerMeth]]
 // CHECK: [[stringWithUTF8StringMeth:@.*]] = private unnamed_addr constant [22 x i8] c"stringWithUTF8String:\00"
 // CHECK: [[stringWithUTF8StringSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds