diff options
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 28 | ||||
| -rw-r--r-- | clang/test/Analysis/misc-ps-region-store.m | 10 | 
2 files changed, 34 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 diff --git a/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m index 3f64a085c83..8831791d8bf 100644 --- a/clang/test/Analysis/misc-ps-region-store.m +++ b/clang/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}}  } +// <rdar://problem/7813989> - ?-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; +} +  | 

