From: Ted Kremenek Date: Sun, 11 Apr 2010 17:02:10 +0000 (+0000) Subject: Fix CFG bug where bases of member expressions were not always evaluated in a lvalue... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115;p=clang Fix CFG bug where bases of member expressions were not always evaluated in a lvalue context. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100966 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(S)); + case Stmt::MemberExprClass: + return VisitMemberExpr(cast(S), asc); + case Stmt::ObjCAtCatchStmtClass: return VisitObjCAtCatchStmt(cast(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 diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 3f64a085c8..8831791d8b 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -984,3 +984,13 @@ void u132monitk (struct pr6036_c *pr6036_d) { (void) ((struct pr6036_a *) (unsigned long (*)[0]) ((char *) pr6036_d - 1))->pr6036_b; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}} } +// - ?-expressions used as a base of a member expression should be treated as an lvalue +typedef struct rdar7813989_NestedVal { int w; } rdar7813989_NestedVal; +typedef struct rdar7813989_Val { rdar7813989_NestedVal nv; } rdar7813989_Val; + +int rdar7813989(int x, rdar7813989_Val *a, rdar7813989_Val *b) { + // This previously crashed with an assertion failure. + int z = (x ? a->nv : b->nv).w; + return z + 1; +} +