From: Fariborz Jahanian Date: Wed, 18 Dec 2013 21:04:43 +0000 (+0000) Subject: Objective-C. After providing a fix-it for a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2dd9321fe249afccc5b58570b855db57d6e55bd0;p=clang Objective-C. After providing a fix-it for a cstring, converted to NSString, produce the matching AST for it. This also required some refactoring of the previous code. // rdar://14106083 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@197605 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 847ac820d9..0e4ab07af0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6902,9 +6902,7 @@ public: QualType DestType, QualType SrcType, Expr *&SrcExpr); - StringLiteral * ConversionToObjCStringLiteralCheck(QualType DstType, - Expr *SrcExpr, FixItHint &Hint, - bool &IsNSString); + bool ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&SrcExpr); bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0597a998c4..fcd972436d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6613,8 +6613,9 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, DiagnoseCFAudited); if (getLangOpts().ObjC1 && - CheckObjCBridgeRelatedConversions(E->getLocStart(), - LHSType, E->getType(), E)) { + (CheckObjCBridgeRelatedConversions(E->getLocStart(), + LHSType, E->getType(), E) || + ConversionToObjCStringLiteralCheck(LHSType, E))) { RHS = Owned(E); return Compatible; } @@ -10587,39 +10588,37 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { return Owned(new (Context) GNUNullExpr(Ty, TokenLoc)); } -StringLiteral * -Sema::ConversionToObjCStringLiteralCheck(QualType DstType, - Expr *SrcExpr, FixItHint &Hint, - bool &IsNSString) { +bool +Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) { if (!getLangOpts().ObjC1) - return 0; + return false; const ObjCObjectPointerType *PT = DstType->getAs(); if (!PT) - return 0; + return false; - // 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 0; - IsNSString = true; + return false; } - + // Ignore any parens, implicit casts (should only be // array-to-pointer decays), and not-so-opaque values. The last is // important for making this trigger for property assignments. - SrcExpr = SrcExpr->IgnoreParenImpCasts(); + Expr *SrcExpr = Exp->IgnoreParenImpCasts(); if (OpaqueValueExpr *OV = dyn_cast(SrcExpr)) if (OV->getSourceExpr()) SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts(); StringLiteral *SL = dyn_cast(SrcExpr); if (!SL || !SL->isAscii()) - return 0; - Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@"); - return SL; + return false; + Diag(SL->getLocStart(), diag::err_missing_atsign_prefix) + << FixItHint::CreateInsertion(SL->getLocStart(), "@"); + Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).take(); + return true; } bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, @@ -10638,7 +10637,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, ConversionFixItGenerator ConvHints; bool MayHaveConvFixit = false; bool MayHaveFunctionDiff = false; - bool IsNSString = false; switch (ConvTy) { case Compatible: @@ -10656,7 +10654,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, MayHaveConvFixit = true; break; case IncompatiblePointer: - ConversionToObjCStringLiteralCheck(DstType, SrcExpr, Hint, IsNSString); DiagKind = (Action == AA_Passing_CFAudited ? diag::err_arc_typecheck_convert_incompatible_pointer : @@ -10670,8 +10667,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SrcType = SrcType.getUnqualifiedType(); DstType = DstType.getUnqualifiedType(); } - else if (IsNSString && !Hint.isNull()) - DiagKind = diag::err_missing_atsign_prefix; MayHaveConvFixit = true; break; case IncompatiblePointerSign: diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index f312839a9d..8f0b90b3be 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -3615,13 +3615,9 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, // 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; - } + if (castACTC == ACTC_retainable && exprACTC == ACTC_none && + ConversionToObjCStringLiteralCheck(castType, castExpr)) + return ACR_okay; // Do not issue "bridge cast" diagnostic when implicit casting // a retainable object to a CF type parameter belonging to an audited diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 95456e52cc..9ba873a078 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4462,11 +4462,14 @@ void InitializationSequence::InitializeFrom(Sema &S, Expr *Initializer = 0; if (Args.size() == 1) { Initializer = Args[0]; - if (S.getLangOpts().ObjC1 && - S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), - DestType, Initializer->getType(), - Initializer)) - Args[0] = Initializer; + if (S.getLangOpts().ObjC1) { + if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), + DestType, Initializer->getType(), + Initializer) || + S.ConversionToObjCStringLiteralCheck(DestType, Initializer)) + Args[0] = Initializer; + + } if (!isa(Initializer)) SourceType = Initializer->getType(); } diff --git a/test/Analysis/default-analyze.m b/test/Analysis/default-analyze.m index 82656b24a6..5fbaa2f98c 100644 --- a/test/Analysis/default-analyze.m +++ b/test/Analysis/default-analyze.m @@ -11,7 +11,7 @@ id foo(int x) { title = @"bar"; break; default: - title = "@baz"; + title = @"baz"; break; } return title; diff --git a/test/FixIt/fixit-objc-arc.m b/test/FixIt/fixit-objc-arc.m index 19a61b4108..dcee81594e 100644 --- a/test/FixIt/fixit-objc-arc.m +++ b/test/FixIt/fixit-objc-arc.m @@ -8,12 +8,12 @@ @class NSString; @interface Test -- (void)test:(NSString *)string; // expected-note{{passing argument to parameter 'string' here}} +- (void)test:(NSString *)string; @property (copy) NSString *property; @end -void g(NSString *a); // expected-note{{passing argument to parameter 'a' here}} +void g(NSString *a); void h(id a); void f(Test *t) { diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m index 17de36528e..f41f75f1d7 100644 --- a/test/FixIt/fixit-objc.m +++ b/test/FixIt/fixit-objc.m @@ -18,20 +18,20 @@ void foo() { @class NSString; @interface Test -- (void)test:(NSString *)string; // expected-note{{passing argument to parameter 'string' here}} +- (void)test:(NSString *)string; @property (copy) NSString *property; @end -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 g(NSString *a); +void h(id a); void f(Test *t) { 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]'}} + id b = "Foo"; // expected-error {{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'}} + h("Foo"); // expected-error {{string literal must be prefixed by '@'}} + h(("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/Index/fix-its.m b/test/Index/fix-its.m index b307cf4c6d..fabcdb2905 100644 --- a/test/Index/fix-its.m +++ b/test/Index/fix-its.m @@ -24,5 +24,3 @@ void _rdar_12584554_A (volatile const void * object, volatile const void * selec // CHECK: Number FIX-ITs = 0 // CHECK: fix-its.m:7:77: note: expanded from macro '_rdar_12584554_B' // CHECK: Number FIX-ITs = 0 -// CHECK: fix-its.m:5:172: note: passing argument to parameter 'msgFormat' here -// CHECK: Number FIX-ITs = 0