From: Fariborz Jahanian Date: Tue, 17 Dec 2013 19:33:43 +0000 (+0000) Subject: Objective-C. Make diagnostics and fix-its consistent X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7fe35ba9ec58843b4b997d03daaaa219f1ad1d5f;p=clang Objective-C. Make diagnostics and fix-its consistent when diagnosing casting of a cstring literal to NSString in default and -fobjc-arc mode. // rdar://14106083 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@197515 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 14b01040de..1be01a2ed4 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -609,8 +609,6 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [ ObjCStringComparison ]>; -def ObjCLiteralMissingAtSign : DiagGroup<"objc-literal-missing-atsign">; - // Inline ASM warnings. def ASMOperandWidths : DiagGroup<"asm-operand-widths">; def ASM : DiagGroup<"asm", [ diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d9d22ab5ad..19456297f2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1911,8 +1911,8 @@ def warn_objc_literal_comparison : Warning< "direct comparison of %select{an array literal|a dictionary literal|" "a numeric literal|a boxed expression|}0 has undefined behavior">, InGroup; -def warn_missing_atsign_prefix : Warning< - "string literal must be prefixed by '@' ">, InGroup; +def err_missing_atsign_prefix : Error< + "string literal must be prefixed by '@' ">; def warn_objc_string_literal_comparison : Warning< "direct comparison of a string literal has undefined behavior">, InGroup; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1bd423cdde..4f05a0c1eb 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6900,6 +6900,10 @@ public: QualType DestType, QualType SrcType, Expr *&SrcExpr); + StringLiteral * ConversionToObjCStringLiteralCheck(QualType DstType, + Expr *SrcExpr, FixItHint &Hint, + bool &IsNSString); + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); /// \brief Check whether the given new method is a valid override of the diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index e4a6102b06..0597a998c4 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10587,22 +10587,23 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { return Owned(new (Context) GNUNullExpr(Ty, TokenLoc)); } -static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, - Expr *SrcExpr, FixItHint &Hint, - bool &IsNSString) { - if (!SemaRef.getLangOpts().ObjC1) - return; +StringLiteral * +Sema::ConversionToObjCStringLiteralCheck(QualType DstType, + Expr *SrcExpr, FixItHint &Hint, + bool &IsNSString) { + if (!getLangOpts().ObjC1) + return 0; const ObjCObjectPointerType *PT = DstType->getAs(); if (!PT) - return; + return 0; // 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; + return 0; IsNSString = true; } @@ -10616,9 +10617,9 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, StringLiteral *SL = dyn_cast(SrcExpr); if (!SL || !SL->isAscii()) - return; - + return 0; Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@"); + return SL; } bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, @@ -10655,7 +10656,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, MayHaveConvFixit = true; break; case IncompatiblePointer: - MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString); + ConversionToObjCStringLiteralCheck(DstType, SrcExpr, Hint, IsNSString); DiagKind = (Action == AA_Passing_CFAudited ? diag::err_arc_typecheck_convert_incompatible_pointer : @@ -10670,7 +10671,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, DstType = DstType.getUnqualifiedType(); } else if (IsNSString && !Hint.isNull()) - DiagKind = diag::warn_missing_atsign_prefix; + DiagKind = diag::err_missing_atsign_prefix; MayHaveConvFixit = true; break; case IncompatiblePointerSign: diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 905c080e47..f312839a9d 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -3612,6 +3612,17 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, CCK != CCK_ImplicitConversion) return ACR_unbridged; + // Do not issue bridge cast" diagnostic when implicit casting a cstring + // to 'NSString *'. Let caller issue a normal mismatched diagnostic with + // suitable fix-it. + if (castACTC == ACTC_retainable && exprACTC == ACTC_none) { + bool IsNSString = false; + FixItHint Hint; + if (ConversionToObjCStringLiteralCheck( + castType, castExpr, Hint, IsNSString) && IsNSString) + return ACR_okay; + } + // Do not issue "bridge cast" diagnostic when implicit casting // a retainable object to a CF type parameter belonging to an audited // CF API function. Let caller issue a normal type mismatched diagnostic diff --git a/test/FixIt/fixit-objc-arc.m b/test/FixIt/fixit-objc-arc.m new file mode 100644 index 0000000000..19a61b4108 --- /dev/null +++ b/test/FixIt/fixit-objc-arc.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -pedantic -verify %s +// RUN: cp %s %t +// RUN: not %clang_cc1 -pedantic -fobjc-arc -fixit -x objective-c %t +// RUN: %clang_cc1 -pedantic -fobjc-arc -Werror -x objective-c %t +// rdar://14106083 + +@class A; +@class NSString; + +@interface Test +- (void)test:(NSString *)string; // expected-note{{passing argument to parameter 'string' here}} + +@property (copy) NSString *property; +@end + +void g(NSString *a); // expected-note{{passing argument to parameter 'a' here}} +void h(id a); + +void f(Test *t) { + NSString *a = "Foo"; // expected-error {{string literal must be prefixed by '@'}} + g("Foo"); // expected-error {{string literal must be prefixed by '@'}} + [t test:"Foo"]; // expected-error {{string literal must be prefixed by '@'}} + t.property = "Foo"; // expected-error {{string literal must be prefixed by '@'}} +} diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m index 7c4776ae71..17de36528e 100644 --- a/test/FixIt/fixit-objc.m +++ b/test/FixIt/fixit-objc.m @@ -27,13 +27,13 @@ void g(NSString *a); // expected-note{{passing argument to parameter 'a' here}} void h(id a); // expected-note 2{{passing argument to parameter 'a' here}} void f(Test *t) { - NSString *a = "Foo"; // expected-warning {{string literal must be prefixed by '@'}} + NSString *a = "Foo"; // expected-error {{string literal must be prefixed by '@'}} id b = "Foo"; // expected-warning {{incompatible pointer types initializing 'id' with an expression of type 'char [4]'}} - g("Foo"); // expected-warning {{string literal must be prefixed by '@'}} + g("Foo"); // expected-error {{string literal must be prefixed by '@'}} h("Foo"); // expected-warning{{incompatible pointer types passing 'char [4]' to parameter of type 'id'}} h(("Foo")); // expected-warning{{incompatible pointer types passing 'char [4]' to parameter of type 'id'}} - [t test:"Foo"]; // expected-warning {{string literal must be prefixed by '@'}} - t.property = "Foo"; // expected-warning {{string literal must be prefixed by '@'}} + [t test:"Foo"]; // expected-error {{string literal must be prefixed by '@'}} + t.property = "Foo"; // expected-error {{string literal must be prefixed by '@'}} // [t test:@"Foo"]]; // expected-error{{extraneous ']' before ';'}}