aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-02-16 17:31:07 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-02-16 17:31:07 +0000
commitae1b4af84ed0200c1040837ed62762557fbce5a7 (patch)
treeabb96c61eb4fa0c566b45c7de77e5f18cf586284 /lib/Sema/SemaExprObjC.cpp
parentdd5756c04c98e354b85c4f7eb660ae60c6d341ec (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.cpp102
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;
}