[cfe-commits] r60760 - in /cfe/trunk: Driver/RewriteObjC.cpp test/Rewriter/properties.m
Steve Naroff
snaroff at apple.com
Tue Dec 9 04:56:40 PST 2008
Author: snaroff
Date: Tue Dec 9 06:56:34 2008
New Revision: 60760
URL: http://llvm.org/viewvc/llvm-project?rev=60760&view=rev
Log:
Fix <rdar://problem/6429113> clang ObjC rewriter: crash rewriting file with Blocks and properties
More fancy footwork to cope with rewriting property 'setters'.
Modified:
cfe/trunk/Driver/RewriteObjC.cpp
cfe/trunk/test/Rewriter/properties.m
Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=60760&r1=60759&r2=60760&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Tue Dec 9 06:56:34 2008
@@ -120,6 +120,8 @@
FunctionDecl *CurFunctionDef;
VarDecl *GlobalVarDecl;
+ bool DisableReplaceStmt;
+
static const int OBJC_ABI_VERSION =7 ;
public:
virtual void Initialize(ASTContext &context);
@@ -146,6 +148,9 @@
if (ReplacingStmt)
return; // We can't rewrite the same node twice.
+ if (DisableReplaceStmt)
+ 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)) {
ReplacedNodes[Old] = New;
@@ -156,7 +161,32 @@
Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
<< Old->getSourceRange();
}
-
+
+ void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
+ // Measaure the old text.
+ int Size = Rewrite.getRangeSize(SrcRange);
+ if (Size == -1) {
+ Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+ << Old->getSourceRange();
+ return;
+ }
+ // Get the new text.
+ std::string SStr;
+ llvm::raw_string_ostream S(SStr);
+ New->printPretty(S);
+ const std::string &Str = S.str();
+
+ // If replacement succeeded or warning disabled return with no warning.
+ if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, &Str[0], Str.size())) {
+ ReplacedNodes[Old] = New;
+ return;
+ }
+ if (SilenceRewriteMacroWarning)
+ return;
+ Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+ << Old->getSourceRange();
+ }
+
void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
bool InsertAfter = true) {
// If insertion succeeded or warning disabled return with no warning.
@@ -220,7 +250,8 @@
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart);
Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
- Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt);
+ Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+ SourceRange SrcRange);
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
@@ -407,6 +438,7 @@
NSStringRecord = 0;
CurMethodDef = 0;
CurFunctionDef = 0;
+ GlobalVarDecl = 0;
SuperStructDecl = 0;
ConstantStringDecl = 0;
BcLabelCount = 0;
@@ -414,7 +446,8 @@
NumObjCStringLiterals = 0;
PropParentMap = 0;
CurrentBody = 0;
-
+ DisableReplaceStmt = false;
+
// Get the ID and start/end of the main file.
MainFileID = SM->getMainFileID();
const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
@@ -1019,7 +1052,8 @@
ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
}
-Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt) {
+Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+ SourceRange SrcRange) {
// Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
// This allows us to reuse all the fun and games in SynthMessageExpr().
ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
@@ -1042,7 +1076,7 @@
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
// Now do the actual rewrite.
- ReplaceStmt(BinOp, ReplacingStmt);
+ ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
delete BinOp;
delete MsgExpr;
return ReplacingStmt;
@@ -4134,7 +4168,15 @@
if (BinOp) {
// Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to rewrite the right hand side prior to rewriting the setter.
+ DisableReplaceStmt = true;
+ // Save the source range. Even if we disable the replacement, the
+ // rewritten node will have been inserted into the tree. If the synthesized
+ // node is at the 'end', the rewriter will fail. Consider this:
+ // self.errorHandler = handler ? handler :
+ // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };
+ SourceRange SrcRange = BinOp->getSourceRange();
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
+ DisableReplaceStmt = false;
//
// Unlike the main iterator, we explicily avoid changing 'BinOp'. If
// we changed the RHS of BinOp, the rewriter would fail (since it needs
@@ -4167,7 +4209,7 @@
// This implies the Rewrite* routines can no longer delete the original
// node. As a result, we now leak the original AST nodes.
//
- return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt));
+ return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
} else {
return RewritePropertyGetter(PropRefExpr);
}
Modified: cfe/trunk/test/Rewriter/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/properties.m?rev=60760&r1=60759&r2=60760&view=diff
==============================================================================
--- cfe/trunk/test/Rewriter/properties.m (original)
+++ cfe/trunk/test/Rewriter/properties.m Tue Dec 9 06:56:34 2008
@@ -47,6 +47,7 @@
obj1.i = (obj2.rrrr);
[obj1 setI:[obj2 rrrr]];
obj1.i = [obj2 rrrr];
+ obj1.i = 3 + [obj2 rrrr];
i = obj1.o.i;
obj1.o.i = 77;
}
More information about the cfe-commits
mailing list