[v2] C++: show private field accessor hints with -g and optimization (PR c++/84994)

Message ID 1521651129-36826-1-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series
  • [v2] C++: show private field accessor hints with -g and optimization (PR c++/84994)
Related show

Commit Message

David Malcolm March 21, 2018, 4:52 p.m.
On Tue, 2018-03-20 at 21:51 -0400, Jason Merrill wrote:
> On Tue, Mar 20, 2018 at 7:37 PM, David Malcolm <dmalcolm@redhat.com>

> wrote:

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

> 

> Would constexpr_fn_retval be useful here?


Aha!  Indeed it is.  Thanks; this simplifies things considerably.

Here's an updated patch which uses constexpr_fn_retval, along with an
indentation fix and a little more test coverage.

Successfully bootstrapped and regression-tested on x86_64-pc-linux-gnu;
adds 486 PASS results to g++.sum (mostly due to the tests moving to
gcc+.dg/torture).

OK for trunk?

gcc/cp/ChangeLog:
	PR c++/84994
	* constexpr.c (constexpr_fn_retval): Make non-"static".
	* cp-tree.h (constexpr_fn_retval): New decl.
	* search.c (direct_accessor_p): Update leading comment.
	(reference_accessor_p): Likewise.
	(field_accessor_p): Replace check that function body is a
	RETURN_EXPR with a call to constexpr_fn_retval.  Fix
	indentation of "field_type" decl.

gcc/testsuite/ChangeLog:
	PR c++/84994
	* 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/cp/constexpr.c                               |   2 +-
 gcc/cp/cp-tree.h                                 |   1 +
 gcc/cp/search.c                                  |  21 ++-
 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 |  31 ++++
 16 files changed, 510 insertions(+), 433 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

-- 
1.8.5.3

Comments

Jason Merrill March 21, 2018, 5:04 p.m. | #1
OK.

On Wed, Mar 21, 2018 at 12:52 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2018-03-20 at 21:51 -0400, Jason Merrill wrote:

>> On Tue, Mar 20, 2018 at 7:37 PM, David Malcolm <dmalcolm@redhat.com>

>> wrote:

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

>>

>> Would constexpr_fn_retval be useful here?

>

> Aha!  Indeed it is.  Thanks; this simplifies things considerably.

>

> Here's an updated patch which uses constexpr_fn_retval, along with an

> indentation fix and a little more test coverage.

>

> Successfully bootstrapped and regression-tested on x86_64-pc-linux-gnu;

> adds 486 PASS results to g++.sum (mostly due to the tests moving to

> gcc+.dg/torture).

>

> OK for trunk?

>

> gcc/cp/ChangeLog:

>         PR c++/84994

>         * constexpr.c (constexpr_fn_retval): Make non-"static".

>         * cp-tree.h (constexpr_fn_retval): New decl.

>         * search.c (direct_accessor_p): Update leading comment.

>         (reference_accessor_p): Likewise.

>         (field_accessor_p): Replace check that function body is a

>         RETURN_EXPR with a call to constexpr_fn_retval.  Fix

>         indentation of "field_type" decl.

>

> gcc/testsuite/ChangeLog:

>         PR c++/84994

>         * 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/cp/constexpr.c                               |   2 +-

>  gcc/cp/cp-tree.h                                 |   1 +

>  gcc/cp/search.c                                  |  21 ++-

>  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 |  31 ++++

>  16 files changed, 510 insertions(+), 433 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/cp/constexpr.c b/gcc/cp/constexpr.c

> index 941562e..02bfb8e 100644

> --- a/gcc/cp/constexpr.c

> +++ b/gcc/cp/constexpr.c

> @@ -657,7 +657,7 @@ get_function_named_in_call (tree t)

>     return value if suitable, error_mark_node for a statement not allowed in

>     a constexpr function, or NULL_TREE if no return value was found.  */

>

> -static tree

> +tree

>  constexpr_fn_retval (tree body)

>  {

>    switch (TREE_CODE (body))

> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h

> index 17d8c6d..2293394 100644

> --- a/gcc/cp/cp-tree.h

> +++ b/gcc/cp/cp-tree.h

> @@ -7400,6 +7400,7 @@ extern bool literal_type_p                      (tree);

>  extern tree register_constexpr_fundef           (tree, tree);

>  extern bool is_valid_constexpr_fn              (tree, bool);

>  extern bool check_constexpr_ctor_body           (tree, tree, bool);

> +extern tree constexpr_fn_retval                (tree);

>  extern tree ensure_literal_type_for_constexpr_object (tree);

>  extern bool potential_constant_expression       (tree);

>  extern bool is_constant_expression (tree);

> diff --git a/gcc/cp/search.c b/gcc/cp/search.c

> index ddcff69..b436610 100644

> --- a/gcc/cp/search.c

> +++ b/gcc/cp/search.c

> @@ -1657,8 +1657,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type)

>

>     Specifically, a simple accessor within struct S of the form:

>         T get_field () { return m_field; }

> -   should have a DECL_SAVED_TREE of the form:

> -       <return_expr

> +   should have a constexpr_fn_retval (saved_tree) of the form:

>          <init_expr:T

>            <result_decl:T

>            <nop_expr:T

> @@ -1666,7 +1665,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type)

>                <indirect_ref:S>

>                  <nop_expr:P*

>                    <parm_decl (this)>

> -                <field_decl (FIELD_DECL)>>>.  */

> +                <field_decl (FIELD_DECL)>>>>>.  */

>

>  static bool

>  direct_accessor_p (tree init_expr, tree field_decl, tree field_type)

