зеркало из https://github.com/microsoft/clang-1.git
When trying to assign a regular string literal to an Objective-C 'id' type or a pointer to an NSString, emit a code insertion hint that turns it into an Objective-C string. For example:
@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
This commit is contained in:
Родитель
2f019aadc9
Коммит
b76cd3d0c1
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче