diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Edit/RewriteObjCFoundationAPI.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Edit/RewriteObjCFoundationAPI.cpp')
-rw-r--r-- | lib/Edit/RewriteObjCFoundationAPI.cpp | 180 |
1 files changed, 167 insertions, 13 deletions
diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index de96fee..f4206fb 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -12,12 +12,13 @@ //===----------------------------------------------------------------------===// #include "clang/Edit/Rewriters.h" -#include "clang/Edit/Commit.h" -#include "clang/Lex/Lexer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/NSAPI.h" +#include "clang/AST/ParentMap.h" +#include "clang/Edit/Commit.h" +#include "clang/Lex/Lexer.h" using namespace clang; using namespace edit; @@ -295,9 +296,8 @@ bool edit::rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, if (!Method) return false; - const ObjCInterfaceDecl * - IFace = NS.getASTContext().getObjContainingInterface( - const_cast<ObjCMethodDecl *>(Method)); + const ObjCInterfaceDecl *IFace = + NS.getASTContext().getObjContainingInterface(Method); if (!IFace) return false; Selector Sel = Msg->getSelector(); @@ -325,7 +325,8 @@ bool edit::rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, //===----------------------------------------------------------------------===// static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); + const NSAPI &NS, Commit &commit, + const ParentMap *PMap); static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, @@ -336,13 +337,14 @@ static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { + const NSAPI &NS, Commit &commit, + const ParentMap *PMap) { IdentifierInfo *II = 0; if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) return false; if (II == NS.getNSClassId(NSAPI::ClassId_NSArray)) - return rewriteToArrayLiteral(Msg, NS, commit); + return rewriteToArrayLiteral(Msg, NS, commit, PMap); if (II == NS.getNSClassId(NSAPI::ClassId_NSDictionary)) return rewriteToDictionaryLiteral(Msg, NS, commit); if (II == NS.getNSClassId(NSAPI::ClassId_NSNumber)) @@ -353,6 +355,19 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, return false; } +/// \brief Returns true if the immediate message arguments of \c Msg should not +/// be rewritten because it will interfere with the rewrite of the parent +/// message expression. e.g. +/// \code +/// [NSDictionary dictionaryWithObjects: +/// [NSArray arrayWithObjects:@"1", @"2", nil] +/// forKeys:[NSArray arrayWithObjects:@"A", @"B", nil]]; +/// \endcode +/// It will return true for this because we are going to rewrite this directly +/// to a dictionary literal without any array literals. +static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg, + const NSAPI &NS); + //===----------------------------------------------------------------------===// // rewriteToArrayLiteral. //===----------------------------------------------------------------------===// @@ -361,7 +376,15 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, static void objectifyExpr(const Expr *E, Commit &commit); static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { + const NSAPI &NS, Commit &commit, + const ParentMap *PMap) { + if (PMap) { + const ObjCMessageExpr *ParentMsg = + dyn_cast_or_null<ObjCMessageExpr>(PMap->getParentIgnoreParenCasts(Msg)); + if (shouldNotRewriteImmediateMessageArgs(ParentMsg, NS)) + return false; + } + Selector Sel = Msg->getSelector(); SourceRange MsgRange = Msg->getSourceRange(); @@ -411,6 +434,59 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, // rewriteToDictionaryLiteral. //===----------------------------------------------------------------------===// +/// \brief If \c Msg is an NSArray creation message or literal, this gets the +/// objects that were used to create it. +/// \returns true if it is an NSArray and we got objects, or false otherwise. +static bool getNSArrayObjects(const Expr *E, const NSAPI &NS, + SmallVectorImpl<const Expr *> &Objs) { + if (!E) + return false; + + E = E->IgnoreParenCasts(); + if (!E) + return false; + + if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) { + IdentifierInfo *Cls = 0; + if (!checkForLiteralCreation(Msg, Cls, NS.getASTContext().getLangOpts())) + return false; + + if (Cls != NS.getNSClassId(NSAPI::ClassId_NSArray)) + return false; + + Selector Sel = Msg->getSelector(); + if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array)) + return true; // empty array. + + if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) { + if (Msg->getNumArgs() != 1) + return false; + Objs.push_back(Msg->getArg(0)); + return true; + } + + if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) || + Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) { + if (Msg->getNumArgs() == 0) + return false; + const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1); + if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) + return false; + + for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i) + Objs.push_back(Msg->getArg(i)); + return true; + } + + } else if (const ObjCArrayLiteral *ArrLit = dyn_cast<ObjCArrayLiteral>(E)) { + for (unsigned i = 0, e = ArrLit->getNumElements(); i != e; ++i) + Objs.push_back(ArrLit->getElement(i)); + return true; + } + + return false; +} + static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { Selector Sel = Msg->getSelector(); @@ -481,6 +557,83 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, return true; } + if (Sel == NS.getNSDictionarySelector( + NSAPI::NSDict_dictionaryWithObjectsForKeys) || + Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) { + if (Msg->getNumArgs() != 2) + return false; + + SmallVector<const Expr *, 8> Vals; + if (!getNSArrayObjects(Msg->getArg(0), NS, Vals)) + return false; + + SmallVector<const Expr *, 8> Keys; + if (!getNSArrayObjects(Msg->getArg(1), NS, Keys)) + return false; + + if (Vals.size() != Keys.size()) + return false; + + if (Vals.empty()) { + commit.replace(MsgRange, "@{}"); + return true; + } + + for (unsigned i = 0, n = Vals.size(); i < n; ++i) { + objectifyExpr(Vals[i], commit); + objectifyExpr(Keys[i], commit); + + SourceRange ValRange = Vals[i]->getSourceRange(); + SourceRange KeyRange = Keys[i]->getSourceRange(); + // Insert value after key. + commit.insertAfterToken(KeyRange.getEnd(), ": "); + commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true); + } + // Range of arguments up until and including the last key. + // The first value is cut off, the value will move after the key. + SourceRange ArgRange(Keys.front()->getLocStart(), + Keys.back()->getLocEnd()); + commit.insertWrap("@{", ArgRange, "}"); + commit.replaceWithInner(MsgRange, ArgRange); + return true; + } + + return false; +} + +static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg, + const NSAPI &NS) { + if (!Msg) + return false; + + IdentifierInfo *II = 0; + if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) + return false; + + if (II != NS.getNSClassId(NSAPI::ClassId_NSDictionary)) + return false; + + Selector Sel = Msg->getSelector(); + if (Sel == NS.getNSDictionarySelector( + NSAPI::NSDict_dictionaryWithObjectsForKeys) || + Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) { + if (Msg->getNumArgs() != 2) + return false; + + SmallVector<const Expr *, 8> Vals; + if (!getNSArrayObjects(Msg->getArg(0), NS, Vals)) + return false; + + SmallVector<const Expr *, 8> Keys; + if (!getNSArrayObjects(Msg->getArg(1), NS, Keys)) + return false; + + if (Vals.size() != Keys.size()) + return false; + + return true; + } + return false; } @@ -540,7 +693,7 @@ static bool getLiteralInfo(SourceRange literalRange, if (text.empty()) return false; - llvm::Optional<bool> UpperU, UpperL; + Optional<bool> UpperU, UpperL; bool UpperF = false; struct Suff { @@ -624,7 +777,7 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, ASTContext &Ctx = NS.getASTContext(); Selector Sel = Msg->getSelector(); - llvm::Optional<NSAPI::NSNumberLiteralMethodKind> + Optional<NSAPI::NSNumberLiteralMethodKind> MKOpt = NS.getNSNumberLiteralMethodKind(Sel); if (!MKOpt) return false; @@ -828,7 +981,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, ASTContext &Ctx = NS.getASTContext(); Selector Sel = Msg->getSelector(); - llvm::Optional<NSAPI::NSNumberLiteralMethodKind> + Optional<NSAPI::NSNumberLiteralMethodKind> MKOpt = NS.getNSNumberLiteralMethodKind(Sel); if (!MKOpt) return false; @@ -921,6 +1074,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_NonAtomicToAtomic: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: + case CK_ZeroToOCLEvent: return false; } } |