<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Nov 30, 2011, at 10:09 PM, David Blaikie 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; ">Does this mean we can't analyze any function involving macros? That<br>would seem overly limiting. Should we try to record more detail about<br>the graph again, such as where a branch (or lack of one) came from?<br>How practical is that?</span></blockquote></div><br><div>This is all a bit of art, but it is about hitting the sweet spot between false positives and false negatives, complexity of implementation (and cleverness) versus payoff. This isn't about soundness; -Wunreachable-code was correctly warning in template instantiations that some code is unreachable. The problem is that there are cases where we don't care, because it doesn't indicate a problem in the original code (e.g., the original template body). The goal of the warning is to find bugs, so we should concentrate on stylistically what kind of deadcode doesn't look intentional.</div><div><br></div><div>For templates, my concern is that the template instantiation can routinely impact control-flow in bizarre ways. We could itemize the common ways that unreachable code occurs in template instantiations, and see if we can do something clever. I think some of this could be done using the CFG approach I described (e.g., recording that specific pruned branches were "instantiation-dependent"). That might be acceptable for a large number of cases, but the analysis isn't trivial. I'm very skeptical that the payoff would be worth it versus the complexity of the implementation.</div><div><br></div><div>Macros I think are more nuanced. Consider the following two cases:</div><div><br></div><div> if (MACRO_INSTANTIATION)</div><div> unreachable</div><div><br></div><div>and</div><div><br></div><div> MACRO_INSTANTIATION_THAT_CONTAINS_UNREACHABLE_CODE</div><div><br></div><div>For the latter, my gut is to never issue a -Wunreachable-code warning. It's basically the same as templates; the instantiated code could be anything (and it frequently does). Many people use macro instantiations understanding that the macro will generate a ton of goop, only to get optimized away from the compiler. I think warning about unreachable code within macros is going to have marginal utility. However, if we saw something like this:</div><div><br></div><div> MACRO_INSTANTIATION_THAT_BLOCKS_FURTHER_EXECUTION</div><div> deadcode</div><div><br></div><div>should we warn about 'deadcode'? Probably not. It's probably no different than using llvm_unreachable.</div><div><br></div><div>Then there is also the case of:</div><div><br></div><div> if (COMPILE_TIME_CONSTANT)</div><div> unreachable</div><div><br></div><div>There, I think it depends on how the compile-time constant was computed. If the constant involved macros, e.g.:</div><div><br></div><div> if (MACRO_A + 1)</div><div><br></div><div>then I'd say this is the same as:</div><div><br></div><div> if (MACRO_INSTANTIATION)</div><div><br></div><div>If it was something like:</div><div><br></div><div> if (some_constant_dependent_on_langoptions_or_triple)</div><div><br></div><div>then I'd also treat it like "if (MACRO_INSTANTIATION)". This is basically 'sizeof(long) == sizeof(int)". It's basically meta-programming of a sort, and we don't know that for a different program "instantiation" (e.g., on a different architecture) that the code would have behaved differently.</div><div><br></div><div>If, however, it looks something like:</div><div><br></div><div> if (2 * 0)</div><div> unreachable</div><div><br></div><div>I think we should definitely warn. There is nothing here that relies on "meta-programming". It's all concrete, and clearly the developer made a mistake.</div><div><br></div><div>So the bottom line is that I think it comes down to a grab bag of heuristics. With the CFG approach I described, I'm basically saying we retain "ghost" edges for the edges we would have pruned. Heck, we don't even need to record why they were pruned, just that they were pruned. -Wunreachable-code, if it cares, could go an infer the specific cases of why an edge was pruned (or what was involved, e.g. a macro instantiation in the condition).</div><div><br></div><div>One nice thing of leaving the heuristics up to -Wunreachable-code is that it doesn't complicate CFG construction. CFG construction just records the ghost edges, and it is up to specific analyses to decide what to do with them (if anything).</div></body></html>