aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--test/FixIt/fixit-objc.m32
2 files changed, 62 insertions, 3 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 34b9eb843b..ec6ca2a9ac 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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;
}
diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m
index b732e2f973..687405c7ce 100644
--- a/test/FixIt/fixit-objc.m
+++ b/test/FixIt/fixit-objc.m
@@ -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";
+}