diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-04-11 17:02:10 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-04-11 17:02:10 +0000 |
commit | 5868ec6e3dc13465725fac2f7ff77f1d2ae249ac (patch) | |
tree | d16ba3d3e39d0d2ca306c14e4515d63ff4f478b6 /clang/lib/Analysis/CFG.cpp | |
parent | 66de60376c06779e4231d8e2dc73b0ebf36946d7 (diff) | |
download | bcm5719-llvm-5868ec6e3dc13465725fac2f7ff77f1d2ae249ac.tar.gz bcm5719-llvm-5868ec6e3dc13465725fac2f7ff77f1d2ae249ac.zip |
Fix CFG bug where bases of member expressions were not always evaluated in a lvalue context. Fixes <rdar://problem/7813989>.
llvm-svn: 100966
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index e15b94ed209..c17a2749b50 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -126,6 +126,7 @@ private: CFGBlock *VisitIfStmt(IfStmt *I); CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); CFGBlock *VisitLabelStmt(LabelStmt *L); + CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); @@ -403,6 +404,9 @@ tryAgain: case Stmt::LabelStmtClass: return VisitLabelStmt(cast<LabelStmt>(S)); + case Stmt::MemberExprClass: + return VisitMemberExpr(cast<MemberExpr>(S), asc); + case Stmt::ObjCAtCatchStmtClass: return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); @@ -626,15 +630,18 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, if (!FinishBlock(ConfluenceBlock)) return 0; + asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue + : AddStmtChoice::AlwaysAdd; + Succ = ConfluenceBlock; Block = NULL; - CFGBlock* LHSBlock = addStmt(C->getLHS()); + CFGBlock* LHSBlock = addStmt(C->getLHS(), asc); if (!FinishBlock(LHSBlock)) return 0; Succ = ConfluenceBlock; Block = NULL; - CFGBlock* RHSBlock = addStmt(C->getRHS()); + CFGBlock* RHSBlock = addStmt(C->getRHS(), asc); if (!FinishBlock(RHSBlock)) return 0; @@ -675,6 +682,9 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, if (!FinishBlock(ConfluenceBlock)) return 0; + asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue + : AddStmtChoice::AlwaysAdd; + // Create a block for the LHS expression if there is an LHS expression. A // GCC extension allows LHS to be NULL, causing the condition to be the // value that is returned instead. @@ -683,7 +693,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, Block = NULL; CFGBlock* LHSBlock = NULL; if (C->getLHS()) { - LHSBlock = addStmt(C->getLHS()); + LHSBlock = addStmt(C->getLHS(), asc); if (!FinishBlock(LHSBlock)) return 0; Block = NULL; @@ -691,7 +701,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, // Create the block for the RHS expression. Succ = ConfluenceBlock; - CFGBlock* RHSBlock = addStmt(C->getRHS()); + CFGBlock* RHSBlock = addStmt(C->getRHS(), asc); if (!FinishBlock(RHSBlock)) return 0; @@ -1073,6 +1083,16 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { } } +CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { + if (asc.alwaysAdd()) { + autoCreateBlock(); + AppendStmt(Block, M, asc); + } + return Visit(M->getBase(), + M->isArrow() ? AddStmtChoice::NotAlwaysAdd + : AddStmtChoice::AsLValueNotAlwaysAdd); +} + CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { // Objective-C fast enumeration 'for' statements: // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC |