<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">These are the cases I get:<div class=""><br class=""></div><div class="">#define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; }</div><div class=""><br class=""></div><div class="">and</div><div class=""><br class=""></div><div class=""><div class="">#if 0</div><div class="">#define DEBG(fmt, args...)      { IOLog(fmt, ## args); kprintf(fmt, ## args); }</div><div class="">#else</div><div class="">#define DEBG(fmt, args...)      {}</div><div class="">#endif</div><div class=""><br class=""></div><div class="">Now calls</div><div class=""><br class=""></div><div class="">`DEBG(‘x’);` and `unexpected(‘msg’);`</div><div class=""><br class=""></div><div class="">cause the warning to be fired.</div><div class="">Of course, semicolon could be omitted, but the fact that the macro has braces is sort of an implementation detail.</div><div class=""><br class=""></div><div class="">Greg Parker has pointed out it’s possible to rewrite the macros using the “do { … } while (0)”,</div><div class="">but that is a lot of macros to change, and the resulting code would be arguably less readable.</div><div><br class=""><blockquote type="cite" class=""><div class="">On Dec 5, 2018, at 5:10 AM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com" class="">aaron@aaronballman.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">On Wed, Dec 5, 2018 at 1:40 AM Roman Lebedev <</span><a href="mailto:lebedev.ri@gmail.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">lebedev.ri@gmail.com</a><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">> wrote:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">It is a problem in practice for us since we have projects which enable all available warnings and also enable “-Werror”.<br class=""></blockquote></blockquote></blockquote></blockquote>Hm, they have asked for -Weverything and they got it. Seems to be<br class="">working as intended.<br class="">When in previous discussions elsewhere i have talked about<br class="">-Weverything, i was always<br class="">been told that it isn't supposed to be used like that (admittedly, i<br class="">*do* use it like that :)).<br class=""><br class="">Could you explain how is this different from any other warning that is<br class="">considered pointless by the project?<br class="">Why not simply disable it?<br class=""></blockquote></div></blockquote><div><br class=""></div><div>You are right, it could be disabled. It’s just for this warning the noise vs. usefulness ratio seemed pretty low.</div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">Would you be okay with the warning if it was only diagnosed when the<br class="">source location of the semi-colon is not immediately preceded by a<br class="">macro expansion location? e.g.,<br class=""><br class="">EMPTY_EXPANSION(12); // Not diagnosed<br class="">EMPTY_EXPANSION; // Not diagnosed<br class="">; // Diagnosed<br class=""></blockquote>This could work provided that all empty space preceding the semicolon is ignored (as the macro could be separated by space(s) or newline(s).<br class="">I’m not sure the complexity would be worth it, as I haven’t seen bugs arising from extra semicolons and empty statements,<br class="">but it would take care of my use case.<br class=""><br class=""></blockquote><br class="">Or rather when the *previous* semicolon is coming from a macro.<br class=""></blockquote>I don't like this. clang is already wa-a-ay too forgiving about<br class="">macros, it almost ignores almost every warning in macros.<br class="">It was an *intentional* decision to still warn on useless ';' after<br class="">non-empty macros.<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">I think I'm confused now. This is a test case:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">NULLMACRO(v7); // OK. This could be either GOODMACRO() or</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">BETTERMACRO() situation, so we can't know we can drop it.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">So empty macro expansions should be ignored as I expected... so what</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">is being diagnosed? George, can you provide a more clear example that</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">demonstrates the issue?</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">To be clear, I do *not* think this is a situation we should spend</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">effort supporting (assuming "all available warnings" really means</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">-Weverything and not something else):</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class="">It is a problem in practice for us since we have projects which enable all available warnings and also enable “-Werror”.<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">However, if we are diagnosing *empty* macro expansions followed by a</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">semi-colon, I think that would be unacceptably chatty and is worth</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">fixing on its own merits.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">~Aaron</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">~Aaron<br class=""><br class=""><blockquote type="cite" class="">Regards,<br class="">George<br class=""></blockquote></blockquote></blockquote></blockquote>Roman.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">On Nov 20, 2018, at 10:59 AM, Roman Lebedev via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:<br class=""><br class="">Author: lebedevri<br class="">Date: Tue Nov 20 10:59:05 2018<br class="">New Revision: 347339<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=347339&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=347339&view=rev</a><br class="">Log:<br class="">[clang][Parse] Diagnose useless null statements / empty init-statements<br class=""><br class="">Summary:<br class="">clang has `-Wextra-semi` (D43162), which is not dictated by the currently selected standard.<br class="">While that is great, there is at least one more source of need-less semis - 'null statements'.<br class="">Sometimes, they are needed:<br class="">```<br class="">for(int x = 0; continueToDoWork(x); x++)<br class="">; // Ugly code, but the semi is needed here.<br class="">```<br class=""><br class="">But sometimes they are just there for no reason:<br class="">```<br class="">switch(X) {<br class="">case 0:<br class="">return -2345;<br class="">case 5:<br class="">return 0;<br class="">default:<br class="">return 42;<br class="">}; // <- oops<br class=""><br class="">;;;;;;;;;;; <- OOOOPS, still not diagnosed. Clearly this is junk.<br class="">```<br class=""><br class="">Additionally:<br class="">```<br class="">if(; // <- empty init-statement<br class=""> true)<br class="">;<br class=""><br class="">switch (; // empty init-statement<br class="">      x) {<br class="">...<br class="">}<br class=""><br class="">for (; // <- empty init-statement<br class="">   int y : S())<br class="">;<br class="">}<br class=""><br class="">As usual, things may or may not go sideways in the presence of macros.<br class="">While evaluating this diag on my codebase of interest, it was unsurprisingly<br class="">discovered that Google Test macros are *very* prone to this.<br class="">And it seems many issues are deep within the GTest itself, not<br class="">in the snippets passed from the codebase that uses GTest.<br class=""><br class="">So after some thought, i decided not do issue a diagnostic if the semi<br class="">is within *any* macro, be it either from the normal header, or system header.<br class=""><br class="">Fixes [[ <a href="https://bugs.llvm.org/show_bug.cgi?id=39111" class="">https://bugs.llvm.org/show_bug.cgi?id=39111</a> | PR39111 ]]<br class=""><br class="">Reviewers: rsmith, aaron.ballman, efriedma<br class=""><br class="">Reviewed By: aaron.ballman<br class=""><br class="">Subscribers: cfe-commits<br class=""><br class="">Differential Revision: <a href="https://reviews.llvm.org/D52695" class="">https://reviews.llvm.org/D52695</a><br class=""><br class="">Added:<br class="">  cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp<br class="">  cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp<br class="">Modified:<br class="">  cfe/trunk/docs/ReleaseNotes.rst<br class="">  cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br class="">  cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br class="">  cfe/trunk/include/clang/Parse/Parser.h<br class="">  cfe/trunk/lib/Parse/ParseExprCXX.cpp<br class="">  cfe/trunk/lib/Parse/ParseStmt.cpp<br class=""><br class="">Modified: cfe/trunk/docs/ReleaseNotes.rst<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/docs/ReleaseNotes.rst (original)<br class="">+++ cfe/trunk/docs/ReleaseNotes.rst Tue Nov 20 10:59:05 2018<br class="">@@ -55,6 +55,63 @@ Major New Features<br class="">Improvements to Clang's diagnostics<br class="">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br class=""><br class="">+- ``-Wextra-semi-stmt`` is a new diagnostic that diagnoses extra semicolons,<br class="">+  much like ``-Wextra-semi``. This new diagnostic diagnoses all *unnecessary*<br class="">+  null statements (expression statements without an expression), unless: the<br class="">+  semicolon directly follows a macro that was expanded to nothing or if the<br class="">+  semicolon is within the macro itself. This applies to macros defined in system<br class="">+  headers as well as user-defined macros.<br class="">+<br class="">+  .. code-block:: c++<br class="">+<br class="">+      #define MACRO(x) int x;<br class="">+      #define NULLMACRO(varname)<br class="">+<br class="">+      void test() {<br class="">+        ; // <- warning: ';' with no preceding expression is a null statement<br class="">+<br class="">+        while (true)<br class="">+          ; // OK, it is needed.<br class="">+<br class="">+        switch (my_enum) {<br class="">+        case E1:<br class="">+          // stuff<br class="">+          break;<br class="">+        case E2:<br class="">+          ; // OK, it is needed.<br class="">+        }<br class="">+<br class="">+        MACRO(v0;) // Extra semicolon, but within macro, so ignored.<br class="">+<br class="">+        MACRO(v1); // <- warning: ';' with no preceding expression is a null statement<br class="">+<br class="">+        NULLMACRO(v2); // ignored, NULLMACRO expanded to nothing.<br class="">+      }<br class="">+<br class="">+- ``-Wempty-init-stmt`` is a new diagnostic that diagnoses empty init-statements<br class="">+  of ``if``, ``switch``, ``range-based for``, unless: the semicolon directly<br class="">+  follows a macro that was expanded to nothing or if the semicolon is within the<br class="">+  macro itself (both macros from system headers, and normal macros). This<br class="">+  diagnostic is in the ``-Wextra-semi-stmt`` group and is enabled in<br class="">+  ``-Wextra``.<br class="">+<br class="">+  .. code-block:: c++<br class="">+<br class="">+      void test() {<br class="">+        if(; // <- warning: init-statement of 'if' is a null statement<br class="">+           true)<br class="">+          ;<br class="">+<br class="">+        switch (; // <- warning: init-statement of 'switch' is a null statement<br class="">+                x) {<br class="">+          ...<br class="">+        }<br class="">+<br class="">+        for (; // <- warning: init-statement of 'range-based for' is a null statement<br class="">+             int y : S())<br class="">+          ;<br class="">+      }<br class="">+<br class=""><br class="">Non-comprehensive list of changes in this release<br class="">-------------------------------------------------<br class=""><br class="">Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br class="">+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Nov 20 10:59:05 2018<br class="">@@ -162,6 +162,8 @@ def GNUEmptyStruct : DiagGroup<"gnu-empt<br class="">def ExtraTokens : DiagGroup<"extra-tokens">;<br class="">def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">;<br class="">def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;<br class="">+def EmptyInitStatement : DiagGroup<"empty-init-stmt">;<br class="">+def ExtraSemiStmt : DiagGroup<"extra-semi-stmt", [EmptyInitStatement]>;<br class="">def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi,<br class="">                                        CXX11ExtraSemi]>;<br class=""><br class="">@@ -768,7 +770,8 @@ def Extra : DiagGroup<"extra", [<br class="">   MissingMethodReturnType,<br class="">   SignCompare,<br class="">   UnusedParameter,<br class="">-    NullPointerArithmetic<br class="">+    NullPointerArithmetic,<br class="">+    EmptyInitStatement<br class=""> ]>;<br class=""><br class="">def Most : DiagGroup<"most", [<br class=""><br class="">Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)<br class="">+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Nov 20 10:59:05 2018<br class="">@@ -53,6 +53,10 @@ def ext_extra_semi_cxx11 : Extension<<br class="">def warn_extra_semi_after_mem_fn_def : Warning<<br class=""> "extra ';' after member function definition">,<br class=""> InGroup<ExtraSemi>, DefaultIgnore;<br class="">+def warn_null_statement : Warning<<br class="">+  "empty expression statement has no effect; "<br class="">+  "remove unnecessary ';' to silence this warning">,<br class="">+  InGroup<ExtraSemiStmt>, DefaultIgnore;<br class=""><br class="">def ext_thread_before : Extension<"'__thread' before '%0'">;<br class="">def ext_keyword_as_ident : ExtWarn<<br class="">@@ -554,6 +558,9 @@ def ext_for_range_init_stmt : ExtWarn<<br class="">def warn_cxx17_compat_for_range_init_stmt : Warning<<br class=""> "range-based for loop initialization statements are incompatible with "<br class=""> "C++ standards before C++2a">, DefaultIgnore, InGroup<CXXPre2aCompat>;<br class="">+def warn_empty_init_statement : Warning<<br class="">+  "empty initialization statement of '%select{if|switch|range-based for}0' "<br class="">+  "has no effect">, InGroup<EmptyInitStatement>, DefaultIgnore;<br class=""><br class="">// C++ derived classes<br class="">def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;<br class=""><br class="">Modified: cfe/trunk/include/clang/Parse/Parser.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Parse/Parser.h (original)<br class="">+++ cfe/trunk/include/clang/Parse/Parser.h Tue Nov 20 10:59:05 2018<br class="">@@ -1888,6 +1888,7 @@ private:<br class=""> StmtResult ParseCompoundStatement(bool isStmtExpr,<br class="">                                   unsigned ScopeFlags);<br class=""> void ParseCompoundStatementLeadingPragmas();<br class="">+  bool ConsumeNullStmt(StmtVector &Stmts);<br class=""> StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);<br class=""> bool ParseParenExprOrCondition(StmtResult *InitStmt,<br class="">                                Sema::ConditionResult &CondResult,<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Nov 20 10:59:05 2018<br class="">@@ -1773,7 +1773,13 @@ Sema::ConditionResult Parser::ParseCXXCo<br class="">   //   if (; true);<br class="">   if (InitStmt && <a href="http://Tok.is" class="">Tok.is</a>(tok::semi)) {<br class="">     WarnOnInit();<br class="">-      SourceLocation SemiLoc = ConsumeToken();<br class="">+      SourceLocation SemiLoc = Tok.getLocation();<br class="">+      if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID()) {<br class="">+        Diag(SemiLoc, diag::warn_empty_init_statement)<br class="">+            << (CK == Sema::ConditionKind::Switch)<br class="">+            << FixItHint::CreateRemoval(SemiLoc);<br class="">+      }<br class="">+      ConsumeToken();<br class="">     *InitStmt = Actions.ActOnNullStmt(SemiLoc);<br class="">     return ParseCXXCondition(nullptr, Loc, CK);<br class="">   }<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseStmt.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=347339&r1=347338&r2=347339&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=347339&r1=347338&r2=347339&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Nov 20 10:59:05 2018<br class="">@@ -930,6 +930,34 @@ void Parser::ParseCompoundStatementLeadi<br class=""><br class="">}<br class=""><br class="">+/// Consume any extra semi-colons resulting in null statements,<br class="">+/// returning true if any tok::semi were consumed.<br class="">+bool Parser::ConsumeNullStmt(StmtVector &Stmts) {<br class="">+  if (!<a href="http://Tok.is" class="">Tok.is</a>(tok::semi))<br class="">+    return false;<br class="">+<br class="">+  SourceLocation StartLoc = Tok.getLocation();<br class="">+  SourceLocation EndLoc;<br class="">+<br class="">+  while (<a href="http://Tok.is" class="">Tok.is</a>(tok::semi) && !Tok.hasLeadingEmptyMacro() &&<br class="">+         Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {<br class="">+    EndLoc = Tok.getLocation();<br class="">+<br class="">+    // Don't just ConsumeToken() this tok::semi, do store it in AST.<br class="">+    StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any);<br class="">+    if (R.isUsable())<br class="">+      Stmts.push_back(R.get());<br class="">+  }<br class="">+<br class="">+  // Did not consume any extra semi.<br class="">+  if (EndLoc.isInvalid())<br class="">+    return false;<br class="">+<br class="">+  Diag(StartLoc, diag::warn_null_statement)<br class="">+      << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));<br class="">+  return true;<br class="">+}<br class="">+<br class="">/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the<br class="">/// ActOnCompoundStmt action.  This expects the '{' to be the current token, and<br class="">/// consume the '}' at the end of the block.  It does not manipulate the scope<br class="">@@ -992,6 +1020,9 @@ StmtResult Parser::ParseCompoundStatemen<br class="">     continue;<br class="">   }<br class=""><br class="">+    if (ConsumeNullStmt(Stmts))<br class="">+      continue;<br class="">+<br class="">   StmtResult R;<br class="">   if (Tok.isNot(tok::kw___extension__)) {<br class="">     R = ParseStatementOrDeclaration(Stmts, ACK_Any);<br class="">@@ -1588,10 +1619,15 @@ StmtResult Parser::ParseForStatement(Sou<br class=""> ParsedAttributesWithRange attrs(AttrFactory);<br class=""> MaybeParseCXX11Attributes(attrs);<br class=""><br class="">+  SourceLocation EmptyInitStmtSemiLoc;<br class="">+<br class=""> // Parse the first part of the for specifier.<br class=""> if (<a href="http://Tok.is" class="">Tok.is</a>(tok::semi)) {  // for (;<br class="">   ProhibitAttributes(attrs);<br class="">   // no first part, eat the ';'.<br class="">+    SourceLocation SemiLoc = Tok.getLocation();<br class="">+    if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())<br class="">+      EmptyInitStmtSemiLoc = SemiLoc;<br class="">   ConsumeToken();<br class=""> } else if (getLangOpts().CPlusPlus && <a href="http://Tok.is" class="">Tok.is</a>(tok::identifier) &&<br class="">            isForRangeIdentifier()) {<br class="">@@ -1723,6 +1759,11 @@ StmtResult Parser::ParseForStatement(Sou<br class="">                  : diag::ext_for_range_init_stmt)<br class="">             << (FirstPart.get() ? FirstPart.get()->getSourceRange()<br class="">                                 : SourceRange());<br class="">+          if (EmptyInitStmtSemiLoc.isValid()) {<br class="">+            Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)<br class="">+                << /*for-loop*/ 2<br class="">+                << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);<br class="">+          }<br class="">       }<br class="">     } else {<br class="">       ExprResult SecondExpr = ParseExpression();<br class=""><br class="">Added: cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp?rev=347339&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp?rev=347339&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp (added)<br class="">+++ cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt-in-init-statement.cpp Tue Nov 20 10:59:05 2018<br class="">@@ -0,0 +1,64 @@<br class="">+// RUN: %clang_cc1 -fsyntax-only -Wextra -std=c++2a -verify %s<br class="">+// RUN: %clang_cc1 -fsyntax-only -Wextra-semi-stmt -std=c++2a -verify %s<br class="">+// RUN: %clang_cc1 -fsyntax-only -Wempty-init-stmt -std=c++2a -verify %s<br class="">+// RUN: cp %s %t<br class="">+// RUN: %clang_cc1 -x c++ -Wempty-init-stmt -std=c++2a -fixit %t<br class="">+// RUN: %clang_cc1 -x c++ -Wempty-init-stmt -std=c++2a -Werror %t<br class="">+<br class="">+struct S {<br class="">+  int *begin();<br class="">+  int *end();<br class="">+};<br class="">+<br class="">+void naive(int x) {<br class="">+  if (; true) // expected-warning {{empty initialization statement of 'if' has no effect}}<br class="">+    ;<br class="">+<br class="">+  switch (; x) { // expected-warning {{empty initialization statement of 'switch' has no effect}}<br class="">+  }<br class="">+<br class="">+  for (; int y : S()) // expected-warning {{empty initialization statement of 'range-based for' has no effect}}<br class="">+    ;<br class="">+<br class="">+  for (;;) // OK<br class="">+    ;<br class="">+}<br class="">+<br class="">+#define NULLMACRO<br class="">+<br class="">+void with_null_macro(int x) {<br class="">+  if (NULLMACRO; true)<br class="">+    ;<br class="">+<br class="">+  switch (NULLMACRO; x) {<br class="">+  }<br class="">+<br class="">+  for (NULLMACRO; int y : S())<br class="">+    ;<br class="">+}<br class="">+<br class="">+#define SEMIMACRO ;<br class="">+<br class="">+void with_semi_macro(int x) {<br class="">+  if (SEMIMACRO true)<br class="">+    ;<br class="">+<br class="">+  switch (SEMIMACRO x) {<br class="">+  }<br class="">+<br class="">+  for (SEMIMACRO int y : S())<br class="">+    ;<br class="">+}<br class="">+<br class="">+#define PASSTHROUGHMACRO(x) x<br class="">+<br class="">+void with_passthrough_macro(int x) {<br class="">+  if (PASSTHROUGHMACRO(;) true)<br class="">+    ;<br class="">+<br class="">+  switch (PASSTHROUGHMACRO(;) x) {<br class="">+  }<br class="">+<br class="">+  for (PASSTHROUGHMACRO(;) int y : S())<br class="">+    ;<br class="">+}<br class=""><br class="">Added: cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp?rev=347339&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp?rev=347339&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp (added)<br class="">+++ cfe/trunk/test/Parser/extra-semi-resulting-in-nullstmt.cpp Tue Nov 20 10:59:05 2018<br class="">@@ -0,0 +1,96 @@<br class="">+// RUN: %clang_cc1 -fsyntax-only -Wextra-semi-stmt -verify %s<br class="">+// RUN: cp %s %t<br class="">+// RUN: %clang_cc1 -x c++ -Wextra-semi-stmt -fixit %t<br class="">+// RUN: %clang_cc1 -x c++ -Wextra-semi-stmt -Werror %t<br class="">+<br class="">+#define GOODMACRO(varname) int varname<br class="">+#define BETTERMACRO(varname) GOODMACRO(varname);<br class="">+#define NULLMACRO(varname)<br class="">+<br class="">+enum MyEnum {<br class="">+  E1,<br class="">+  E2<br class="">+};<br class="">+<br class="">+void test() {<br class="">+  ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+  ;<br class="">+<br class="">+  // This removal of extra semi also consumes all the comments.<br class="">+  // clang-format: off<br class="">+  ;;;<br class="">+  // clang-format: on<br class="">+<br class="">+  // clang-format: off<br class="">+  ;NULLMACRO(ZZ);<br class="">+  // clang-format: on<br class="">+<br class="">+  {}; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+<br class="">+  {<br class="">+    ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+  }<br class="">+<br class="">+  if (true) {<br class="">+    ; // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+  }<br class="">+<br class="">+  GOODMACRO(v0); // OK<br class="">+<br class="">+  GOODMACRO(v1;) // OK<br class="">+<br class="">+  BETTERMACRO(v2) // OK<br class="">+<br class="">+  BETTERMACRO(v3;) // Extra ';', but within macro expansion, so ignored.<br class="">+<br class="">+  BETTERMACRO(v4); // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+<br class="">+  BETTERMACRO(v5;); // expected-warning {{empty expression statement has no effect; remove unnecessary ';' to silence this warning}}<br class="">+<br class="">+  NULLMACRO(v6) // OK<br class="">+<br class="">+  NULLMACRO(v7); // OK. This could be either GOODMACRO() or BETTERMACRO() situation, so we can't know we can drop it.<br class="">+<br class="">+  if (true)<br class="">+    ; // OK<br class="">+<br class="">+  while (true)<br class="">+    ; // OK<br class="">+<br class="">+  do<br class="">+    ; // OK<br class="">+  while (true);<br class="">+<br class="">+  for (;;) // OK<br class="">+    ;      // OK<br class="">+<br class="">+  MyEnum my_enum;<br class="">+  switch (my_enum) {<br class="">+  case E1:<br class="">+    // stuff<br class="">+    break;<br class="">+  case E2:; // OK<br class="">+  }<br class="">+<br class="">+  for (;;) {<br class="">+    for (;;) {<br class="">+      goto contin_outer;<br class="">+    }<br class="">+  contin_outer:; // OK<br class="">+  }<br class="">+}<br class="">+<br class="">+;<br class="">+<br class="">+namespace NS {};<br class="">+<br class="">+void foo(int x) {<br class="">+  switch (x) {<br class="">+  case 0:<br class="">+    [[fallthrough]];<br class="">+  case 1:<br class="">+    return;<br class="">+  }<br class="">+}<br class="">+<br class="">+[[]];<br class=""><br class=""><br class="">_______________________________________________<br class="">cfe-commits mailing list<br class=""><a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits<br class=""></blockquote></blockquote></blockquote>_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></blockquote><br class="">_______________________________________________<br class="">cfe-commits mailing list<br class=""><a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</blockquote></blockquote></div></blockquote></div><br class=""></div></body></html>