> @@ -1690,8 +1689,7 @@ direct_accessor_p (tree init_expr, tree field_decl, tree field_type)

>

>     Specifically, a simple accessor within struct S of the form:

>         T& get_field () { return m_field; }

> -   should have a DECL_SAVED_TREE of the form:

> -       <return_expr

> +   should have a constexpr_fn_retval (saved_tree) of the form:

>          <init_expr:T&

>            <result_decl:T&

>            <nop_expr: T&

> @@ -1757,16 +1755,19 @@ field_accessor_p (tree fn, tree field_decl, bool const_p)

>    if (saved_tree == NULL_TREE)

>      return false;

>

> -  if (TREE_CODE (saved_tree) != RETURN_EXPR)

> +  /* Attempt to extract a single return value from the function,

> +     if it has one.  */

> +  tree retval = constexpr_fn_retval (saved_tree);

> +  if (retval == NULL_TREE || retval == error_mark_node)

>      return false;

> -

> -  tree init_expr = TREE_OPERAND (saved_tree, 0);

> -  if (TREE_CODE (init_expr) != INIT_EXPR)

> +  /* Require an INIT_EXPR.  */

> +  if (TREE_CODE (retval) != INIT_EXPR)

>      return false;

> +  tree init_expr = retval;

>

>    /* Determine if this is a simple accessor within struct S of the form:

>         T get_field () { return m_field; }.  */

> -   tree field_type = TREE_TYPE (field_decl);

> +  tree field_type = TREE_TYPE (field_decl);

>    if (cxx_types_compatible_p (TREE_TYPE (init_expr), field_type))

>      return direct_accessor_p (init_expr, field_decl, field_type);

>

> 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..1338b7d

> --- /dev/null

> +++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-8.C

> @@ -0,0 +1,31 @@

> +// { 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; }

> +  int with_unreachable () const { __builtin_unreachable (); return m_field; }

> +  void no_return () { }

> +

> +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

>

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 941562e..02bfb8e 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -657,7 +657,7 @@  get_function_named_in_call (tree t)
    return value if suitable, error_mark_node for a statement not allowed in
    a constexpr function, or NULL_TREE if no return value was found.  */
 
-static tree
+tree
 constexpr_fn_retval (tree body)
 {
   switch (TREE_CODE (body))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 17d8c6d..2293394 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7400,6 +7400,7 @@  extern bool literal_type_p                      (tree);
 extern tree register_constexpr_fundef           (tree, tree);
 extern bool is_valid_constexpr_fn		(tree, bool);
 extern bool check_constexpr_ctor_body           (tree, tree, bool);
+extern tree constexpr_fn_retval		(tree);
 extern tree ensure_literal_type_for_constexpr_object (tree);
 extern bool potential_constant_expression       (tree);
 extern bool is_constant_expression (tree);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index ddcff69..b436610 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1657,8 +1657,7 @@  field_access_p (tree component_ref, tree field_decl, tree field_type)
 
    Specifically, a simple accessor within struct S of the form:
        T get_field () { return m_field; }
-   should have a DECL_SAVED_TREE of the form:
-       <return_expr
+   should have a constexpr_fn_retval (saved_tree) of the form:
 	 <init_expr:T
 	   <result_decl:T
 	   <nop_expr:T
@@ -1666,7 +1665,7 @@  field_access_p (tree component_ref, tree field_decl, tree field_type)
 	       <indirect_ref:S>
 		 <nop_expr:P*
 		   <parm_decl (this)>
-		 <field_decl (FIELD_DECL)>>>.  */
+		 <field_decl (FIELD_DECL)>>>>>.  */
 
 static bool
 direct_accessor_p (tree init_expr, tree field_decl, tree field_type)
@@ -1690,8 +1689,7 @@  direct_accessor_p (tree init_expr, tree field_decl, tree field_type)
 
    Specifically, a simple accessor within struct S of the form:
        T& get_field () { return m_field; }
-   should have a DECL_SAVED_TREE of the form:
-       <return_expr
+   should have a constexpr_fn_retval (saved_tree) of the form:
 	 <init_expr:T&
 	   <result_decl:T&
 	   <nop_expr: T&
@@ -1757,16 +1755,19 @@  field_accessor_p (tree fn, tree field_decl, bool const_p)
   if (saved_tree == NULL_TREE)
     return false;
 
-  if (TREE_CODE (saved_tree) != RETURN_EXPR)
+  /* Attempt to extract a single return value from the function,
+     if it has one.  */
+  tree retval = constexpr_fn_retval (saved_tree);
+  if (retval == NULL_TREE || retval == error_mark_node)
     return false;
-
-  tree init_expr = TREE_OPERAND (saved_tree, 0);
-  if (TREE_CODE (init_expr) != INIT_EXPR)
+  /* Require an INIT_EXPR.  */
+  if (TREE_CODE (retval) != INIT_EXPR)
     return false;
+  tree init_expr = retval;
 
   /* Determine if this is a simple accessor within struct S of the form:
        T get_field () { return m_field; }.  */
-   tree field_type = TREE_TYPE (field_decl);
+  tree field_type = TREE_TYPE (field_decl);
   if (cxx_types_compatible_p (TREE_TYPE (init_expr), field_type))
     return direct_accessor_p (init_expr, field_decl, field_type);
 
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..1338b7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/accessor-fixits-8.C
@@ -0,0 +1,31 @@ 
+// { 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; }
+  int with_unreachable () const { __builtin_unreachable (); return m_field; }
+  void no_return () { }
+
+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.  */
+}