forked from OSchip/llvm-project
objective-C arg: provide fixit support when
c++'s named cast need be replaced for bridge casting. // rdar://12788838 llvm-svn: 175923
This commit is contained in:
parent
9b620f341a
commit
f073871f7f
|
@ -179,14 +179,16 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
|
|||
private:
|
||||
SourceLocation Loc; // the location of the casting op
|
||||
SourceLocation RParenLoc; // the location of the right parenthesis
|
||||
SourceRange AngleBrackets; // range for '<' '>'
|
||||
|
||||
protected:
|
||||
CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
|
||||
CastKind kind, Expr *op, unsigned PathSize,
|
||||
TypeSourceInfo *writtenTy, SourceLocation l,
|
||||
SourceLocation RParenLoc)
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets)
|
||||
: ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
|
||||
RParenLoc(RParenLoc) {}
|
||||
RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}
|
||||
|
||||
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
|
||||
: ExplicitCastExpr(SC, Shell, PathSize) { }
|
||||
|
@ -205,6 +207,7 @@ public:
|
|||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
|
||||
SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
switch (T->getStmtClass()) {
|
||||
|
@ -227,9 +230,10 @@ public:
|
|||
class CXXStaticCastExpr : public CXXNamedCastExpr {
|
||||
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
|
||||
unsigned pathSize, TypeSourceInfo *writtenTy,
|
||||
SourceLocation l, SourceLocation RParenLoc)
|
||||
SourceLocation l, SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets)
|
||||
: CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
|
||||
writtenTy, l, RParenLoc) {}
|
||||
writtenTy, l, RParenLoc, AngleBrackets) {}
|
||||
|
||||
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
|
||||
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
|
||||
|
@ -239,7 +243,8 @@ public:
|
|||
ExprValueKind VK, CastKind K, Expr *Op,
|
||||
const CXXCastPath *Path,
|
||||
TypeSourceInfo *Written, SourceLocation L,
|
||||
SourceLocation RParenLoc);
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets);
|
||||
static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
|
||||
unsigned PathSize);
|
||||
|
||||
|
@ -257,9 +262,10 @@ public:
|
|||
class CXXDynamicCastExpr : public CXXNamedCastExpr {
|
||||
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
|
||||
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
|
||||
SourceLocation l, SourceLocation RParenLoc)
|
||||
SourceLocation l, SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets)
|
||||
: CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
|
||||
writtenTy, l, RParenLoc) {}
|
||||
writtenTy, l, RParenLoc, AngleBrackets) {}
|
||||
|
||||
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
|
||||
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
|
||||
|
@ -269,7 +275,8 @@ public:
|
|||
ExprValueKind VK, CastKind Kind, Expr *Op,
|
||||
const CXXCastPath *Path,
|
||||
TypeSourceInfo *Written, SourceLocation L,
|
||||
SourceLocation RParenLoc);
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets);
|
||||
|
||||
static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
|
||||
unsigned pathSize);
|
||||
|
@ -291,9 +298,10 @@ class CXXReinterpretCastExpr : public CXXNamedCastExpr {
|
|||
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
|
||||
Expr *op, unsigned pathSize,
|
||||
TypeSourceInfo *writtenTy, SourceLocation l,
|
||||
SourceLocation RParenLoc)
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets)
|
||||
: CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
|
||||
pathSize, writtenTy, l, RParenLoc) {}
|
||||
pathSize, writtenTy, l, RParenLoc, AngleBrackets) {}
|
||||
|
||||
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
|
||||
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
|
||||
|
@ -303,7 +311,8 @@ public:
|
|||
ExprValueKind VK, CastKind Kind,
|
||||
Expr *Op, const CXXCastPath *Path,
|
||||
TypeSourceInfo *WrittenTy, SourceLocation L,
|
||||
SourceLocation RParenLoc);
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets);
|
||||
static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
|
||||
unsigned pathSize);
|
||||
|
||||
|
@ -320,9 +329,9 @@ public:
|
|||
class CXXConstCastExpr : public CXXNamedCastExpr {
|
||||
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
|
||||
TypeSourceInfo *writtenTy, SourceLocation l,
|
||||
SourceLocation RParenLoc)
|
||||
SourceLocation RParenLoc, SourceRange AngleBrackets)
|
||||
: CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
|
||||
0, writtenTy, l, RParenLoc) {}
|
||||
0, writtenTy, l, RParenLoc, AngleBrackets) {}
|
||||
|
||||
explicit CXXConstCastExpr(EmptyShell Empty)
|
||||
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
|
||||
|
@ -331,7 +340,8 @@ public:
|
|||
static CXXConstCastExpr *Create(ASTContext &Context, QualType T,
|
||||
ExprValueKind VK, Expr *Op,
|
||||
TypeSourceInfo *WrittenTy, SourceLocation L,
|
||||
SourceLocation RParenLoc);
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets);
|
||||
static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
|
@ -526,13 +526,14 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
|
|||
const CXXCastPath *BasePath,
|
||||
TypeSourceInfo *WrittenTy,
|
||||
SourceLocation L,
|
||||
SourceLocation RParenLoc) {
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets) {
|
||||
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
||||
void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
|
||||
+ PathSize * sizeof(CXXBaseSpecifier*));
|
||||
CXXStaticCastExpr *E =
|
||||
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
||||
RParenLoc);
|
||||
RParenLoc, AngleBrackets);
|
||||
if (PathSize) E->setCastPath(*BasePath);
|
||||
return E;
|
||||
}
|
||||
|
@ -550,13 +551,14 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
|
|||
const CXXCastPath *BasePath,
|
||||
TypeSourceInfo *WrittenTy,
|
||||
SourceLocation L,
|
||||
SourceLocation RParenLoc) {
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets) {
|
||||
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
||||
void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
|
||||
+ PathSize * sizeof(CXXBaseSpecifier*));
|
||||
CXXDynamicCastExpr *E =
|
||||
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
||||
RParenLoc);
|
||||
RParenLoc, AngleBrackets);
|
||||
if (PathSize) E->setCastPath(*BasePath);
|
||||
return E;
|
||||
}
|
||||
|
@ -606,13 +608,14 @@ CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK,
|
|||
CastKind K, Expr *Op,
|
||||
const CXXCastPath *BasePath,
|
||||
TypeSourceInfo *WrittenTy, SourceLocation L,
|
||||
SourceLocation RParenLoc) {
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets) {
|
||||
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
||||
void *Buffer =
|
||||
C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
|
||||
CXXReinterpretCastExpr *E =
|
||||
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
||||
RParenLoc);
|
||||
RParenLoc, AngleBrackets);
|
||||
if (PathSize) E->setCastPath(*BasePath);
|
||||
return E;
|
||||
}
|
||||
|
@ -628,8 +631,9 @@ CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T,
|
|||
ExprValueKind VK, Expr *Op,
|
||||
TypeSourceInfo *WrittenTy,
|
||||
SourceLocation L,
|
||||
SourceLocation RParenLoc) {
|
||||
return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc);
|
||||
SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets) {
|
||||
return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets);
|
||||
}
|
||||
|
||||
CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
|
||||
|
|
|
@ -258,7 +258,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
}
|
||||
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.SrcExpr.take(), DestTInfo,
|
||||
OpLoc, Parens.getEnd()));
|
||||
OpLoc, Parens.getEnd(),
|
||||
AngleBrackets));
|
||||
|
||||
case tok::kw_dynamic_cast: {
|
||||
if (!TypeDependent) {
|
||||
|
@ -269,7 +270,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
|
||||
&Op.BasePath, DestTInfo,
|
||||
OpLoc, Parens.getEnd()));
|
||||
OpLoc, Parens.getEnd(),
|
||||
AngleBrackets));
|
||||
}
|
||||
case tok::kw_reinterpret_cast: {
|
||||
if (!TypeDependent) {
|
||||
|
@ -280,7 +282,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
|
||||
0, DestTInfo, OpLoc,
|
||||
Parens.getEnd()));
|
||||
Parens.getEnd(),
|
||||
AngleBrackets));
|
||||
}
|
||||
case tok::kw_static_cast: {
|
||||
if (!TypeDependent) {
|
||||
|
@ -292,7 +295,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
|
||||
&Op.BasePath, DestTInfo,
|
||||
OpLoc, Parens.getEnd()));
|
||||
OpLoc, Parens.getEnd(),
|
||||
AngleBrackets));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2810,19 +2810,36 @@ static void addFixitForObjCARCConversion(Sema &S,
|
|||
SourceLocation afterLParen,
|
||||
QualType castType,
|
||||
Expr *castExpr,
|
||||
Expr *realCast,
|
||||
const char *bridgeKeyword,
|
||||
const char *CFBridgeName) {
|
||||
// We handle C-style and implicit casts here.
|
||||
switch (CCK) {
|
||||
case Sema::CCK_ImplicitConversion:
|
||||
case Sema::CCK_CStyleCast:
|
||||
case Sema::CCK_OtherCast:
|
||||
break;
|
||||
case Sema::CCK_FunctionalCast:
|
||||
case Sema::CCK_OtherCast:
|
||||
return;
|
||||
}
|
||||
|
||||
if (CFBridgeName) {
|
||||
if (CCK == Sema::CCK_OtherCast) {
|
||||
if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
|
||||
SourceRange range(NCE->getOperatorLoc(),
|
||||
NCE->getAngleBrackets().getEnd());
|
||||
SmallString<32> BridgeCall;
|
||||
|
||||
SourceManager &SM = S.getSourceManager();
|
||||
char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
|
||||
if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts()))
|
||||
BridgeCall += ' ';
|
||||
|
||||
BridgeCall += CFBridgeName;
|
||||
DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));
|
||||
}
|
||||
return;
|
||||
}
|
||||
Expr *castedE = castExpr;
|
||||
if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))
|
||||
castedE = CCE->getSubExpr();
|
||||
|
@ -2854,6 +2871,16 @@ static void addFixitForObjCARCConversion(Sema &S,
|
|||
|
||||
if (CCK == Sema::CCK_CStyleCast) {
|
||||
DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));
|
||||
} else if (CCK == Sema::CCK_OtherCast) {
|
||||
if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
|
||||
std::string castCode = "(";
|
||||
castCode += bridgeKeyword;
|
||||
castCode += castType.getAsString();
|
||||
castCode += ")";
|
||||
SourceRange Range(NCE->getOperatorLoc(),
|
||||
NCE->getAngleBrackets().getEnd());
|
||||
DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));
|
||||
}
|
||||
} else {
|
||||
std::string castCode = "(";
|
||||
castCode += bridgeKeyword;
|
||||
|
@ -2878,7 +2905,8 @@ static void addFixitForObjCARCConversion(Sema &S,
|
|||
static void
|
||||
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
||||
QualType castType, ARCConversionTypeClass castACTC,
|
||||
Expr *castExpr, ARCConversionTypeClass exprACTC,
|
||||
Expr *castExpr, Expr *realCast,
|
||||
ARCConversionTypeClass exprACTC,
|
||||
Sema::CheckedConversionKind CCK) {
|
||||
SourceLocation loc =
|
||||
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
|
||||
|
@ -2930,7 +2958,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|||
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
|
||||
|
||||
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
||||
castType, castExpr, "__bridge ", 0);
|
||||
castType, castExpr, realCast, "__bridge ", 0);
|
||||
}
|
||||
if (CreateRule != ACC_plusZero)
|
||||
{
|
||||
|
@ -2942,7 +2970,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|||
<< castExprType << br;
|
||||
|
||||
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
||||
castType, castExpr, "__bridge_transfer ",
|
||||
castType, castExpr, realCast, "__bridge_transfer ",
|
||||
br ? "CFBridgingRelease" : 0);
|
||||
}
|
||||
|
||||
|
@ -2969,7 +2997,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|||
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
|
||||
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
|
||||
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
||||
castType, castExpr, "__bridge ", 0);
|
||||
castType, castExpr, realCast, "__bridge ", 0);
|
||||
}
|
||||
if (CreateRule != ACC_plusZero)
|
||||
{
|
||||
|
@ -2981,7 +3009,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|||
<< castType << br;
|
||||
|
||||
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
||||
castType, castExpr, "__bridge_retained ",
|
||||
castType, castExpr, realCast, "__bridge_retained ",
|
||||
br ? "CFBridgingRetain" : 0);
|
||||
}
|
||||
|
||||
|
@ -3078,7 +3106,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
|
|||
return ACR_unbridged;
|
||||
|
||||
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
|
||||
castExpr, exprACTC, CCK);
|
||||
castExpr, castExpr, exprACTC, CCK);
|
||||
return ACR_okay;
|
||||
}
|
||||
|
||||
|
@ -3113,7 +3141,7 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) {
|
|||
assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
|
||||
|
||||
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
|
||||
castExpr, ACTC_retainable, CCK);
|
||||
castExpr, realCast, ACTC_retainable, CCK);
|
||||
}
|
||||
|
||||
/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
|
||||
|
|
|
@ -7022,17 +7022,13 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
|
|||
Type == E->getTypeInfoAsWritten() &&
|
||||
SubExpr.get() == E->getSubExpr())
|
||||
return SemaRef.Owned(E);
|
||||
|
||||
// FIXME: Poor source location information here.
|
||||
SourceLocation FakeLAngleLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
|
||||
SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
|
||||
return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
|
||||
E->getStmtClass(),
|
||||
FakeLAngleLoc,
|
||||
E->getAngleBrackets().getBegin(),
|
||||
Type,
|
||||
FakeRAngleLoc,
|
||||
FakeRAngleLoc,
|
||||
E->getAngleBrackets().getEnd(),
|
||||
// FIXME. this should be '(' location
|
||||
E->getAngleBrackets().getEnd(),
|
||||
SubExpr.get(),
|
||||
E->getRParenLoc());
|
||||
}
|
||||
|
|
|
@ -1147,6 +1147,8 @@ void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
|
|||
SourceRange R = ReadSourceRange(Record, Idx);
|
||||
E->Loc = R.getBegin();
|
||||
E->RParenLoc = R.getEnd();
|
||||
R = ReadSourceRange(Record, Idx);
|
||||
E->AngleBrackets = R;
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
|
||||
|
|
|
@ -1124,6 +1124,7 @@ void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
|
|||
VisitExplicitCastExpr(E);
|
||||
Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()),
|
||||
Record);
|
||||
Writer.AddSourceRange(E->getAngleBrackets(), Record);
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdiagnostics-parseable-fixits -x objective-c++ -fobjc-arc %s 2>&1 | FileCheck %s
|
||||
// rdar://12788838
|
||||
|
||||
id obj;
|
||||
|
||||
void Test1() {
|
||||
void *foo = reinterpret_cast<void *>(obj);
|
||||
}
|
||||
// CHECK: {7:15-7:39}:"(__bridge void *)"
|
||||
// CHECK: {7:15-7:39}:"(__bridge_retained void *)"
|
||||
|
||||
typedef const void * CFTypeRef;
|
||||
extern "C" CFTypeRef CFBridgingRetain(id X);
|
||||
|
||||
void Test2() {
|
||||
void *foo = reinterpret_cast<void *>(obj);
|
||||
}
|
||||
// CHECK: {16:15-16:39}:"(__bridge void *)"
|
||||
// CHECK: {16:15-16:39}:"CFBridgingRetain"
|
Loading…
Reference in New Issue