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 2/2] C++: show private field accessor hints with -g and optimization (PR c++/84994)


PR c++/84894 reports that the fix-it hints suggesting accessor calls for
private fields doesn't work with -g for -O1 and above.

The issue is that field_accessor_p requires DECL_SAVED_TREE (fn) to be
a RETURN_EXPR, but the former is a STATEMENT_LIST, created in
start_preparsed_function here:

15060	  /* Start the statement-tree, start the tree now.  */
15061	  DECL_SAVED_TREE (decl1) = push_stmt_list ();

This works for -O0 and without -g since cp/decl.c: finish_function
modifies it here:

15636	  /* If we're saving up tree structure, tie off the function now.  */
15637	  DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));

which strips away the stmt list, giving the RETURN_EXPR, but for -g with
-O1 and above, the STATEMENT_LIST is preserved.

This patch fixes the issue by introducing a new function:
  get_any_single_nondebug_stmt_in_list
to extract the single non-debug stmt from a STATEMENT_LIST, if there
is one, using it within field_accessor_p.

It moves the existing testcases to the g++.dg/torture subdirectory, so
that they are run for a variety of debug and optimization combinations.

Successfully bootstrapped and regression-tested on x86_64-pc-linux-gnu.

OK for trunk?  (not technically a regression, but affects a new feature)

gcc/c-family/ChangeLog:
	PR c++/84994
	* c-common.h (get_any_single_nondebug_stmt_in_list): New decl.
	* c-semantics.c (get_any_single_nondebug_stmt_in_list): New function.

gcc/cp/ChangeLog:
	PR c++/84994
	* search.c (field_accessor_p): Call
	get_any_single_nondebug_stmt_in_list on DECL_SAVED_TREE (fn).

gcc/testsuite/ChangeLog:
	* g++.dg/other/accessor-fixits-1.C: Move to...
	* g++.dg/torture/accessor-fixits-1.C: ...here.
	* g++.dg/other/accessor-fixits-2.C: Move to...
	* g++.dg/torture/accessor-fixits-2.C: ...here.
	* g++.dg/other/accessor-fixits-3.C: Move to...
	* g++.dg/torture/accessor-fixits-3.C: ...here.
	* g++.dg/other/accessor-fixits-4.C: Move to...
	* g++.dg/torture/accessor-fixits-4.C: ...here.
	* g++.dg/other/accessor-fixits-5.C: Move to...
	* g++.dg/torture/accessor-fixits-5.C: ...here.
	* g++.dg/torture/accessor-fixits-6.C: New testcase.
	* g++.dg/torture/accessor-fixits-7.C: New testcase.
	* g++.dg/torture/accessor-fixits-8.C: New testcase.
---
 gcc/c-family/c-common.h                          |   1 +
 gcc/c-family/c-semantics.c                       |  34 ++++
 gcc/cp/search.c                                  |   5 +
 gcc/testsuite/g++.dg/other/accessor-fixits-1.C   | 222 -----------------------
 gcc/testsuite/g++.dg/other/accessor-fixits-2.C   | 104 -----------
 gcc/testsuite/g++.dg/other/accessor-fixits-3.C   |  15 --
 gcc/testsuite/g++.dg/other/accessor-fixits-4.C   |  48 -----
 gcc/testsuite/g++.dg/other/accessor-fixits-5.C   |  33 ----
 gcc/testsuite/g++.dg/torture/accessor-fixits-1.C | 222 +++++++++++++++++++++++
 gcc/testsuite/g++.dg/torture/accessor-fixits-2.C | 104 +++++++++++
 gcc/testsuite/g++.dg/torture/accessor-fixits-3.C |  15 ++
 gcc/testsuite/g++.dg/torture/accessor-fixits-4.C |  48 +++++
 gcc/testsuite/g++.dg/torture/accessor-fixits-5.C |  33 ++++
 gcc/testsuite/g++.dg/torture/accessor-fixits-6.C |  22 +++
 gcc/testsuite/g++.dg/torture/accessor-fixits-7.C |  22 +++
 gcc/testsuite/g++.dg/torture/accessor-fixits-8.C |  29 +++
 16 files changed, 535 insertions(+), 422 deletions(-)
 delete mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-1.C
 delete mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-2.C
 delete mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-3.C
 delete mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-4.C
 delete mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-5.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-1.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-2.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-3.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-4.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-5.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-6.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-7.C
 create mode 100644 gcc/testsuite/g++.dg/torture/accessor-fixits-8.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 95bb0fd..67d0ed2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -581,6 +581,7 @@ extern tree push_stmt_list (void);
 extern tree pop_stmt_list (tree);
 extern tree add_stmt (tree);
 extern void push_cleanup (tree, tree, bool);
