]> granicus.if.org Git - clang/commitdiff
When a && or || appears as the condition of a ?:, perform appropriate
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 24 Jul 2012 21:02:14 +0000 (21:02 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 24 Jul 2012 21:02:14 +0000 (21:02 +0000)
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

lib/Analysis/CFG.cpp
test/Sema/uninit-variables.c

index 1e3fa90c37237f0f68f2a0d7b690b390952818c5..128452759540dd93ee90fd63a30cf0062e285a22 100644 (file)
@@ -1491,6 +1491,12 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
   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 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
   // 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 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
 
     // 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 @@ CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
 
     // 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 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
     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 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
 
   } 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";
index 9257751e4717769ed245b8bc2409a68d0fd4295e..634ae0dc42843155576842924ce1ef321be6153c 100644 (file)
@@ -503,3 +503,8 @@ int compound_assign_3() {
   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;
+}