[PATCH] New C++ warning option '-Wduplicated-access-specifiers'

David Malcolm dmalcolm@redhat.com
Sat Jul 22 00:56:00 GMT 2017


On Fri, 2017-07-21 at 19:58 +0200, Volker Reichelt wrote:
> On 21 Jul, David Malcolm wrote:
> > On Thu, 2017-07-20 at 18:35 +0200, Volker Reichelt wrote:
> >> Hi,
> >> 
> >> the following patch introduces a new C++ warning option
> >> -Wduplicated-access-specifiers that warns about redundant
> >> access-specifiers in classes, e.g.
> >> 
> >>   class B
> >>   {
> >>     public:
> >>       B();
> >> 
> >>     private:
> >>       void foo();
> >>     private:
> >>       int i;
> >>   };
> >> 
> >> test.cc:8:5: warning: duplicate 'private' access-specifier [
> >> -Wduplicated-access-specifiers]
> >>      private:
> >>      ^~~~~~~
> >>      -------
> >> test.cc:6:5: note: access-specifier was previously given here
> >>      private:
> >>      ^~~~~~~
> > 
> > Thanks for working on this.
> > 
> > I'm not able to formally review, but you did CC me; various
> comments below throughout.
> > 
> >> The test is implemented by tracking the location of the last
> >> access-specifier together with the access-specifier itself.
> >> The location serves two purposes: the obvious one is to be able to
> >> print the location in the note that comes with the warning.
> >> The second purpose is to be able to distinguish an access
> -specifier
> >> given by the user from the default of the class type (i.e. public
> for
> >> 'struct' and private for 'class') where the location is set to
> >> UNKNOWN_LOCATION. The warning is only issued if the user gives the
> >> access-specifier twice, i.e. if the previous location is not
> >> UNKNOWN_LOCATION.
> > 
> > Presumably given
> > 
> > struct foo
> > {
> > public:
> >   /* ... *
> > };
> > 
> > we could issue something like:
> > 
> >   warning: access-specifier 'public' is redundant within 'struct'
> > 
> > for the first; similarly for:
> > 
> > class bar
> > {
> > private:
> > };
> > 
> > we could issue:
> > 
> >   warning: access-specifier 'private' is redundant within 'class'
> > 
> > 
> >> One could actually make this a two-level warning so that on the
> >> higher level also the default class-type settings are taken into
> >> account. Would that be helpful? I could prepare a second patch for
> >> that.
> > 
> > I'm not sure how best to structure it.
> > 
> > FWIW, when I first saw the patch, I wasn't a big fan of the
> warning, as I like to use access-specifiers to break up the kinds of
> entities within a class.
> > 
> > For example, our coding guidelines 
> >   https://gcc.gnu.org/codingconventions.html#Class_Form
> > recommend:
> > 
> > "first define all public types,
> > then define all non-public types,
> > then declare all public constructors,
> > ...
> > then declare all non-public member functions, and
> > then declare all non-public member variables."
> > 
> > I find it's useful to put a redundant "private:" between the last
> two,
> > e.g.:
> > 
> > class baz
> > {
> >  public:
> >   ...
> > 
> >  private:
> >   void some_private_member ();
> > 
> >  private:
> >   int m_some_field;
> > };
> > 
> > to provide a subdivision between the private member functions and
> the
> > private data fields.
> 
> That's what also can be seen in our libstdc++ to some extent.
> The other half of the warnings indicate redundant access-specifiers.
> 
> It's up to the user to keep those duplicate access-specifiers as
> subdividers or to use something else (like comments) to do that
> and to switch on the warning for her/his code.
> Because the subdivider usage seems to be relatively common,
> I don't want to enable the warning by -Wall or -Wextra.
> 
> > This might be a violation of our guidelines (though if so, I'm not
> sure
> > it's explicitly stated), but I find it useful, and the patch would
> warn
> > about it.
> > 
> > Having said that, looking at e.g. the "jit" subdir, I see lots of
> > places where the warning would fire.  In some of these, the code
> has a
> > bit of a "smell", so maybe I like the warning after all... in that
> it
> > can be good for a new warning to draw attention to code that might
> need
> > work.
> > 
> > Sorry that this is rambling; comments on the patch inline below.
> > 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu.
> >> OK for trunk?
> >> 
> >> Btw, there are about 50 places in our libstdc++ headers where this
> >> warning triggers. I'll come up with a patch for this later.
> >> 
> >> Regards,
> >> Volker
> >> 
> >> 
> >> 2017-07-20  Volker Reichelt  <v.reichelt@netcologne.de>
> >> 
> >>         * doc/invoke.texi (-Wduplicated-access-specifiers):
> Document
> >> new
> >>         warning option.
> >> 
> >> Index: gcc/doc/invoke.texi
> >>
> ===================================================================
> >> --- gcc/doc/invoke.texi (revision 250356)
> >> +++ gcc/doc/invoke.texi (working copy)
> >> @@ -275,7 +275,7 @@
> >>  -Wdisabled-optimization @gol
> >>  -Wno-discarded-qualifiers  -Wno-discarded-array-qualifiers @gol
> >>  -Wno-div-by-zero  -Wdouble-promotion @gol
> >> --Wduplicated-branches  -Wduplicated-cond @gol
> >> +-Wduplicated-access-specifiers  -Wduplicated-branches  
> -Wduplicated
> >> -cond @gol
> >>  -Wempty-body  -Wenum-compare  -Wno-endif-labels  -Wexpansion-to
> >> -defined @gol
> >>  -Werror  -Werror=*  -Wextra-semi  -Wfatal-errors @gol
> >>  -Wfloat-equal  -Wformat  -Wformat=2 @gol
> >> @@ -5388,6 +5388,12 @@
> >>  
> >>  This warning is enabled by @option{-Wall}.
> >>  
> >> +@item -Wduplicated-access-specifiers
> >> +@opindex Wno-duplicated-access-specifiers
> >> +@opindex Wduplicated-access-specifiers
> >> +Warn when an access-specifier is redundant because it was already
> >> given
> >> +before.
> > 
> > Presumably this should be marked as C++-specific.
> 
> Oops, good point!
> 
> > I think it's best to give an example for any warning, though we
> don't
> > do that currently.
> 
> Sounds reasonable. Especially because 'access-specifier' is a very
> technical term that is not linked to 'public/protected/private'
> by everybody.
> 
> [...snip...]
> 
> >> Index: gcc/cp/parser.c
> >>
> ===================================================================
> >> --- gcc/cp/parser.c     (revision 250356)
> >> +++ gcc/cp/parser.c     (working copy)
> >> @@ -23113,8 +23113,24 @@
> >>         case RID_PRIVATE:
> >>           /* Consume the access-specifier.  */
> >>           cp_lexer_consume_token (parser->lexer);
> >> +
> >> +         /* Warn if the same access-specifier has been given
> >> already.  */
> >> +         if (warn_duplicated_access
> >> +             && current_access_specifier == token->u.value
> >> +             && current_access_specifier_loc != UNKNOWN_LOCATION)
> >> +           {
> >> +             gcc_rich_location richloc (token->location);
> >> +             richloc.add_fixit_remove ();
> > 
> > If the fix-it hint is to work, it presumably needs to remove two
> > tokens: both the "private" (or whatever), *and* the colon.
> 
> I did not do this because I did not want to reorder the code.
> OTOH just moving the cp_parser_require line a little bit up
> should not be a big deal for better diagnostics.
> 
> > You can probably do this via:
> > 
> >   richloc.add_fixit_remove ();  /* for the primary location */
> >   richloc.add_fixit_remove (colon_loc);  /* for the colon */
> > 
> > and the rich_location ought to do the right thing, consolidating
> the removals if they are adjacent (and coping with e.g. a comment
> between them if they're not).
> >
> >> +             warning_at_rich_loc (&richloc,
> >> OPT_Wduplicated_access_specifiers,
> >> +                                  "duplicate %qE access
> -specifier",
> >> +                                  token->u.value);
> >> +             inform (current_access_specifier_loc,
> >> +                     "access-specifier was previously given
> here");
> >> +           }
> >> +
> >>           /* Remember which access-specifier is active.  */
> >>           current_access_specifier = token->u.value;
> >> +         current_access_specifier_loc = token->location;
> >>           /* Look for the `:'.  */
> >>           cp_parser_require (parser, CPP_COLON, RT_COLON);
> >>           break;
> >>
> ===================================================================
> >> 
> >> 
> >> 2017-07-20  Volker Reichelt  <v.reichelt@netcologne.de>
> >> 
> >>         * g++.dg/warn/Wduplicated-access-specifiers-1.C: New test.
> 
> {...snip...]
> 
> > If you're going to implement a fix-it hint for this, there should
> be a
> > test case that tests it (probably as a separate file, e.g.
> Wduplicated
> > -access-specifiers-2.C, to allow for the extra option -
> -fdiagnostics
> > -show-caret, covering just one instance of the diagnostic firing,
> for
> > simplicity).
> 
> I actually did try that, but dejagnu somehow gets confused.
> To me it looks like the reason for this is that both multi-line
> messages
> are so similar. I'll give it a second try, though.

I'm not sure what you mean by "both" multi-line messages; shouldn't
there be just one multi-line message for the fix-it hint.

Isn't this like e.g. g++.dg/cpp0x/auto1.C ?  (an example of a testcase
that verifies a deletion fix-it hint)

Dave



More information about the Gcc-patches mailing list