Skip to content

Commit bd714e9

Browse files
author
Fariborz Jahanian
committed
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 llvm-svn: 197515
1 parent e4083f9 commit bd714e9

File tree

7 files changed

+57
-19
lines changed

7 files changed

+57
-19
lines changed

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,6 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
609609
ObjCStringComparison
610610
]>;
611611

612-
def ObjCLiteralMissingAtSign : DiagGroup<"objc-literal-missing-atsign">;
613-
614612
// Inline ASM warnings.
615613
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
616614
def ASM : DiagGroup<"asm", [

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,8 +1911,8 @@ def warn_objc_literal_comparison : Warning<
19111911
"direct comparison of %select{an array literal|a dictionary literal|"
19121912
"a numeric literal|a boxed expression|}0 has undefined behavior">,
19131913
InGroup<ObjCLiteralComparison>;
1914-
def warn_missing_atsign_prefix : Warning<
1915-
"string literal must be prefixed by '@' ">, InGroup<ObjCLiteralMissingAtSign>;
1914+
def err_missing_atsign_prefix : Error<
1915+
"string literal must be prefixed by '@' ">;
19161916
def warn_objc_string_literal_comparison : Warning<
19171917
"direct comparison of a string literal has undefined behavior">,
19181918
InGroup<ObjCStringComparison>;

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6900,6 +6900,10 @@ class Sema {
69006900
QualType DestType, QualType SrcType,
69016901
Expr *&SrcExpr);
69026902

6903+
StringLiteral * ConversionToObjCStringLiteralCheck(QualType DstType,
6904+
Expr *SrcExpr, FixItHint &Hint,
6905+
bool &IsNSString);
6906+
69036907
bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
69046908

69056909
/// \brief Check whether the given new method is a valid override of the

clang/lib/Sema/SemaExpr.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10587,22 +10587,23 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
1058710587
return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
1058810588
}
1058910589

10590-
static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
10591-
Expr *SrcExpr, FixItHint &Hint,
10592-
bool &IsNSString) {
10593-
if (!SemaRef.getLangOpts().ObjC1)
10594-
return;
10590+
StringLiteral *
10591+
Sema::ConversionToObjCStringLiteralCheck(QualType DstType,
10592+
Expr *SrcExpr, FixItHint &Hint,
10593+
bool &IsNSString) {
10594+
if (!getLangOpts().ObjC1)
10595+
return 0;
1059510596

1059610597
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
1059710598
if (!PT)
10598-
return;
10599+
return 0;
1059910600

1060010601
// Check if the destination is of type 'id'.
1060110602
if (!PT->isObjCIdType()) {
1060210603
// Check if the destination is the 'NSString' interface.
1060310604
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
1060410605
if (!ID || !ID->getIdentifier()->isStr("NSString"))
10605-
return;
10606+
return 0;
1060610607
IsNSString = true;
1060710608
}
1060810609

@@ -10616,9 +10617,9 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
1061610617

1061710618
StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
1061810619
if (!SL || !SL->isAscii())
10619-
return;
10620-
10620+
return 0;
1062110621
Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@");
10622+
return SL;
1062210623
}
1062310624

1062410625
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
@@ -10655,7 +10656,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
1065510656
MayHaveConvFixit = true;
1065610657
break;
1065710658
case IncompatiblePointer:
10658-
MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
10659+
ConversionToObjCStringLiteralCheck(DstType, SrcExpr, Hint, IsNSString);
1065910660
DiagKind =
1066010661
(Action == AA_Passing_CFAudited ?
1066110662
diag::err_arc_typecheck_convert_incompatible_pointer :
@@ -10670,7 +10671,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
1067010671
DstType = DstType.getUnqualifiedType();
1067110672
}
1067210673
else if (IsNSString && !Hint.isNull())
10673-
DiagKind = diag::warn_missing_atsign_prefix;
10674+
DiagKind = diag::err_missing_atsign_prefix;
1067410675
MayHaveConvFixit = true;
1067510676
break;
1067610677
case IncompatiblePointerSign:

clang/lib/Sema/SemaExprObjC.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3612,6 +3612,17 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
36123612
CCK != CCK_ImplicitConversion)
36133613
return ACR_unbridged;
36143614

3615+
// Do not issue bridge cast" diagnostic when implicit casting a cstring
3616+
// to 'NSString *'. Let caller issue a normal mismatched diagnostic with
3617+
// suitable fix-it.
3618+
if (castACTC == ACTC_retainable && exprACTC == ACTC_none) {
3619+
bool IsNSString = false;
3620+
FixItHint Hint;
3621+
if (ConversionToObjCStringLiteralCheck(
3622+
castType, castExpr, Hint, IsNSString) && IsNSString)
3623+
return ACR_okay;
3624+
}
3625+
36153626
// Do not issue "bridge cast" diagnostic when implicit casting
36163627
// a retainable object to a CF type parameter belonging to an audited
36173628
// CF API function. Let caller issue a normal type mismatched diagnostic

clang/test/FixIt/fixit-objc-arc.m

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %clang_cc1 -pedantic -verify %s
2+
// RUN: cp %s %t
3+
// RUN: not %clang_cc1 -pedantic -fobjc-arc -fixit -x objective-c %t
4+
// RUN: %clang_cc1 -pedantic -fobjc-arc -Werror -x objective-c %t
5+
// rdar://14106083
6+
7+
@class A;
8+
@class NSString;
9+
10+
@interface Test
11+
- (void)test:(NSString *)string; // expected-note{{passing argument to parameter 'string' here}}
12+
13+
@property (copy) NSString *property;
14+
@end
15+
16+
void g(NSString *a); // expected-note{{passing argument to parameter 'a' here}}
17+
void h(id a);
18+
19+
void f(Test *t) {
20+
NSString *a = "Foo"; // expected-error {{string literal must be prefixed by '@'}}
21+
g("Foo"); // expected-error {{string literal must be prefixed by '@'}}
22+
[t test:"Foo"]; // expected-error {{string literal must be prefixed by '@'}}
23+
t.property = "Foo"; // expected-error {{string literal must be prefixed by '@'}}
24+
}

clang/test/FixIt/fixit-objc.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ - (void)test:(NSString *)string; // expected-note{{passing argument to parameter
2727
void h(id a); // expected-note 2{{passing argument to parameter 'a' here}}
2828

2929
void f(Test *t) {
30-
NSString *a = "Foo"; // expected-warning {{string literal must be prefixed by '@'}}
30+
NSString *a = "Foo"; // expected-error {{string literal must be prefixed by '@'}}
3131
id b = "Foo"; // expected-warning {{incompatible pointer types initializing 'id' with an expression of type 'char [4]'}}
32-
g("Foo"); // expected-warning {{string literal must be prefixed by '@'}}
32+
g("Foo"); // expected-error {{string literal must be prefixed by '@'}}
3333
h("Foo"); // expected-warning{{incompatible pointer types passing 'char [4]' to parameter of type 'id'}}
3434
h(("Foo")); // expected-warning{{incompatible pointer types passing 'char [4]' to parameter of type 'id'}}
35-
[t test:"Foo"]; // expected-warning {{string literal must be prefixed by '@'}}
36-
t.property = "Foo"; // expected-warning {{string literal must be prefixed by '@'}}
35+
[t test:"Foo"]; // expected-error {{string literal must be prefixed by '@'}}
36+
t.property = "Foo"; // expected-error {{string literal must be prefixed by '@'}}
3737

3838
// <rdar://problem/6896493>
3939
[t test:@"Foo"]]; // expected-error{{extraneous ']' before ';'}}

0 commit comments

Comments
 (0)