<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Nov 19, 2011, at 9:07 PM, Cyril Roelandt wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; ">The code should look a little bit better now. Three different functions are used. The 0-checking and report emission are now two different functions, for I thought they served a different purpose, and that the code would be easier to understand that way.</span></blockquote></div><br><div>Hi Cyril,</div><div><br></div><div>I like this patch.  I have a few specific comments inline:</div><div><br></div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp</font></div><div><font class="Apple-style-span" color="#000000">index e955f9e..6a4d63f 100644</font></div><div><font class="Apple-style-span" color="#000000">--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp</font></div><div><font class="Apple-style-span" color="#000000">+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp</font></div><div><font class="Apple-style-span" color="#000000">@@ -36,10 +36,17 @@ public:</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">   void CheckOpen(CheckerContext &C, const CallExpr *CE) const;</font></div><div><font class="Apple-style-span" color="#000000">   void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;</font></div><div><font class="Apple-style-span" color="#000000">+  void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;</font></div><div><font class="Apple-style-span" color="#000000">   void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;</font></div><div><font class="Apple-style-span" color="#000000">+  void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">   typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,</font></div><div><font class="Apple-style-span" color="#000000">                                              const CallExpr *) const;</font></div><div><font class="Apple-style-span" color="#000000">+private:</font></div><div><font class="Apple-style-span" color="#000000">+  void ReportZeroByteAllocation(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000">+                                const ExplodedNode *N,</font></div><div><font class="Apple-style-span" color="#000000">+                                const Expr *arg,</font></div><div><font class="Apple-style-span" color="#000000">+                                const char *fn_name) const;</font></div><div><font class="Apple-style-span" color="#000000"> };</font></div><div><font class="Apple-style-span" color="#000000"> } //end anonymous namespace</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">@@ -170,48 +177,138 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000"> }</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000"> //===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" color="#000000">-// "malloc" with allocation size 0</font></div><div><font class="Apple-style-span" color="#000000">+//"calloc",  "malloc" and "realloc" with allocation size 0</font></div></blockquote><div><br></div><div>Very minor: please maintain the space here between the '//' and the first letter.</div><div><br></div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000"> //===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">+// Fills in trueState and falseState</font></div></blockquote><div><br></div><div>Minor: please follow the LLVM convention of ending comments with a '.'</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+static int IsZeroByteAllocation(const ProgramState *state,</font></div><div><font class="Apple-style-span" color="#000000">+                                const SVal argVal,</font></div><div><font class="Apple-style-span" color="#000000">+                                const ProgramState **trueState,</font></div><div><font class="Apple-style-span" color="#000000">+                                const ProgramState **falseState) {</font></div><div><font class="Apple-style-span" color="#000000">+  llvm::tie(*trueState, *falseState) = state->assume(cast<DefinedSVal>(argVal));</font></div><div><font class="Apple-style-span" color="#000000">+  return (*falseState && !*trueState);</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div></blockquote><br></div><div>Please have this method return 'bool'.  This is C++.  :)</div><div><br></div><div>Also, please have a comment indicate what the return value indicates.</div><div><br></div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+// N should be non-null here.</font></div></blockquote><div><br></div><div>Please expand the comments, indicating what this function does.</div><div><br></div><div>Also, instead of having a comment that says "N should be non-null", how about</div><div>using __attribute__((nonnull))?</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+void UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000">+                                            const ExplodedNode *N,</font></div><div><font class="Apple-style-span" color="#000000">+                                            const Expr *arg,</font></div><div><font class="Apple-style-span" color="#000000">+                                            const char *fn_name) const {</font></div><div><font class="Apple-style-span" color="#000000">+  // FIXME: Add reference to CERT advisory, and/or C99 standard in bug</font></div><div><font class="Apple-style-span" color="#000000">+  // output.</font></div><div><font class="Apple-style-span" color="#000000">+  LazyInitialize(BT_mallocZero, "Undefined allocation of 0 bytes");</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  llvm::SmallString<256> S;</font></div><div><font class="Apple-style-span" color="#000000">+  llvm::raw_svector_ostream os(S);    </font></div><div><font class="Apple-style-span" color="#000000">+  os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";</font></div><div><font class="Apple-style-span" color="#000000">+  BugReport *report = new BugReport(*BT_mallocZero, os.str(), N);</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  report->addRange(arg->getSourceRange());</font></div><div><font class="Apple-style-span" color="#000000">+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, arg));</font></div><div><font class="Apple-style-span" color="#000000">+  C.EmitReport(report);</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div></blockquote><div><br></div><div>Looks good.</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+void UnixAPIChecker::CheckCallocZero(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000">+                                     const CallExpr *CE) const {</font></div><div><font class="Apple-style-span" color="#000000">+  if (CE->getNumArgs() != 2)</font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  SVal argVal;</font></div><div><font class="Apple-style-span" color="#000000">+  const Expr *arg;</font></div><div><font class="Apple-style-span" color="#000000">+  const ProgramState *state = C.getState();</font></div><div><font class="Apple-style-span" color="#000000">+  const ProgramState *trueState = NULL, *falseState = NULL;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  /* Check if one of the arguments is equal to 0 */</font></div><div><font class="Apple-style-span" color="#000000">+  arg = CE->getArg(0);</font></div><div><font class="Apple-style-span" color="#000000">+  argVal = state->getSVal(arg);</font></div></blockquote><div><br></div><div>This is unnecessarily verbose.  You can just tie declaration and initialization on one line.  All, please use '//' style comments, not /* *..</div><div><br></div><div>For example:</div><div><br></div><div>const ProgramState *state = C.getState();</div><div>const ProgramState *trueState = 0, *falseState = 0;</div><div><br></div><div>// Check if one of the arguments is equal to 0.</div><div>const Expr *arg = CE->getArg(0);</div><div>SVal argVal = state->getSVal(arg);</div><div><br></div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+  if (argVal.isUnknownOrUndef())</font></div><div><font class="Apple-style-span" color="#000000">+    goto check_snd_arg;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {</font></div><div><font class="Apple-style-span" color="#000000">+    ExplodedNode *N = C.generateSink(falseState);</font></div><div><font class="Apple-style-span" color="#000000">+    if (!N)</font></div><div><font class="Apple-style-span" color="#000000">+      goto check_snd_arg;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+    UnixAPIChecker::ReportZeroByteAllocation(C, N, arg, "calloc"); </font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div></blockquote><div><br></div><div>I'm not a huge fan of gotos.  They stylistically are problematic in C++.  It's okay here, but I still think it is a little gross.  You could alternatively have a "do ... while(0)" and use "break" statements instead.  It's a little gross as well (to some people), but it is more structured.</div><div><br></div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+check_snd_arg:</font></div><div><font class="Apple-style-span" color="#000000">+  arg = CE->getArg(1);</font></div><div><font class="Apple-style-span" color="#000000">+  argVal = state->getSVal(arg);</font></div><div><font class="Apple-style-span" color="#000000">+  if (argVal.isUnknownOrUndef())</font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {</font></div><div><font class="Apple-style-span" color="#000000">+    ExplodedNode *N = C.generateSink(falseState);</font></div><div><font class="Apple-style-span" color="#000000">+    if (!N)</font></div><div><font class="Apple-style-span" color="#000000">+      return;</font></div></blockquote><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+    UnixAPIChecker::ReportZeroByteAllocation(C, N, arg, "calloc"); </font></div></blockquote><div><br></div><div>Why do we need this fully qualified name?  Why not just 'ReportZeroByteAllocation()'?</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div></blockquote><div><br></div><div>If we have 'ReportZeroByteAllocation() generate the sink node and do the null check, you could just do:</div><div><br></div><div>  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState) {</div><div>   UnixAPIChecker::ReportZeroByteAllocation(C, falseState, arg, "calloc");</div><div>   return;</div><div>  }</div><div><br></div><div>Same thing for the other callsites.</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  // Assume the the value is non-zero going forward.</font></div><div><font class="Apple-style-span" color="#000000">+  assert(trueState);</font></div><div><font class="Apple-style-span" color="#000000">+  if (trueState != state) {</font></div><div><font class="Apple-style-span" color="#000000">+    C.addTransition(trueState);</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div></blockquote><div><br></div><div>Can just be made:</div><div> </div><div> if (trueState != state)</div><div>   C.addTransition(trueState);</div><div><br></div><div>No need for the extra braces.</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000"> // FIXME: Eventually this should be rolled into the MallocChecker, but this</font></div><div><font class="Apple-style-span" color="#000000"> // check is more basic and is valuable for widespread use.</font></div><div><font class="Apple-style-span" color="#000000"> void UnixAPIChecker::CheckMallocZero(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000">                                      const CallExpr *CE) const {</font></div><div><font class="Apple-style-span" color="#000000">-</font></div><div><font class="Apple-style-span" color="#000000">   // Sanity check that malloc takes one argument.</font></div><div><font class="Apple-style-span" color="#000000">   if (CE->getNumArgs() != 1)</font></div><div><font class="Apple-style-span" color="#000000">     return;</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">   // Check if the allocation size is 0.</font></div><div><font class="Apple-style-span" color="#000000">   const ProgramState *state = C.getState();</font></div><div><font class="Apple-style-span" color="#000000">-  SVal argVal = state->getSVal(CE->getArg(0));</font></div><div><font class="Apple-style-span" color="#000000">+  const ProgramState *trueState = NULL, *falseState = NULL;</font></div><div><font class="Apple-style-span" color="#000000">+  const Expr *arg = CE->getArg(0);</font></div><div><font class="Apple-style-span" color="#000000">+  SVal argVal = state->getSVal(arg);</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">   if (argVal.isUnknownOrUndef())</font></div><div><font class="Apple-style-span" color="#000000">     return;</font></div><div><font class="Apple-style-span" color="#000000">-  </font></div><div><font class="Apple-style-span" color="#000000">-  const ProgramState *trueState, *falseState;</font></div><div><font class="Apple-style-span" color="#000000">-  llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal));</font></div><div><font class="Apple-style-span" color="#000000">-  </font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">   // Is the value perfectly constrained to zero?</font></div><div><font class="Apple-style-span" color="#000000">-  if (falseState && !trueState) {</font></div><div><font class="Apple-style-span" color="#000000">+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {</font></div><div><font class="Apple-style-span" color="#000000">     ExplodedNode *N = C.generateSink(falseState);</font></div><div><font class="Apple-style-span" color="#000000">-    if (!N)</font></div><div><font class="Apple-style-span" color="#000000">-      return;</font></div><div><font class="Apple-style-span" color="#000000">-    </font></div><div><font class="Apple-style-span" color="#000000">-    // FIXME: Add reference to CERT advisory, and/or C99 standard in bug</font></div><div><font class="Apple-style-span" color="#000000">-    // output.</font></div><div><font class="Apple-style-span" color="#000000">+    if (N) {</font></div><div><font class="Apple-style-span" color="#000000">+      UnixAPIChecker::ReportZeroByteAllocation(C, N, arg, "malloc"); </font></div></blockquote><div><br></div>Why do we need this fully qualified name?  Why not just 'ReportZeroByteAllocation()'?</div><div><br></div><div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+    }</font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div></blockquote><div><br></div><div>Same comment as before.  If we have ReportZeroByteAllocation() do the generation of the node, you can compress this code. </div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+  // Assume the the value is non-zero going forward.</font></div><div><font class="Apple-style-span" color="#000000">+  assert(trueState);</font></div><div><font class="Apple-style-span" color="#000000">+  if (trueState != state) {</font></div><div><font class="Apple-style-span" color="#000000">+    C.addTransition(trueState);</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div></blockquote><div><br></div><div>Ditch the extra braces.</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">-    LazyInitialize(BT_mallocZero, "Undefined allocation of 0 bytes");</font></div><div><font class="Apple-style-span" color="#000000">-    </font></div><div><font class="Apple-style-span" color="#000000">-    BugReport *report =</font></div><div><font class="Apple-style-span" color="#000000">-      new BugReport(*BT_mallocZero, "Call to 'malloc' has an allocation"</font></div><div><font class="Apple-style-span" color="#000000">-                                            " size of 0 bytes", N);</font></div><div><font class="Apple-style-span" color="#000000">-    report->addRange(CE->getArg(0)->getSourceRange());</font></div><div><font class="Apple-style-span" color="#000000">-    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,</font></div><div><font class="Apple-style-span" color="#000000">-                                                                CE->getArg(0)));</font></div><div><font class="Apple-style-span" color="#000000">-    C.EmitReport(report);</font></div><div><font class="Apple-style-span" color="#000000">+void UnixAPIChecker::CheckReallocZero(CheckerContext &C,</font></div><div><font class="Apple-style-span" color="#000000">+                                      const CallExpr *CE) const {</font></div><div><font class="Apple-style-span" color="#000000">+  if (CE->getNumArgs() != 2)</font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  const ProgramState *state = C.getState();</font></div><div><font class="Apple-style-span" color="#000000">+  const ProgramState *trueState = NULL, *falseState = NULL;</font></div><div><font class="Apple-style-span" color="#000000">+  const Expr *arg = CE->getArg(1);</font></div><div><font class="Apple-style-span" color="#000000">+  SVal argVal = state->getSVal(arg);</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+  if (argVal.isUnknownOrUndef())</font></div><div><font class="Apple-style-span" color="#000000">+    return;</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">+</font></div></blockquote><div><br></div><div>We don't need two blank lines.</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">+  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {</font></div><div><font class="Apple-style-span" color="#000000">+    ExplodedNode *N = C.generateSink(falseState);</font></div><div><font class="Apple-style-span" color="#000000">+    if (N) {</font></div><div><font class="Apple-style-span" color="#000000">+      UnixAPIChecker::ReportZeroByteAllocation(C, N, arg, "realloc");</font></div><div><font class="Apple-style-span" color="#000000">+    }</font></div><div><font class="Apple-style-span" color="#000000">     return;</font></div></blockquote><div><br></div><div>Per comment above, this can be made more condensed by sinking the node generation into ReportZeroByteAllocation().</div><br><blockquote type="cite"><div><font class="Apple-style-span" color="#000000">   }</font></div><div><font class="Apple-style-span" color="#000000">+</font></div><div><font class="Apple-style-span" color="#000000">   // Assume the the value is non-zero going forward.</font></div><div><font class="Apple-style-span" color="#000000">   assert(trueState);</font></div><div><font class="Apple-style-span" color="#000000">   if (trueState != state) {</font></div><div><font class="Apple-style-span" color="#000000">@@ -232,7 +329,9 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {</font></div><div><font class="Apple-style-span" color="#000000">     llvm::StringSwitch<SubChecker>(FName)</font></div><div><font class="Apple-style-span" color="#000000">       .Case("open", &UnixAPIChecker::CheckOpen)</font></div><div><font class="Apple-style-span" color="#000000">       .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)</font></div><div><font class="Apple-style-span" color="#000000">+      .Case("calloc", &UnixAPIChecker::CheckCallocZero)</font></div><div><font class="Apple-style-span" color="#000000">       .Case("malloc", &UnixAPIChecker::CheckMallocZero)</font></div><div><font class="Apple-style-span" color="#000000">+      .Case("realloc", &UnixAPIChecker::CheckReallocZero)</font></div><div><font class="Apple-style-span" color="#000000">       .Default(NULL);</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000">   if (SC)</font></div><div><font class="Apple-style-span" color="#000000">diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c</font></div><div><font class="Apple-style-span" color="#000000">index cf5ca81..86b95c6 100644</font></div><div><font class="Apple-style-span" color="#000000">--- a/test/Analysis/unix-fns.c</font></div><div><font class="Apple-style-span" color="#000000">+++ b/test/Analysis/unix-fns.c</font></div><div><font class="Apple-style-span" color="#000000">@@ -9,7 +9,9 @@ typedef __darwin_pthread_once_t pthread_once_t;</font></div><div><font class="Apple-style-span" color="#000000"> int pthread_once(pthread_once_t *, void (*)(void));</font></div><div><font class="Apple-style-span" color="#000000"> typedef long unsigned int __darwin_size_t;</font></div><div><font class="Apple-style-span" color="#000000"> typedef __darwin_size_t size_t;</font></div><div><font class="Apple-style-span" color="#000000">+void *calloc(size_t, size_t);</font></div><div><font class="Apple-style-span" color="#000000"> void *malloc(size_t);</font></div><div><font class="Apple-style-span" color="#000000">+void *realloc(void *, size_t);</font></div><div><font class="Apple-style-span" color="#000000"> </font></div><div><font class="Apple-style-span" color="#000000"> typedef void (^dispatch_block_t)(void);</font></div><div><font class="Apple-style-span" color="#000000"> typedef long dispatch_once_t;</font></div><div><font class="Apple-style-span" color="#000000">@@ -66,3 +68,33 @@ void pr2899_nowarn(size_t size) {</font></div><div><font class="Apple-style-span" color="#000000">     foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">   }</font></div><div><font class="Apple-style-span" color="#000000"> }</font></div><div><font class="Apple-style-span" color="#000000">+void test_calloc(void) {</font></div><div><font class="Apple-style-span" color="#000000">+  char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}}</font></div><div><font class="Apple-style-span" color="#000000">+  for (unsigned i = 0; i < 100; i++) {</font></div><div><font class="Apple-style-span" color="#000000">+    foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000">+void test_calloc2(void) {</font></div><div><font class="Apple-style-span" color="#000000">+  char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}}</font></div><div><font class="Apple-style-span" color="#000000">+  for (unsigned i = 0; i < 100; i++) {</font></div><div><font class="Apple-style-span" color="#000000">+    foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000">+void test_calloc_nowarn(size_t nmemb, size_t size) {</font></div><div><font class="Apple-style-span" color="#000000">+  char *foo = calloc(nmemb, size); // no-warning</font></div><div><font class="Apple-style-span" color="#000000">+  for (unsigned i = 0; i < 100; i++) {</font></div><div><font class="Apple-style-span" color="#000000">+    foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000">+void test_realloc(char *ptr) {</font></div><div><font class="Apple-style-span" color="#000000">+  char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc' has an allocation size of 0 bytes}}</font></div><div><font class="Apple-style-span" color="#000000">+  for (unsigned i = 0; i < 100; i++) {</font></div><div><font class="Apple-style-span" color="#000000">+    foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div><div><font class="Apple-style-span" color="#000000">+void test_realloc_nowarn(char *ptr, size_t size) {</font></div><div><font class="Apple-style-span" color="#000000">+  char *foo = realloc(ptr, size); // no-warning</font></div><div><font class="Apple-style-span" color="#000000">+  for (unsigned i = 0; i < 100; i++) {</font></div><div><font class="Apple-style-span" color="#000000">+    foo[i] = 0;</font></div><div><font class="Apple-style-span" color="#000000">+  }</font></div><div><font class="Apple-style-span" color="#000000">+}</font></div></blockquote><br></div><div>Test cases look good.</div><div><div><br></div></div></body></html>