This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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:
     ^~~~~~~

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.

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.

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.
+
 @item -Wduplicated-branches
 @opindex Wno-duplicated-branches
 @opindex Wduplicated-branches
===================================================================


2017-07-20  Volker Reichelt  <v.reichelt@netcologne.de>

	* c.opt (Wduplicated-access-specifiers): New C++ warning flag.

Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 250356)
+++ gcc/c-family/c.opt	(working copy)
@@ -476,6 +476,10 @@
 C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
 Warn about compile-time integer division by zero.
 
+Wduplicated-access-specifiers
+C++ ObjC++ Var(warn_duplicated_access) Warning
+Warn about duplicated 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-20  Volker Reichelt  <v.reichelt@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_member_specification_opt): Warn about
	duplicated access-specifier.  Set current_access_specifier_loc.

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 250356)
+++ 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/class.c
===================================================================
--- gcc/cp/class.c	(revision 250356)
+++ 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;
@@ -7723,6 +7724,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++;
@@ -7738,6 +7740,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
@@ -7777,6 +7780,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/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 ();
+	      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.

Index: gcc/testsuite/g++.dg/warn/Wduplicated-access-specifiers-1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wduplicated-access-specifiers-1.C	2017-07-20
+++ gcc/testsuite/g++.dg/warn/Wduplicated-access-specifiers-1.C	2017-07-20
@@ -0,0 +1,35 @@
+// { dg-options "-Wduplicated-access-specifiers" }
+
+struct A
+{
+    int i;
+  public:       // { dg-message "previously" }
+    int j;
+  public:       // { dg-warning "access-specifier" }
+    int k;
+  protected:    // { dg-message "previously" }
+
+    class B
+    {
+      private:  // { dg-message "previously" }
+      private:  // { dg-warning "access-specifier" }
+      public:
+    };
+
+  protected:    // { dg-warning "access-specifier" }
+    void a();
+  public:
+    void b();
+  private:      // { dg-message "previously" }
+    void c();
+  private:      // { dg-warning "access-specifier" }
+    void d();
+  public:
+    void e();
+  protected:    // { dg-message "previously" }
+    void f();
+  protected:    // { dg-warning "access-specifier" }
+                // { dg-message "previously" "" { target *-*-* } .-1 }
+    void g();
+  protected:    // { dg-warning "access-specifier" }
+};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]