]> granicus.if.org Git - clang/commitdiff
When trying to assign a regular string literal to an Objective-C 'id' type or a point...
authorAnders Carlsson <andersca@mac.com>
Tue, 10 Nov 2009 04:46:30 +0000 (04:46 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 10 Nov 2009 04:46:30 +0000 (04:46 +0000)
@class NSString;

@interface Test
+ (void)test:(NSString *)string;
@end

void g(NSString *a);

void f() {
  NSString *a = "Foo";
  g("Foo");
  [Test test:"Foo"];
}

will produce

t.m:10:17: warning: incompatible pointer types initializing 'char [4]', expected 'NSString *'
  NSString *a = "Foo";
                ^~~~~
                @
t.m:11:5: warning: incompatible pointer types passing 'char [4]', expected 'NSString *'
  g("Foo");
    ^~~~~
    @
t.m:12:14: warning: incompatible pointer types sending 'char [4]', expected 'NSString *'
  [Test test:"Foo"];
             ^~~~~
             @
3 diagnostics generated.

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

lib/Sema/SemaExpr.cpp
test/FixIt/fixit-objc.m

index 34b9eb843bb6aac9e256ec5932a95b27d40978a8..ec6ca2a9ac02f5badcfcd9fd719100865fdce063 100644 (file)
@@ -6201,6 +6201,34 @@ Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
   return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
 }
 
+static void 
+MakeObjCStringLiteralCodeModificationHint(Sema& SemaRef,
+                                          QualType DstType,
+                                          Expr *SrcExpr,
+                                          CodeModificationHint &Hint) {
+  if (!SemaRef.getLangOptions().ObjC1)
+    return;
+  
+  const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
+  if (!PT)
+    return;
+
+  // Check if the destination is of type 'id'.
+  if (!PT->isObjCIdType()) {
+    // Check if the destination is the 'NSString' interface.
+    const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+    if (!ID || !ID->getIdentifier()->isStr("NSString"))
+      return;
+  }
+  
+  // Strip off any parens and casts.
+  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());
+  if (!SL || SL->isWide())
+    return;
+  
+  Hint = CodeModificationHint::CreateInsertion(SL->getLocStart(), "@");
+}
+
 bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
                                     SourceLocation Loc,
                                     QualType DstType, QualType SrcType,
@@ -6208,6 +6236,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
   // Decode the result (notice that AST's are still created for extensions).
   bool isInvalid = false;
   unsigned DiagKind;
+  CodeModificationHint Hint;
+  
   switch (ConvTy) {
   default: assert(0 && "Unknown conversion type");
   case Compatible: return false;
@@ -6218,6 +6248,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
     DiagKind = diag::ext_typecheck_convert_int_pointer;
     break;
   case IncompatiblePointer:
+    MakeObjCStringLiteralCodeModificationHint(*this, DstType, SrcExpr, Hint);
     DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
     break;
   case IncompatiblePointerSign:
@@ -6265,7 +6296,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
   }
 
   Diag(Loc, DiagKind) << DstType << SrcType << Flavor
-    << SrcExpr->getSourceRange();
+    << SrcExpr->getSourceRange() << Hint;
   return isInvalid;
 }
 
index b732e2f97346817845914163663f78c16b830704..687405c7ce385f27dae7eea9de9f5004a3d91cb3 100644 (file)
@@ -1,8 +1,36 @@
-// RUN: clang-cc -fsyntax-only -fixit-at=fixit-at.c:3:1 %s -o %t.m
-// RUN: clang-cc -verify %t.m
+// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o %t
+// RUN: clang-cc -fsyntax-only -pedantic -x objective-c %t -verify
+
+/* This is a test of the various code modification hints that are
+   provided as part of warning or extension diagnostics. All of the
+   warnings will be fixed by -fixit, and the resulting file should
+   compile cleanly with -Werror -pedantic. */
 
 @protocol X;
 
 void foo() {
   <X> *P;    // should be fixed to 'id<X>'.
 }
+
+@class A;
+@class NSString;
+
+@interface Test
+- (void)test:(NSString *)string;
+
+@property (copy) NSString *property;
+@end
+
+void g(NSString *a);
+void h(id a);
+
+void f(Test *t) {
+  NSString *a = "Foo";
+  id b = "Foo";
+  A* c = "Foo"; // expected-warning {{incompatible pointer types initializing 'char [4]', expected 'A *'}}
+  g("Foo");
+  h("Foo");
+  h(("Foo"));
+  [t test:"Foo"];
+  t.property = "Foo";
+}