]> granicus.if.org Git - clang/commitdiff
Fix CFG bug where bases of member expressions were not always evaluated in a lvalue...
authorTed Kremenek <kremenek@apple.com>
Sun, 11 Apr 2010 17:02:10 +0000 (17:02 +0000)
committerTed Kremenek <kremenek@apple.com>
Sun, 11 Apr 2010 17:02:10 +0000 (17:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100966 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Analysis/misc-ps-region-store.m

index e15b94ed2098747212df737a13c5354ac16bc1b2..c17a2749b508371781b8b17bced171f57aca3def 100644 (file)
@@ -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
index 3f64a085c8392bd2e5473a4171d6db4577d910e9..8831791d8bf91944ffd381c367e05e9e760bba3f 100644 (file)
@@ -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;
+}
+