+extern tree get_any_single_nondebug_stmt_in_list (tree);
 
 extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
 			       location_t, tree, tree);
diff --git a/gcc/c-family/c-semantics.c b/gcc/c-family/c-semantics.c
index 322b26b..fbe204a 100644
--- a/gcc/c-family/c-semantics.c
+++ b/gcc/c-family/c-semantics.c
@@ -126,6 +126,40 @@ pop_stmt_list (tree t)
   return t;
 }
 
+/* If T is a statement_list, and it contains a single non-debug-statement,
+   then return that non-debug-statement.
+   Otherwise return T.  */
+
+tree
+get_any_single_nondebug_stmt_in_list (tree t)
+{
+  if (TREE_CODE (t) != STATEMENT_LIST)
+    return t;
+
+  /* Locate first non-debug stmt in T.  */
+  tree_stmt_iterator i;
+  for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+    {
+      tree u = tsi_stmt (i);
+      if (TREE_CODE (u) == DEBUG_BEGIN_STMT)
+	continue;
+      /* First non-debug stmt.  */
+      break;
+    }
+
+  if (tsi_end_p (i))
+    return t;
+
+  tree first_non_debug = tsi_stmt (i);
+  gcc_assert (TREE_CODE (first_non_debug) != DEBUG_BEGIN_STMT);
+
+  /* Are there any other non-debug stmts?  */
+  if (only_debug_stmts_after_p (i))
+    return first_non_debug;
+  else
+    return t;
+}
+
 /* Build a generic statement based on the given type of node and
    arguments. Similar to `build_nt', except that we set
    EXPR_LOCATION to LOC. */
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index ddcff69..a910c22 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1757,6 +1757,11 @@ field_accessor_p (tree fn, tree field_decl, bool const_p)
   if (saved_tree == NULL_TREE)
     return false;
 
+  /* Attempt to extract a single RETURN_EXPR from within the
+     STATEMENT_LIST.  pop_stmt_list may already have done this
+     when -g or optimization are off.  */
+  saved_tree = get_any_single_nondebug_stmt_in_list (saved_tree);
+
   if (TREE_CODE (saved_tree) != RETURN_EXPR)
     return false;
 
diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-1.C b/gcc/testsuite/g++.dg/other/accessor-fixits-1.C
deleted file mode 100644
index fd46a52..0000000
--- a/gcc/testsuite/g++.dg/other/accessor-fixits-1.C
+++ /dev/null
@@ -1,222 +0,0 @@
-// { dg-options "-fdiagnostics-show-caret" }
-
-class t1
-{
-public:
-  int get_color () const { return m_color; }
-  int get_shape () const { return m_shape; }
-
-private:
-  int m_color;
-
-protected:
-  int m_shape;
-};
-
-int test_access_t1_color (t1 &ref)
-{
-  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared private here" "" { target *-*-* } 10 }
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-              get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_access_const_t1_color (const t1 &ref)
-{
-  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-              get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_access_t1_shape (t1 &ref)
-{
-  return ref.m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_shape;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared protected here" "" { target *-*-* } 13 }
-  /* { dg-begin-multiline-output "" }
-   int m_shape;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_shape. can be accessed via .int t1::get_shape\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_shape;
-              ^~~~~~~
-              get_shape()
-     { dg-end-multiline-output "" } */
-}
-
-int test_deref_t1_color (t1 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-               get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_deref_const_t1_color (const t1 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-               get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_deref_t1_shape (t1 *ptr)
-{
-  return ptr->m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_shape;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_shape;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_shape. can be accessed via .int t1::get_shape\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_shape;
-               ^~~~~~~
-               get_shape()
-     { dg-end-multiline-output "" } */
-}
-
-/* Example of public inheritance.  */
-
-class t2 : public t1
-{
-};
-
-int test_deref_t2_color (t2 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-               get_color()
-     { dg-end-multiline-output "" } */
-}
-
-/* Example of private inheritance.  */
-
-class t3 : private t1
-{
-};
-
-int test_deref_t3_color (t3 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* We shouldn't provide a fix-it hint for this case due to the
-     private inheritance.  */
-}
-
-/* Example of non-public "accessor".  */
-
-class t4
-{
-  int m_field;
-  int get_field () { return m_field; }
-};
-
-int test_deref_t4_field (t4 *ptr)
-{
-  return ptr->m_field; // { dg-error ".int t4::m_field. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_field;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* { dg-begin-multiline-output "" }
-   int m_field;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* We shouldn't provide a fix-it hint for this case, as the accessor is
-     itself private.  */
-}
diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-2.C b/gcc/testsuite/g++.dg/other/accessor-fixits-2.C
deleted file mode 100644
index e1a2b78..0000000
--- a/gcc/testsuite/g++.dg/other/accessor-fixits-2.C
+++ /dev/null
@@ -1,104 +0,0 @@
-// { dg-options "-fdiagnostics-show-caret" }
-
-/* Test of accessors that return references.  */
-
-class t1
-{
-public:
-  int& get_color () { return m_color; }
-  int& get_shape () { return m_shape; }
-
-private:
-  int m_color;
-
-protected:
-  int m_shape;
-};
-
-int test_access_t1_color (t1 &ref)
-{
-  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared private here" "" { target *-*-* } 12 }
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int& t1::get_color\\(\\)." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_color;
-              ^~~~~~~
-              get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_access_t1_shape (t1 &ref)
-{
-  return ref.m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_shape;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared protected here" "" { target *-*-* } 15 }
-  /* { dg-begin-multiline-output "" }
-   int m_shape;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_shape. can be accessed via .int& t1::get_shape\\(\\)." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_shape;
-              ^~~~~~~
-              get_shape()
-     { dg-end-multiline-output "" } */
-}
-
-int test_deref_t1_color (t1 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_color. can be accessed via .int& t1::get_color\\(\\)." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-               get_color()
-     { dg-end-multiline-output "" } */
-}
-
-int test_deref_t1_shape (t1 *ptr)
-{
-  return ptr->m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_shape;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-
-  /* { dg-begin-multiline-output "" }
-   int m_shape;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "field .int t1::m_shape. can be accessed via .int& t1::get_shape\\(\\)." "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_shape;
-               ^~~~~~~
-               get_shape()
-     { dg-end-multiline-output "" } */
-}
diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-3.C b/gcc/testsuite/g++.dg/other/accessor-fixits-3.C
deleted file mode 100644
index 27d2eb4..0000000
--- a/gcc/testsuite/g++.dg/other/accessor-fixits-3.C
+++ /dev/null
@@ -1,15 +0,0 @@
-class foo
-{
-public:
-  static foo& get_singleton () { return s_singleton; }
-
-private:
-  static foo s_singleton;
-};
-
-foo & test_access_singleton ()
-{
-  return foo::s_singleton; // { dg-error ".foo foo::s_singleton. is private within this context" }
-  // { dg-message "declared private here" "" { target *-*-* } 7 }
-  // We don't yet support generating a fix-it hint for this case.
-}
diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-4.C b/gcc/testsuite/g++.dg/other/accessor-fixits-4.C
deleted file mode 100644
index c03dd4e..0000000
--- a/gcc/testsuite/g++.dg/other/accessor-fixits-4.C
+++ /dev/null
@@ -1,48 +0,0 @@
-// { dg-options "-fdiagnostics-show-caret" }
-
-class t1
-{
-public:
-  int& get_color () { return m_color; }
-  int& get_shape () { return m_shape; }
-
-private:
-  int m_color; // { dg-line color_decl }
-  int m_shape; // { dg-line shape_decl }
-};
-
-int test_const_ptr (const t1 *ptr)
-{
-  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ptr->m_color;
-               ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared private here" "" { target *-*-* } color_decl }
-  /* { dg-begin-multiline-output "" }
-   int m_color;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* We shouldn't issue a suggestion: the accessor is non-const, and we
-     only have a const ptr.  */
-}
-
-int test_const_reference (const t1 &ref)
-{
-  return ref.m_shape; // { dg-error ".int t1::m_shape. is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return ref.m_shape;
-              ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared private here" "" { target *-*-* } shape_decl }
-  /* { dg-begin-multiline-output "" }
-   int m_shape;
-       ^~~~~~~
-     { dg-end-multiline-output "" } */
-
-  /* We shouldn't issue a suggestion: the accessor is non-const, and we
-     only have a const ptr.  */
-}
diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-5.C b/gcc/testsuite/g++.dg/other/accessor-fixits-5.C
deleted file mode 100644
index cf72d78..0000000
--- a/gcc/testsuite/g++.dg/other/accessor-fixits-5.C
+++ /dev/null
@@ -1,33 +0,0 @@
-// PR c++/84892
-// { dg-options "-fdiagnostics-show-caret" }
-
-class S {
-private:
-  bool field;
-
-public:
-  bool get_field() const {
-    return field;
-  }
-};
-
-bool thingy(const S & s) {
-  return s.field; // { dg-error "'bool S::field' is private within this context" }
-  /* { dg-begin-multiline-output "" }
-   return s.field;
-            ^~~~~
-     { dg-end-multiline-output "" } */
-
-  // { dg-message "declared private here" "" { target *-*-* } 6 }
-  /* { dg-begin-multiline-output "" }
-   bool field;
-        ^~~~~
-     { dg-end-multiline-output "" } */
- 
-  // { dg-message "field 'bool S::field' can be accessed via 'bool S::get_field\\(\\) const'" "" { target *-*-* } .-12 }
-  /* { dg-begin-multiline-output "" }
-   return s.field;
-            ^~~~~
-            get_field()
-     { dg-end-multiline-output "" } */
-}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-1.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-1.C
new file mode 100644
index 0000000..fd46a52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-1.C
@@ -0,0 +1,222 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+class t1
+{
+public:
+  int get_color () const { return m_color; }
+  int get_shape () const { return m_shape; }
+
+private:
+  int m_color;
+
+protected:
+  int m_shape;
+};
+
+int test_access_t1_color (t1 &ref)
+{
+  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } 10 }
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+              get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_access_const_t1_color (const t1 &ref)
+{
+  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+              get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_access_t1_shape (t1 &ref)
+{
+  return ref.m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_shape;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared protected here" "" { target *-*-* } 13 }
+  /* { dg-begin-multiline-output "" }
+   int m_shape;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_shape. can be accessed via .int t1::get_shape\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_shape;
+              ^~~~~~~
+              get_shape()
+     { dg-end-multiline-output "" } */
+}
+
+int test_deref_t1_color (t1 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+               get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_deref_const_t1_color (const t1 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+               get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_deref_t1_shape (t1 *ptr)
+{
+  return ptr->m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_shape;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_shape;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_shape. can be accessed via .int t1::get_shape\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_shape;
+               ^~~~~~~
+               get_shape()
+     { dg-end-multiline-output "" } */
+}
+
+/* Example of public inheritance.  */
+
+class t2 : public t1
+{
+};
+
+int test_deref_t2_color (t2 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int t1::get_color\\(\\) const." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+               get_color()
+     { dg-end-multiline-output "" } */
+}
+
+/* Example of private inheritance.  */
+
+class t3 : private t1
+{
+};
+
+int test_deref_t3_color (t3 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* We shouldn't provide a fix-it hint for this case due to the
+     private inheritance.  */
+}
+
+/* Example of non-public "accessor".  */
+
+class t4
+{
+  int m_field;
+  int get_field () { return m_field; }
+};
+
+int test_deref_t4_field (t4 *ptr)
+{
+  return ptr->m_field; // { dg-error ".int t4::m_field. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_field;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* { dg-begin-multiline-output "" }
+   int m_field;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* We shouldn't provide a fix-it hint for this case, as the accessor is
+     itself private.  */
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-2.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-2.C
new file mode 100644
index 0000000..e1a2b78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-2.C
@@ -0,0 +1,104 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+/* Test of accessors that return references.  */
+
+class t1
+{
+public:
+  int& get_color () { return m_color; }
+  int& get_shape () { return m_shape; }
+
+private:
+  int m_color;
+
+protected:
+  int m_shape;
+};
+
+int test_access_t1_color (t1 &ref)
+{
+  return ref.m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } 12 }
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int& t1::get_color\\(\\)." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_color;
+              ^~~~~~~
+              get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_access_t1_shape (t1 &ref)
+{
+  return ref.m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_shape;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared protected here" "" { target *-*-* } 15 }
+  /* { dg-begin-multiline-output "" }
+   int m_shape;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_shape. can be accessed via .int& t1::get_shape\\(\\)." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_shape;
+              ^~~~~~~
+              get_shape()
+     { dg-end-multiline-output "" } */
+}
+
+int test_deref_t1_color (t1 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_color. can be accessed via .int& t1::get_color\\(\\)." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+               get_color()
+     { dg-end-multiline-output "" } */
+}
+
+int test_deref_t1_shape (t1 *ptr)
+{
+  return ptr->m_shape; // { dg-error ".int t1::m_shape. is protected within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_shape;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   int m_shape;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "field .int t1::m_shape. can be accessed via .int& t1::get_shape\\(\\)." "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_shape;
+               ^~~~~~~
+               get_shape()
+     { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-3.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-3.C
new file mode 100644
index 0000000..27d2eb4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-3.C
@@ -0,0 +1,15 @@
+class foo
+{
+public:
+  static foo& get_singleton () { return s_singleton; }
+
+private:
+  static foo s_singleton;
+};
+
+foo & test_access_singleton ()
+{
+  return foo::s_singleton; // { dg-error ".foo foo::s_singleton. is private within this context" }
+  // { dg-message "declared private here" "" { target *-*-* } 7 }
+  // We don't yet support generating a fix-it hint for this case.
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-4.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-4.C
new file mode 100644
index 0000000..c03dd4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-4.C
@@ -0,0 +1,48 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+class t1
+{
+public:
+  int& get_color () { return m_color; }
+  int& get_shape () { return m_shape; }
+
+private:
+  int m_color; // { dg-line color_decl }
+  int m_shape; // { dg-line shape_decl }
+};
+
+int test_const_ptr (const t1 *ptr)
+{
+  return ptr->m_color; // { dg-error ".int t1::m_color. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_color;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } color_decl }
+  /* { dg-begin-multiline-output "" }
+   int m_color;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* We shouldn't issue a suggestion: the accessor is non-const, and we
+     only have a const ptr.  */
+}
+
+int test_const_reference (const t1 &ref)
+{
+  return ref.m_shape; // { dg-error ".int t1::m_shape. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ref.m_shape;
+              ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } shape_decl }
+  /* { dg-begin-multiline-output "" }
+   int m_shape;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* We shouldn't issue a suggestion: the accessor is non-const, and we
+     only have a const ptr.  */
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-5.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-5.C
new file mode 100644
index 0000000..cf72d78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-5.C
@@ -0,0 +1,33 @@
+// PR c++/84892
+// { dg-options "-fdiagnostics-show-caret" }
+
+class S {
+private:
+  bool field;
+
+public:
+  bool get_field() const {
+    return field;
+  }
+};
+
+bool thingy(const S & s) {
+  return s.field; // { dg-error "'bool S::field' is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return s.field;
+            ^~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } 6 }
+  /* { dg-begin-multiline-output "" }
+   bool field;
+        ^~~~~
+     { dg-end-multiline-output "" } */
+ 
+  // { dg-message "field 'bool S::field' can be accessed via 'bool S::get_field\\(\\) const'" "" { target *-*-* } .-12 }
+  /* { dg-begin-multiline-output "" }
+   return s.field;
+            ^~~~~
+            get_field()
+     { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-6.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-6.C
new file mode 100644
index 0000000..ae2f180
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-6.C
@@ -0,0 +1,22 @@
+// PR c++/84994
+/* Ensure that fix-it hints are offered at every optimization level, even when
+   "-g" is enabled (coverage for every optimization level without -g is given
+   by the other cases within g++.dg/torture/accessor-fixits-*.C).  */
+// { dg-additional-options "-g" }
+
+class foo
+{
+public:
+  double get_ratio() const { return m_ratio; }
+
+private:
+  double m_ratio; // { dg-line field_decl }
+};
+
+void test(foo *ptr)
+{
+  if (ptr->m_ratio >= 0.5) // { dg-error "'double foo::m_ratio' is private within this context" }
+    ;
+  // { dg-message "declared private here" "" { target *-*-* } field_decl }
+  // { dg-message "'double foo::m_ratio' can be accessed via 'double foo::get_ratio\\(\\) const'" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-7.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-7.C
new file mode 100644
index 0000000..3b5babd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-7.C
@@ -0,0 +1,22 @@
+class foo
+{
+public:
+  double get_ratio() const;
+
+private:
+  double m_ratio; // { dg-line field_decl }
+};
+
+double
+foo::get_ratio() const
+{
+  return m_ratio;
+}
+
+void test(foo *ptr)
+{
+  if (ptr->m_ratio >= 0.5) // { dg-error "'double foo::m_ratio' is private within this context" }
+    ;
+  // { dg-message "declared private here" "" { target *-*-* } field_decl }
+  // { dg-message "'double foo::m_ratio' can be accessed via 'double foo::get_ratio\\(\\) const'" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/g++.dg/torture/accessor-fixits-8.C b/gcc/testsuite/g++.dg/torture/accessor-fixits-8.C
new file mode 100644
index 0000000..2a129e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-8.C
@@ -0,0 +1,29 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+class t1
+{
+public:
+  int get_doubled_field () const { return m_field * 2; }
+  int get_guarded_field_1 () const { if (m_field) return m_field; else return 42; }
+  int get_guarded_field_2 () const { return m_field ? m_field : 42; }
+
+private:
+  int m_field; // { dg-line field_decl }
+};
+
+int test (t1 *ptr)
+{
+  return ptr->m_field; // { dg-error ".int t1::m_field. is private within this context" }
+  /* { dg-begin-multiline-output "" }
+   return ptr->m_field;
+               ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  // { dg-message "declared private here" "" { target *-*-* } field_decl }
+  /* { dg-begin-multiline-output "" }
+   int m_field;
+       ^~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* We shouldn't issue a suggestion: none of the member functions are suitable returns.  */
+}
-- 
1.8.5.3


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