When a && or || appears as the condition of a ?:, perform appropriate
short-circuiting when building the CFG. Also be sure to skip parens before
checking for the && / || special cases. Finally, fix some crashes in CFG
printing in the presence of calls to destructors for array of array of class
type.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160691 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 1e3fa90..1284527 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1491,6 +1491,12 @@
   if (badCFG)
     return 0;
 
+  // If the condition is a logical '&&' or '||', build a more accurate CFG.
+  if (BinaryOperator *Cond =
+        dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens()))
+    if (Cond->isLogicalOp())
+      return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
+
   // Create the block that will contain the condition.
   Block = createBlock(false);
 
@@ -1708,7 +1714,8 @@
   // control-flow transfer of '&&' or '||' go directly into the then/else
   // blocks directly.
   if (!I->getConditionVariable())
-    if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(I->getCond()))
+    if (BinaryOperator *Cond =
+            dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens()))
       if (Cond->isLogicalOp())
         return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
 
@@ -1928,7 +1935,8 @@
 
     // Specially handle logical operators, which have a slightly
     // more optimal CFG representation.
-    if (BinaryOperator *Cond = dyn_cast_or_null<BinaryOperator>(C))
+    if (BinaryOperator *Cond =
+            dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0))
       if (Cond->isLogicalOp()) {
         llvm::tie(EntryConditionBlock, ExitConditionBlock) =
           VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
@@ -2237,7 +2245,7 @@
 
     // Specially handle logical operators, which have a slightly
     // more optimal CFG representation.
-    if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C))
+    if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))
       if (Cond->isLogicalOp()) {
         llvm::tie(EntryConditionBlock, ExitConditionBlock) =
           VisitLogicalOperator(Cond, W, BodyBlock,
@@ -3712,8 +3720,7 @@
     const Type* T = VD->getType().getTypePtr();
     if (const ReferenceType* RT = T->getAs<ReferenceType>())
       T = RT->getPointeeType().getTypePtr();
-    else if (const Type *ET = T->getArrayElementTypeNoTypeQual())
-      T = ET;
+    T = T->getBaseElementTypeUnsafe();
 
     OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
     OS << " (Implicit destructor)\n";
@@ -3725,11 +3732,7 @@
 
   } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) {
     const FieldDecl *FD = ME->getFieldDecl();
-
-    const Type *T = FD->getType().getTypePtr();
-    if (const Type *ET = T->getArrayElementTypeNoTypeQual())
-      T = ET;
-
+    const Type *T = FD->getType()->getBaseElementTypeUnsafe();
     OS << "this->" << FD->getName();
     OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
     OS << " (Member object destructor)\n";
diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c
index 9257751..634ae0d 100644
--- a/test/Sema/uninit-variables.c
+++ b/test/Sema/uninit-variables.c
@@ -503,3 +503,8 @@
   x *= 0; // expected-warning {{variable 'x' is uninitialized}}
   return x;
 }
+
+int self_init_in_cond(int *p) {
+  int n = ((p && (0 || 1)) && (n = *p)) ? n : -1; // ok
+  return n;
+}