summaryrefslogtreecommitdiffstats
path: root/lib/Edit/RewriteObjCFoundationAPI.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Edit/RewriteObjCFoundationAPI.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-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.cpp180
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;
}
}
OpenPOWER on IntegriCloud