From f799ae1afb897151a84a7170951e367d8307ae04 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 22 Feb 2013 22:02:53 +0000 Subject: [PATCH] objective-C arg: provide fixit support when c++'s named cast need be replaced for bridge casting. // rdar://12788838 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175923 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 38 ++++++++++++++++--------- lib/AST/ExprCXX.cpp | 20 +++++++------ lib/Sema/SemaCast.cpp | 12 +++++--- lib/Sema/SemaExprObjC.cpp | 44 +++++++++++++++++++++++------ lib/Sema/TreeTransform.h | 12 +++----- lib/Serialization/ASTReaderStmt.cpp | 2 ++ lib/Serialization/ASTWriterStmt.cpp | 1 + test/FixIt/bridge-cast-in-arc.mm | 19 +++++++++++++ 8 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 test/FixIt/bridge-cast-in-arc.mm diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index cc12d0527a..04f6fb64cf 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -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) { diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 4b520e4fdf..e1e96e4c5c 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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) { diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index e6dc0bd8bc..3f46cd457a 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -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)); } } } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 2dbba853e4..b26fa7661c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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(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(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(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 diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 438d06a8ef..66bf4cea68 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7022,17 +7022,13 @@ TreeTransform::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()); } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 7f26a1752b..9c99d6e46f 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -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) { diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 6b96c500c3..ee9735c163 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -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) { diff --git a/test/FixIt/bridge-cast-in-arc.mm b/test/FixIt/bridge-cast-in-arc.mm new file mode 100644 index 0000000000..5cd482fabc --- /dev/null +++ b/test/FixIt/bridge-cast-in-arc.mm @@ -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(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(obj); +} +// CHECK: {16:15-16:39}:"(__bridge void *)" +// CHECK: {16:15-16:39}:"CFBridgingRetain" -- 2.40.0