<div dir="ltr"><div>Hello Haowei,<br><br></div>You described most of the behaviors right but not exactly.<br><div><div><div class="gmail_extra"><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>When I run clang static analyzer on this piece of code with scan-build, the function "func_with_loop()" will not be inlined by ExprEngine.</div><div><br></div></div></blockquote><div>The func_with_loop() function will be inlined for sure. That is what your example has just proven by producing the line:<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><font face="monospace, monospace">testmxchannel.c:204:3func_<wbr>with_loop  Should inline: Direct inlined</font></div></div></div></blockquote><div><br></div><div>So it will be inlined. Lets considering the next important line in the output:<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><font face="monospace, monospace">Block Count exceeded maxBlockVisitOnPath 4Dump SRC</font></div><div><font face="monospace, monospace"></font></div><div><font face="monospace, monospace">...<br></font></div><div><font face="monospace, monospace">testmxchannel.c:204:3func_<wbr>with_loop  InlinedFailedState is not null  Should not inline </font></div></div><div> </div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>It seems that the ExprEngine did try to inline the function "func_with_loop", but the total block count of this function exceeded "maxBlockVisitOnPath", which by default is 4. The inline process was rolled back and this function is evaluated by "conservativeEvalCall".<br></div></div></blockquote><div> <br></div><div>Yeah. that is what happens BUT! only on the <b>PATH</b> where the maxBlockVisitOnPath exceeded. So the other paths will be simulated but this path will be rolled back before the point where the analyzer inline the function and mark the function not to be inlined again (<i><span style="font-family:monospace,monospace">NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE)</span></i><span style="font-family:monospace,monospace">)</span>. So simulating again that path will trigger the defaultEvalCall on the same function call which was just rolled back and marked so the analyzer won't inline it. That is what is checked by the <i>getInlineFailedState() </i>and that is the reason why the 2. output says it should not be inlined<i>. <br></i></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif">In my understanding, by default, when clang static analyzer evaluate a loop that the total times of the loop cannot determined, the loop will be evaluated for 4 times and an additional ExplodedNode will be created with the loop condition evaluated to false. But why in this code example it causes the function inline to be rolled back instead of creating an additional node that evaluate the loop conditions to false?</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div></div></blockquote><div>Not exactly. The ExplodedGraph will be forked every time when the loop condition is evaluated. So there will be 5 different paths int ExplodedGraph while simulating a loop like this:<br></div><div>- when the condition is false<br>- when the condition is false after the 1. step<br>- when the condition is false after the 2. step<br>- when the condition is false after the 3. step<br>- when the condition is true every time - but this will be the path where the maxBlockVisitOnPath exceeds and then the above mentioned things happen.<br><br></div><div>Why is it important to replay the analysis without inlining this function which contains a loop?<br></div><div>The most problematic case is when the bound is known so the analyzer won't create new branches for paths where the condition can be false if it knows it can't be. For example if you try out a code like this:<br><div><br></div><div><div><font face="monospace, monospace">void func_with_loop(int loop_times) {</font></div><div><font face="monospace, monospace">  for (int i = 0; i < loop_times; i++) {</font></div><div><font face="monospace, monospace">    //Do nothing</font></div><div><font face="monospace, monospace">  }</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">void call_loop() {</font></div><div><font face="monospace, monospace">  func_with_loop(12);<br></font></div><div><font face="monospace, monospace">  ... //the most complex body you can just imagine<br></font></div><div><font face="monospace, monospace">}<br><br></font></div><div><font face="monospace, monospace"><span style="font-family:arial,helvetica,sans-serif">In this case (without the replaying-without-inlining feature) the analysis of this call_loop function would be ended while analyzing the inlined <span style="font-family:monospace,monospace">func_with_loop()</span> function and </span></font>exceeding the<font face="monospace, monospace"> maxBlockVisitOnPath. <font face="arial,helvetica,sans-serif">Which is not something you would like to see so the state is going to be rolled back and the other parts of the function will be analyzed but without knowing what the func_with_loop() function did (so yes, with more unknown value).</font><br></font></div></div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif"></font></div><div><font face="arial, helvetica, sans-serif">Another question I have is that is it possible in checkPreCall() callback of a checker to determine if the function call will not be inlined by ExprEngine? </font></div><div><font face="arial, helvetica, sans-serif"><br></font></div></div></blockquote><div>I would be surprised if you can check that in checkPreCall() but maybe somebody else (probably NoQ) knows a way to check this.  (in checkPostCall() you can do this for sure by checking the <span style="font-family:monospace,monospace">wasInlined</span> flag of the CheckerContext.) <br><br></div><div>I hope I could help at least a little bit.<br><br></div><div>Cheers,<br></div><div>Peter<br></div></div></div></div></div></div>