diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-02-16 17:31:07 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-02-16 17:31:07 +0000 |
commit | ae1b4af84ed0200c1040837ed62762557fbce5a7 (patch) | |
tree | abb96c61eb4fa0c566b45c7de77e5f18cf586284 /lib/Sema/SemaExprObjC.cpp | |
parent | dd5756c04c98e354b85c4f7eb660ae60c6d341ec (diff) |
Add fixits for ARC casting errors for implicit conversions as well. rdar://10289283
Also fix the fixit (oh the irony) when it uses CFBridgingRetain/CFBridgingRelease;
they are supposed to be calls with the casted expression as parameter, they should
not be inserted into the cast like the __bridge keywords.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150705 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 102 |
1 files changed, 86 insertions, 16 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 497b2ec5f5..133c2d3de9 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1889,6 +1889,68 @@ KnownName(Sema &S, const char *name) { return S.LookupName(R, S.TUScope, false); } +static void addFixitForObjCARCConversion(Sema &S, + DiagnosticBuilder &DiagB, + Sema::CheckedConversionKind CCK, + SourceLocation afterLParen, + QualType castType, + Expr *castExpr, + const char *bridgeKeyword, + const char *CFBridgeName) { + // We handle C-style and implicit casts here. + switch (CCK) { + case Sema::CCK_ImplicitConversion: + case Sema::CCK_CStyleCast: + break; + case Sema::CCK_FunctionalCast: + case Sema::CCK_OtherCast: + return; + } + + if (CFBridgeName) { + Expr *castedE = castExpr; + if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE)) + castedE = CCE->getSubExpr(); + castedE = castedE->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa<ParenExpr>(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + CFBridgeName)); + } else { + std::string namePlusParen = CFBridgeName; + namePlusParen += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + namePlusParen)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + return; + } + + if (CCK == Sema::CCK_CStyleCast) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); + } else { + std::string castCode = "("; + castCode += bridgeKeyword; + castCode += castType.getAsString(); + castCode += ")"; + Expr *castedE = castExpr->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa<ParenExpr>(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + } else { + castCode += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + } +} + static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange, QualType castType, ARCConversionTypeClass castACTC, @@ -1934,14 +1996,18 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castRange << castExpr->getSourceRange(); bool br = KnownName(S, "CFBridgingRelease"); - S.Diag(noteLoc, diag::note_arc_bridge) - << (CCK != Sema::CCK_CStyleCast ? FixItHint() : - FixItHint::CreateInsertion(afterLParen, "__bridge ")); - S.Diag(noteLoc, diag::note_arc_bridge_transfer) - << castExprType << br - << (CCK != Sema::CCK_CStyleCast ? FixItHint() : - FixItHint::CreateInsertion(afterLParen, - br ? "CFBridgingRelease " : "__bridge_transfer ")); + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_transfer) + << castExprType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_transfer ", + br ? "CFBridgingRelease" : 0); + } return; } @@ -1958,14 +2024,18 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castRange << castExpr->getSourceRange(); - S.Diag(noteLoc, diag::note_arc_bridge) - << (CCK != Sema::CCK_CStyleCast ? FixItHint() : - FixItHint::CreateInsertion(afterLParen, "__bridge ")); - S.Diag(noteLoc, diag::note_arc_bridge_retained) - << castType << br - << (CCK != Sema::CCK_CStyleCast ? FixItHint() : - FixItHint::CreateInsertion(afterLParen, - br ? "CFBridgingRetain " : "__bridge_retained")); + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_retained) + << castType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_retained ", + br ? "CFBridgingRetain" : 0); + } return; } |