On 7/23/17, Volker Reichelt <v.reich...@netcologne.de> wrote:
> Hi again,
>
> here is an updated patch for a new warning about redundant
> access-specifiers. It takes Dave's various comments into account.
>
> The main changes w.r.t. to the previous versions are:
>
> * The warning is now a two-level warning with a slightly shorter name:
>   -Waccess-specifiers=1, -Waccess-specifiers=2
>   with -Waccess-specifiers defaulting to -Waccess-specifiers=1.

Just a more generalized comment as a user, but I don't really like
this trend that new warning options are so often given numeric levels
these days. A warning option with different levels requires special
handling in configure scripts or Makefiles, which is harder than just
toggling different names (i.e. how things work without numeric
levels).

> * The warning now checks for 3 different scenarios, see testcase
>   Waccess-specifiers-2.C below:
>   A) Two consecutive access-specifiers, so that the first one
>      has no effect. (This is new.)
>   B) Two (non-consecutive) equal access-specifiers.
>      (That's what the original patch checked.)
>   C) An access-specifier that does not change the class-type's default.
>      (That's what I only suggested in the original patch.)
>   The first two tests are enabled in level 1, the last in level 2.

Instead of levels, I'd prefer A and B to be in an option like the
original -Wduplicate-access-specifiers, while putting C under a
separate name like -Wdefault-access-specifiers. This way they can be
toggled individually, so for example I can get just warning C without
also getting warnings A and B. Using numeric levels makes that
impossible. But that's just my personal preference for how to separate
them, so feel free to disregard me.

> * The warning is now in a separate function.
> * The fix-it hints now include the colon after the access-specifier.
> * There's a testcase for the fix-it hints.
>
> What's missing from Dave's comments are some examples for invoke.texi.
> I'll work on that once the warning made it into the trunk.
>
> The switch statement in cp_parser_maybe_warn_access_specifier is a little
> bit ugly. It would be nicer to emit the warnings directly next to the
> checks. But then I'd have to write the code for the fix-it hint 3 times.
> With C++11 I'd use a lambda for this, but with C++03 I hope the switch
> is OK.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu.
> OK for trunk?
>
> Regards,
> Volker
>
>
> 2017-07-22  Volker Reichelt  <v.reich...@netcologne.de>
>
>       * doc/invoke.texi (-Waccess-specifiers, -Waccess-specifiers=):
>       Document new warning options.
>
> Index: gcc/doc/invoke.texi
> ===================================================================
> --- gcc/doc/invoke.texi       (revision 250356)
> +++ gcc/doc/invoke.texi       (working copy)
> @@ -259,7 +259,8 @@
>  @xref{Warning Options,,Options to Request or Suppress Warnings}.
>  @gccoptlist{-fsyntax-only  -fmax-errors=@var{n}  -Wpedantic @gol
>  -pedantic-errors @gol
> --w  -Wextra  -Wall  -Waddress  -Waggregate-return  @gol
> +-w  -Wextra  -Wall  -Waccess-specifiers  -Waccess-specifiers=@var{n} @gol
> +-Waddress  -Waggregate-return  @gol
>  -Walloc-zero  -Walloc-size-larger-than=@var{n}
>  -Walloca  -Walloca-larger-than=@var{n} @gol
>  -Wno-aggressive-loop-optimizations  -Warray-bounds  -Warray-bounds=@var{n}
> @gol
> @@ -5254,6 +5255,13 @@
>  Warn about overriding virtual functions that are not marked with the
> override
>  keyword.
>
> +@item -Waccess-specifiers @r{(C++ and Objective-C++ only)}
> +@itemx -Waccess-specifiers=@var{n}
> +@opindex Wno-access-specifiers
> +@opindex Waccess-specifiers
> +Warn when an access-specifier is redundant because it was already given
> +before.
> +
>  @item -Walloc-zero
>  @opindex Wno-alloc-zero
>  @opindex Walloc-zero
> ===================================================================
>
>
> 2017-07-22  Volker Reichelt  <v.reich...@netcologne.de>
>
>       * c.opt (Waccess-specifiers=): New C++ warning flag.
>       (Waccess-specifiers): New alias.
>
> Index: gcc/c-family/c.opt
> ===================================================================
> --- gcc/c-family/c.opt        (revision 250443)
> +++ gcc/c-family/c.opt        (working copy)
> @@ -476,6 +476,14 @@
>  C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
>  Warn about compile-time integer division by zero.
>
> +Waccess-specifiers
> +C++ ObjC++ Warning Alias(Waccess-specifiers=, 1, 0)
> +Warn about redundant access-specifiers.
> +
> +Waccess-specifiers=
> +C++ ObjC++ Var(warn_access_specifiers) Warning Joined RejectNegative
> UInteger
> +Warn about redundant access-specifiers.
> +
>  Wduplicated-branches
>  C ObjC C++ ObjC++ Var(warn_duplicated_branches) Init(0) Warning
>  Warn about duplicated branches in if-else statements.
> ===================================================================
>
>
> 2017-07-22  Volker Reichelt  <v.reich...@netcologne.de>
>
>       * cp-tree.h (struct saved_scope): New access_specifier_loc variable.
>       (current_access_specifier_loc): New macro.
>       * class.c (struct class_stack_node): New access_loc variable.
>       (pushclass): Push current_access_specifier_loc.  Set new
>       initial value.
>       (popclass): Pop current_access_specifier_loc.
>       * parser.c (cp_parser_maybe_warn_access_specifier): New function
>       to warn about duplicated access-specifiers.
>       (cp_parser_member_specification_opt): Call it.  Set
>       current_access_specifier_loc.
>
> Index: gcc/cp/class.c
> ===================================================================
> --- gcc/cp/class.c    (revision 250443)
> +++ gcc/cp/class.c    (working copy)
> @@ -60,6 +60,7 @@
>    /* The access specifier pending for new declarations in the scope of
>       this class.  */
>    tree access;
> +  location_t access_loc;
>
>    /* If were defining TYPE, the names used in this class.  */
>    splay_tree names_used;
> @@ -7724,6 +7725,7 @@
>    csn->name = current_class_name;
>    csn->type = current_class_type;
>    csn->access = current_access_specifier;
> +  csn->access_loc = current_access_specifier_loc;
>    csn->names_used = 0;
>    csn->hidden = 0;
>    current_class_depth++;
> @@ -7739,6 +7741,7 @@
>    current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)
>                             ? access_private_node
>                             : access_public_node);
> +  current_access_specifier_loc = UNKNOWN_LOCATION;
>
>    if (previous_class_level
>        && type != previous_class_level->this_entity
> @@ -7778,6 +7781,7 @@
>    current_class_name = current_class_stack[current_class_depth].name;
>    current_class_type = current_class_stack[current_class_depth].type;
>    current_access_specifier =
> current_class_stack[current_class_depth].access;
> +  current_access_specifier_loc =
> current_class_stack[current_class_depth].access_loc;
>    if (current_class_stack[current_class_depth].names_used)
>      splay_tree_delete
> (current_class_stack[current_class_depth].names_used);
>  }
> Index: gcc/cp/cp-tree.h
> ===================================================================
> --- gcc/cp/cp-tree.h  (revision 250443)
> +++ gcc/cp/cp-tree.h  (working copy)
> @@ -1531,6 +1531,7 @@
>    tree class_name;
>    tree class_type;
>    tree access_specifier;
> +  source_location access_specifier_loc;
>    tree function_decl;
>    vec<tree, va_gc> *lang_base;
>    tree lang_name;
> @@ -1592,6 +1593,7 @@
>     class, or union).  */
>
>  #define current_access_specifier scope_chain->access_specifier
> +#define current_access_specifier_loc scope_chain->access_specifier_loc
>
>  /* Pointer to the top of the language name stack.  */
>
> Index: gcc/cp/parser.c
> ===================================================================
> --- gcc/cp/parser.c   (revision 250453)
> +++ gcc/cp/parser.c   (working copy)
> @@ -23082,6 +23082,69 @@
>    return;
>  }
>
> +/* Warn about redundant access-specifiers.  */
> +
> +static void
> +cp_parser_maybe_warn_access_specifier (cp_parser* parser)
> +{
> +  cp_token *token = cp_lexer_peek_token (parser->lexer);
> +  cp_token *colon_token = cp_lexer_peek_nth_token (parser->lexer, 2);
> +  cp_token *next_token = cp_lexer_peek_nth_token (parser->lexer, 3);
> +
> +  int message_id = 0;
> +
> +  /* Check for two consecutive access-specifiers.  */
> +  if (colon_token->type == CPP_COLON && (next_token->keyword == RID_PUBLIC
> +                                      || next_token->keyword == RID_PROTECTED
> +                                      || next_token->keyword == RID_PRIVATE))
> +    message_id = 1;
> +  /* Check for access-specifiers not changing access.  */
> +  else if (current_access_specifier == token->u.value)
> +    {
> +      if (current_access_specifier_loc != UNKNOWN_LOCATION)
> +        message_id = 2;
> +      else if (warn_access_specifiers > 1)
> +        message_id = 3;
> +    }
> +
> +  if (!message_id)
> +    return;
> +
> +  /* Emit warning.  */
> +  gcc_rich_location richloc (token->location);
> +  richloc.add_fixit_remove ();
> +  if (colon_token->type == CPP_COLON)
> +    richloc.add_fixit_remove (colon_token->location);
> +
> +  switch (message_id)
> +    {
> +    case 1:
> +      warning_at_rich_loc (&richloc, OPT_Waccess_specifiers_,
> +                        "redundant %qE access-specifier",
> +                        token->u.value);
> +      inform (next_token->location, "directly followed by another one
> here");
> +      break;
> +
> +    case 2:
> +      warning_at_rich_loc (&richloc, OPT_Waccess_specifiers_,
> +                        "duplicate %qE access-specifier",
> +                        token->u.value);
> +      inform (current_access_specifier_loc,
> +           "same access-specifier was previously given here");
> +      break;
> +
> +    case 3:
> +      warning_at_rich_loc (&richloc, OPT_Waccess_specifiers_,
> +                        "access-specifier %qE is redundant within %qs",
> +                        token->u.value,
> +                        class_key_or_enum_as_string (current_class_type));
> +      break;
> +
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
>  /* Parse an (optional) member-specification.
>
>     member-specification:
> @@ -23111,10 +23174,15 @@
>       case RID_PUBLIC:
>       case RID_PROTECTED:
>       case RID_PRIVATE:
> +       /* Warn about redundant access-specifiers.  */
> +       if (warn_access_specifiers)
> +         cp_parser_maybe_warn_access_specifier (parser);
> +
>         /* Consume the access-specifier.  */
>         cp_lexer_consume_token (parser->lexer);
>         /* 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-22  Volker Reichelt  <v.reich...@netcologne.de>
>
>       * g++.dg/warn/Waccess-specifiers-1.C: New test.
>       * g++.dg/warn/Waccess-specifiers-2.C: New test.
>
> Index: gcc/testsuite/g++.dg/warn/Waccess-specifiers-1.C
> ===================================================================
> --- gcc/testsuite/g++.dg/warn/Waccess-specifiers-1.C  2017-07-22
> +++ gcc/testsuite/g++.dg/warn/Waccess-specifiers-1.C  2017-07-22
> @@ -0,0 +1,38 @@
> +// { dg-options "-Waccess-specifiers" }
> +
> +struct A
> +{
> +    int i;
> +  public:         // { dg-message "previously" }
> +    int j;
> +  public:         // { dg-warning "duplicate 'public' access-specifier" }
> +    int k;
> +  protected:      // { dg-message "previously" }
> +
> +    class B
> +    {
> +      private:    // { dg-message "previously" }
> +        int m;
> +      private:    // { dg-warning "duplicate 'private' access-specifier" }
> +        int n;
> +      protected:  // { dg-warning "redundant 'protected' access-specifier"
> }
> +      public:     // { dg-message "directly followed" }
> +    };
> +
> +  protected:      // { dg-warning "duplicate 'protected' access-specifier"
> }
> +    void a();
> +  public:
> +    void b();
> +  private:        // { dg-message "previously" }
> +    void c();
> +  private:        // { dg-warning "duplicate 'private' access-specifier" }
> +    void d();
> +  public:
> +    void e();
> +  protected:      // { dg-message "previously" }
> +    void f();
> +  protected:      // { dg-warning "duplicate 'protected' access-specifier"
> }
> +                  // { dg-message "previously" "" { target *-*-* } .-1 }
> +    void g();
> +  protected:      // { dg-warning "duplicate 'protected' access-specifier"
> }
> +};
> Index: gcc/testsuite/g++.dg/warn/Waccess-specifiers-2.C
> ===================================================================
> --- gcc/testsuite/g++.dg/warn/Waccess-specifiers-2.C  2017-07-22
> +++ gcc/testsuite/g++.dg/warn/Waccess-specifiers-2.C  2017-07-22
> @@ -0,0 +1,44 @@
> +// { dg-options "-Waccess-specifiers=2 -fdiagnostics-show-caret" }
> +
> +class A
> +{
> +  public:  /* { dg-warning "access-specifier" }
> +  { dg-begin-multiline-output "" }
> +   public:
> +   ^~~~~~
> +   -------
> +  { dg-end-multiline-output "" } */
> +
> +  private:  /* { dg-message "directly followed" }
> +  { dg-begin-multiline-output "" }
> +   private:
> +   ^~~~~~~
> +  { dg-end-multiline-output "" } */
> +};
> +
> +struct B
> +{
> +  protected:  /* { dg-message "previously" }
> +  { dg-begin-multiline-output "" }
> +   protected:
> +   ^~~~~~~~~
> +  { dg-end-multiline-output "" } */
> +    B();
> +
> +  protected  :  /* { dg-warning "access-specifier" }
> +  { dg-begin-multiline-output "" }
> +   protected  :
> +   ^~~~~~~~~
> +   ---------  -
> +  { dg-end-multiline-output "" } */
> +};
> +
> +class C
> +{
> +  private:  /* { dg-warning "redundant within" }
> +  { dg-begin-multiline-output "" }
> +   private:
> +   ^~~~~~~
> +   --------
> +  { dg-end-multiline-output "" } */
> +};
>
>

Reply via email to