summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/CFG.cpp
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
commit5868ec6e3dc13465725fac2f7ff77f1d2ae249ac (patch)
treed16ba3d3e39d0d2ca306c14e4515d63ff4f478b6 /clang/lib/Analysis/CFG.cpp
parent66de60376c06779e4231d8e2dc73b0ebf36946d7 (diff)
downloadbcm5719-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.cpp28
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
OpenPOWER on IntegriCloud