aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-04-11 17:02:10 +0000
committerTed Kremenek <kremenek@apple.com>2010-04-11 17:02:10 +0000
commit115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115 (patch)
tree9f345a4a1a76543b6b2375826cbfa92120b49329 /lib/Analysis
parent431ac2d9c2f7596af6187daf88be411cb1ea34cf (diff)
Fix CFG bug where bases of member expressions were not always evaluated in a lvalue context. Fixes <rdar://problem/7813989>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100966 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/CFG.cpp28
1 files changed, 24 insertions, 4 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index e15b94ed20..c17a2749b5 100644
--- a/lib/Analysis/CFG.cpp
+++ b/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