From: Ted Kremenek Date: Thu, 24 Feb 2011 03:09:15 +0000 (+0000) Subject: Fix tiny error in CFG construction for BinaryConditionalOperators, making sure the... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f226d18f0f49394cec460699f4268e32bd0ce833;p=clang Fix tiny error in CFG construction for BinaryConditionalOperators, making sure the branch always has two successors. Also teach Environment::getSVal() about OpaqueValueExprs. This fixes a crash reported in PR9287, and also fixes a false positive involving the value of such ternary expressions not properly getting propagated. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126362 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 90b3120cd2..cc6e9c592a 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1217,6 +1217,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, return 0; Block = NULL; } + else + LHSBlock = ConfluenceBlock; // Create the block for the RHS expression. Succ = ConfluenceBlock; @@ -1229,23 +1231,23 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, // See if this is a known constant. const TryResult& KnownVal = tryEvaluateBool(C->getCond()); - if (LHSBlock) - addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); + addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); Block->setTerminator(C); Expr *condExpr = C->getCond(); - CFGBlock *result = 0; - - // Run the condition expression if it's not trivially expressed in - // terms of the opaque value (or if there is no opaque value). - if (condExpr != opaqueValue) result = addStmt(condExpr); + if (opaqueValue) { + // Run the condition expression if it's not trivially expressed in + // terms of the opaque value (or if there is no opaque value). + if (condExpr != opaqueValue) + addStmt(condExpr); - // Before that, run the common subexpression if there was one. - // At least one of this or the above will be run. - if (opaqueValue) result = addStmt(BCO->getCommon()); - - return result; + // Before that, run the common subexpression if there was one. + // At least one of this or the above will be run. + return addStmt(BCO->getCommon()); + } + + return addStmt(condExpr); } CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index ecaff295b3..1bffa3022e 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -32,6 +32,11 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { switch (E->getStmtClass()) { case Stmt::AddrLabelExprClass: return svalBuilder.makeLoc(cast(E)); + case Stmt::OpaqueValueExprClass: { + const OpaqueValueExpr *ope = cast(E); + E = ope->getSourceExpr(); + continue; + } case Stmt::ParenExprClass: // ParenExprs are no-ops. E = cast(E)->getSubExpr(); diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 4daf899a8d..7f117ccfa1 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -1246,3 +1246,26 @@ void pr9269() { ++i) {} } +// Test evaluation of GNU-style ?:. +int pr9287(int type) { return type ? : 0; } // no-warning + +void pr9287_b(int type, int *p) { + int x = type ? : 0; + if (x) { + p = 0; + } + if (type) { + *p = 0xDEADBEEF; // expected-warning {{null pointer}} + } +} + +void pr9287_c(int type, int *p) { + int x = type ? : 0; + if (x) { + p = 0; + } + if (!type) { + *p = 0xDEADBEEF; // no-warning + } +} +