On 7 Apr, David Malcolm wrote: > On Fri, 2017-04-07 at 21:55 +0200, Volker Reichelt wrote: >> Hi, >> >> with the following patch I suggest to add a diagnostic for extra >> semicolons after in-class member function definitions: >> >> struct A >> { >> A() {}; >> void foo() {}; >> friend void bar() {}; >> }; >> >> Although they are allowed in the C++ standard, people (including me) >> often like to get rid of them for stylistic/consistency reasons. >> In fact clang has a warning -Wextra-semi for this. >> >> Also in GCC (almost exactly 10 years ago) there was a patch >> https://gcc.gnu.org/ml/gcc-cvs/2007-03/msg00841.html >> to issue a pedwarn (which had to be reverted as GCC would reject >> valid >> code because of the pedwarn). >> >> Instead of using pewarn the patch below adds a new warning (named >> like >> clang's) to warn about these redundant semicolons. >> Btw, clang's warning message "extra ';' after member function >> definition" >> is slightly incorrect because it is also emitted for friend functions >> which are not member-functions. That's why I suggest a different >> wording: >> >> Wextra-semi.C:3:9: warning: extra ';' after in-class function >> definition [-Wextra-semi] >> A() {}; >> ^ >> Wextra-semi.C:4:16: warning: extra ';' after in-class function >> definition [-Wextra-semi] >> void foo() {}; >> ^ >> Wextra-semi.C:5:23: warning: extra ';' after in-class function >> definition [-Wextra-semi] >> friend void bar() {}; >> ^ >> >> Bootstrapped and regtested on x86_64-pc-linux-gnu. >> >> OK for stage 1, once GCC 7 has branched? >> Regards, >> Volker >> >> >> 2017-04-07 Volker Reichelt <v.reich...@netcologne.de> >> >> * c.opt (Wextra-semi): New C++ warning flag. >> >> Index: gcc/c-family/c.opt >> =================================================================== >> --- gcc/c-family/c.opt (revision 246752) >> +++ gcc/c-family/c.opt (working copy) >> @@ -504,6 +504,10 @@ >> C ObjC C++ ObjC++ Warning >> ; in common.opt >> >> +Wextra-semi >> +C++ Var(warn_extra_semi) Warning >> +Warn about semicolon after in-class function definition. >> + >> Wfloat-conversion >> C ObjC C++ ObjC++ Var(warn_float_conversion) Warning LangEnabledBy(C >> ObjC C++ ObjC++,Wconversion) >> Warn for implicit type conversions that cause loss of floating point >> precision. >> >> 2017-04-07 Volker Reichelt <v.reich...@netcologne.de> >> >> * parser.c (cp_parser_member_declaration): Add warning for >> extra semicolon after in-class function definition. >> >> Index: gcc/cp/parser.c >> =================================================================== >> --- gcc/cp/parser.c (revision 246752) >> +++ gcc/cp/parser.c (working copy) >> @@ -23386,7 +23386,11 @@ >> token = cp_lexer_peek_token (parser->lexer); >> /* If the next token is a semicolon, consume it. >> */ >> if (token->type == CPP_SEMICOLON) >> - cp_lexer_consume_token (parser->lexer); >> + { >> + cp_lexer_consume_token (parser->lexer); >> + warning (OPT_Wextra_semi, "extra %<;%> " >> + "after in-class function definition"); >> + } > > Thanks for posting this. > > I'm not a C++ maintainer, but I like the idea (though the patch is > missing at least a doc/invoke.texi change).
You're right. I had the nagging feeling that I forgot something. I added a respective section to doc/invoke.texi after -Wempty-body and -Wenum-compare. > A small improvement to this would be to emit a deletion fix-it hint > about the redundant token (so that IDEs have a change of fixing it > easily). > > This could be done something like this: > > location_t semicolon_loc > = cp_lexer_consume_token (parser->lexer)->location; > gcc_rich_location richloc (semicolon_loc); > richloc.add_fixit_remove (); > warning_at_richloc (&richloc, OPT_Wextra_semi, > "extra %<;%> after in-class function > definition"); > That's a nice suggestion. I modified the patch accordingly. >> goto out; >> } >> else >> >> 2017-04-07 Volker Reichelt <v.reich...@netcologne.de> >> >> * g++.dg/warn/Wextra-semi.C: New test. >> >> Index: gcc/testsuite/g++.dg/warn/Wextra-semi.C >> =================================================================== >> --- gcc/testsuite/g++.dg/warn/Wextra-semi.C 2017-04-07 >> +++ gcc/testsuite/g++.dg/warn/Wextra-semi.C 2017-04-07 >> @@ -0,0 +1,8 @@ >> +// { dg-options "-Wextra-semi" } >> + >> +struct A >> +{ >> + A() {}; // { dg-warning "after in-class function >> definition" } >> + void foo() {}; // { dg-warning "after in-class function >> definition" } >> + friend void bar() {}; // { dg-warning "after in-class >> function definition" } >> +}; >> > > If you implement the fix-it idea, then you can add > -fdiagnostics-show-caret to the dg-options, and use something like: > > /* { dg-begin-multiline-output "" } > A() {}; > ^ > - > { dg-end-multiline-output "" } */ > > to express the expected output (copied and pasted from GCC's output). > You should omit the commented parts of the lines if you do (otherwise > DejaGnu gets very confused due to them containing dg- directives). Even without the fix-it, the multiline check would make sense for the position of the caret, so I followed your suggestion. > Hope this is constructive > Dave Thanks a lot for your very helpful comments, Dave! So here's an updated version of the patch, again bootstrapped and regtested on x86_64-pc-linux-gnu. Right now, the patch enables the warning only for C++. Would it make sense to enable it also for ObjC++? OK for stage 1 (with or without ObjC++ support), once GCC 7 has branched? Regards, Volker 2017-04-09 Volker Reichelt <v.reich...@netcologne.de> * c.opt (Wextra-semi): New C++ warning flag. Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 246752) +++ gcc/c-family/c.opt (working copy) @@ -504,6 +504,10 @@ C ObjC C++ ObjC++ Warning ; in common.opt +Wextra-semi +C++ Var(warn_extra_semi) Warning +Warn about semicolon after in-class function definition. + Wfloat-conversion C ObjC C++ ObjC++ Var(warn_float_conversion) Warning LangEnabledBy(C ObjC C++ ObjC++,Wconversion) Warn for implicit type conversions that cause loss of floating point precision. 2017-04-09 Volker Reichelt <v.reich...@netcologne.de> * doc/invoke.texi (-Wextra-semi): Document new warning option. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 246752) +++ gcc/doc/invoke.texi (working copy) @@ -274,7 +274,8 @@ -Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol -Wno-div-by-zero -Wdouble-promotion -Wduplicated-cond @gol -Wempty-body -Wenum-compare -Wno-endif-labels -Wexpansion-to-defined @gol --Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol +-Werror -Werror=* -Wextra-semi -Wfatal-errors @gol +-Wfloat-equal -Wformat -Wformat=2 @gol -Wno-format-contains-nul -Wno-format-extra-args @gol -Wformat-nonliteral -Wformat-overflow=@var{n} @gol -Wformat-security -Wformat-signedness -Wformat-truncation=@var{n} @gol @@ -5960,6 +5961,11 @@ diagnosed and the warning is enabled by default. In C this warning is enabled by @option{-Wall}. +@item -Wextra-semi @r{(C++ only)} +@opindex Wextra-semi +@opindex Wno-extra-semi +Warn about redundant semicolon after in-class function definition. + @item -Wjump-misses-init @r{(C, Objective-C only)} @opindex Wjump-misses-init @opindex Wno-jump-misses-init 2017-04-09 Volker Reichelt <v.reich...@netcologne.de> * parser.c (cp_parser_member_declaration): Add warning with fixit information for extra semicolon after in-class function definition. Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 246752) +++ gcc/cp/parser.c (working copy) @@ -23386,7 +23386,15 @@ token = cp_lexer_peek_token (parser->lexer); /* If the next token is a semicolon, consume it. */ if (token->type == CPP_SEMICOLON) - cp_lexer_consume_token (parser->lexer); + { + location_t semicolon_loc + = cp_lexer_consume_token (parser->lexer)->location; + gcc_rich_location richloc (semicolon_loc); + richloc.add_fixit_remove (); + warning_at_rich_loc (&richloc, OPT_Wextra_semi, + "extra %<;%> after in-class " + "function definition"); + } goto out; } else 2017-04-09 Volker Reichelt <v.reich...@netcologne.de> * g++.dg/warn/Wextra-semi.C: New test. Index: gcc/testsuite/g++.dg/warn/Wextra-semi.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wextra-semi.C 2017-04-09 +++ gcc/testsuite/g++.dg/warn/Wextra-semi.C 2017-04-09 @@ -0,0 +1,25 @@ +// { dg-options "-Wextra-semi -fdiagnostics-show-caret" } + +struct A +{ + A() {}; /* { dg-warning "after in-class function definition" } + { dg-begin-multiline-output "" } + A() {}; + ^ + - + { dg-end-multiline-output "" } */ + + void foo() {}; /* { dg-warning "after in-class function definition" } + { dg-begin-multiline-output "" } + void foo() {}; + ^ + - + { dg-end-multiline-output "" } */ + + friend void bar() {}; /* { dg-warning "after in-class function definition" } + { dg-begin-multiline-output "" } + friend void bar() {}; + ^ + - + { dg-end-multiline-output "" } */ +}; ===================================================================