aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Rewrite/Rewriter.h2
-rw-r--r--lib/Frontend/RewriteObjC.cpp12
-rw-r--r--lib/Rewrite/Rewriter.cpp5
-rw-r--r--test/Rewriter/rewrite-nested-ivar.mm33
4 files changed, 45 insertions, 7 deletions
diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h
index 1692180a6d..e625b4a36e 100644
--- a/include/clang/Rewrite/Rewriter.h
+++ b/include/clang/Rewrite/Rewriter.h
@@ -190,7 +190,7 @@ public:
/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
/// printer to generate the replacement code. This returns true if the input
/// could not be rewritten, or false if successful.
- bool ReplaceStmt(Stmt *From, Stmt *To);
+ bool ReplaceStmt(Stmt *From, Stmt *To, int Size=0);
/// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
/// If no modification has been made to it, return null.
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index c56055599b..68d9b27c40 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -167,7 +167,7 @@ namespace {
virtual void HandleTranslationUnit(ASTContext &C);
- void ReplaceStmt(Stmt *Old, Stmt *New) {
+ void ReplaceStmt(Stmt *Old, Stmt *New, int Size=0) {
Stmt *ReplacingStmt = ReplacedNodes[Old];
if (ReplacingStmt)
@@ -177,7 +177,7 @@ namespace {
return; // Used when rewriting the assignment of a property setter.
// If replacement succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceStmt(Old, New)) {
+ if (!Rewrite.ReplaceStmt(Old, New, Size)) {
ReplacedNodes[Old] = New;
return;
}
@@ -1247,8 +1247,12 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
// delete IV; leak for now, see RewritePropertySetter() usage for more info.
return ME;
}
-
- ReplaceStmt(IV->getBase(), PE);
+ // Get the old text, only to get its size.
+ std::string SStr;
+ llvm::raw_string_ostream S(SStr);
+ IV->getBase()->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
+ // Get the new text
+ ReplaceStmt(IV->getBase(), PE, S.str().size());
// Cannot delete IV->getBase(), since PE points to it.
// Replace the old base with the cast. This is important when doing
// embedded rewrites. For example, [newInv->_container addObject:0].
diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp
index 9744496ac4..96a2a06a44 100644
--- a/lib/Rewrite/Rewriter.cpp
+++ b/lib/Rewrite/Rewriter.cpp
@@ -207,9 +207,10 @@ bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
/// printer to generate the replacement code. This returns true if the input
/// could not be rewritten, or false if successful.
-bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) {
+bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To, int Size) {
// Measaure the old text.
- int Size = getRangeSize(From->getSourceRange());
+ if (!Size)
+ Size = getRangeSize(From->getSourceRange());
if (Size == -1)
return true;
diff --git a/test/Rewriter/rewrite-nested-ivar.mm b/test/Rewriter/rewrite-nested-ivar.mm
new file mode 100644
index 0000000000..bbc9d28d25
--- /dev/null
+++ b/test/Rewriter/rewrite-nested-ivar.mm
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: FileCheck -check-prefix LP --input-file=%t-rw.cpp %s
+// radar 7583971
+
+
+@interface NSURLResponse {
+@public
+ NSURLResponse *InnerResponse;
+}
+@end
+
+@interface NSCachedURLResponseInternal
+{
+ @public
+ NSURLResponse *response;
+}
+@end
+
+@interface NSCachedURLResponse
+{
+ @private
+ NSCachedURLResponseInternal *_internal;
+}
+- (void) Meth;
+@end
+
+@implementation NSCachedURLResponse
+- (void) Meth {
+ _internal->response->InnerResponse = 0;
+ }
+@end
+
+// CHECK-LP: ((struct NSURLResponse_IMPL *)((struct NSCachedURLResponseInternal_IMPL *)((struct NSCachedURLResponse_IMPL *)self)->_internal)->response)->InnerResponse