]> granicus.if.org Git - clang/commitdiff
objective-c++: Type of an objc string literal is NSString, not 'id'.
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 23 Feb 2012 22:51:36 +0000 (22:51 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 23 Feb 2012 22:51:36 +0000 (22:51 +0000)
// rdar://10907410

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151296 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
lib/Sema/SemaExprObjC.cpp
test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
test/PCH/objc_exprs.m
test/SemaObjC/NSString-type.m [new file with mode: 0644]
test/SemaObjCXX/NSString-type.mm [new file with mode: 0644]

index 26e91959624e7315cdb8866af1771080ee7e6e3f..723dd1748d41041bdc1df8261929f85869636c74 100644 (file)
@@ -218,6 +218,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   QualType ObjCConstantStringType;
   mutable RecordDecl *CFConstantStringTypeDecl;
+  
+  QualType ObjCNSStringType;
 
   /// \brief The typedef declaration for the Objective-C "instancetype" type.
   TypedefDecl *ObjCInstanceTypeDecl;
@@ -944,6 +946,14 @@ public:
     return ObjCConstantStringType;
   }
 
+  QualType getObjCNSStringType() const {
+    return ObjCNSStringType;
+  }
+  
+  void setObjCNSStringType(QualType T) {
+    ObjCNSStringType = T;
+  }
+  
   /// \brief Retrieve the type that 'id' has been defined to, which may be
   /// different from the built-in 'id' if 'id' has been typedef'd.
   QualType getObjCIdRedefinitionType() const {
index e0420c1faff98fc82702cddd91d50ca1d673b252..ec5329c4d4cb6488cadd186f76caab22677c7d41 100644 (file)
@@ -113,9 +113,21 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
       Ty = Context.getObjCConstantStringInterface();
       Ty = Context.getObjCObjectPointerType(Ty);
     } else {
-      // If there is no NSString interface defined then treat constant
-      // strings as untyped objects and let the runtime figure it out later.
-      Ty = Context.getObjCIdType();
+      // If there is no NSString interface defined, implicitly declare
+      // a @class NSString; and use that instead. This is to make sure
+      // type of an NSString literal is represented correctly, instead of
+      // being an 'id' type.
+      Ty = Context.getObjCNSStringType();
+      if (Ty.isNull()) {
+        ObjCInterfaceDecl *NSStringIDecl = 
+          ObjCInterfaceDecl::Create (Context, 
+                                     Context.getTranslationUnitDecl(), 
+                                     SourceLocation(), NSIdent, 
+                                     0, SourceLocation());
+        Ty = Context.getObjCInterfaceType(NSStringIDecl);
+        Context.setObjCNSStringType(Ty);
+      }
+      Ty = Context.getObjCObjectPointerType(Ty);
     }
   }
 
index eba72bac9f7120c61ad2b2fff6d516dc7f89ad57..96bc7a9b3e7e91837c346892ed8fd5483d0af6ca 100644 (file)
@@ -48,7 +48,7 @@ void createFoo4() {
 }
 
 void createFoo5() {
-  MyClass *obj = @"";  
+  MyClass *obj = (id)@"";  
   
   double d = [obj doubleM]; // no-warning
 }
index c37968b7b93821f413f242fb994204769afdbd54..1f971e794133f0ad8f243f730538f70998fb8502 100644 (file)
@@ -6,7 +6,7 @@
 // RUN: %clang_cc1 -fblocks -include-pch %t -fsyntax-only -verify %s 
 
 // Expressions
-int *A1 = (objc_string)0;   // expected-warning {{aka 'id'}}
+int *A1 = (objc_string)0;   // expected-warning {{aka 'NSString *'}}
 
 char A2 = (objc_encode){};  // expected-error {{not a compile-time constant}} \
                                expected-warning {{char [2]}}
diff --git a/test/SemaObjC/NSString-type.m b/test/SemaObjC/NSString-type.m
new file mode 100644 (file)
index 0000000..3b4857a
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1  -triple x86_64-apple-darwin10 -fblocks -fsyntax-only -verify %s
+// rdar://10907410
+
+void test(id pid, Class pclass) {
+  void (^block)(void) = @"help"; // expected-error {{initializing 'void (^)(void)' with an expression of incompatible type 'NSString *'}}
+  void (^block1)(void) = pid;
+  void (^block2)(void) = @"help"; // expected-error {{initializing 'void (^)(void)' with an expression of incompatible type 'NSString *'}}
+  void (^block3)(void) = @"help"; // expected-error {{initializing 'void (^)(void)' with an expression of incompatible type 'NSString *'}}
+}
+
diff --git a/test/SemaObjCXX/NSString-type.mm b/test/SemaObjCXX/NSString-type.mm
new file mode 100644 (file)
index 0000000..1033866
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -fsyntax-only -verify %s
+// rdar://10907410
+
+void test(id pid, Class pclass) {
+  void (^block)(void) = @"help"; // expected-error {{cannot initialize a variable of type 'void (^)()' with an rvalue of type 'NSString *'}}
+  void (^block1)(void) = pid;
+  void (^block2)(void) = @"help"; // expected-error {{cannot initialize a variable of type 'void (^)()' with an rvalue of type 'NSString *'}}
+  void (^block3)(void) = @"help"; // expected-error {{cannot initialize a variable of type 'void (^)()' with an rvalue of type 'NSString *'}}
+}
+