OK.

On Wed, Mar 21, 2018 at 12:52 PM, David Malcolm <dmalc...@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 <dmalc...@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
>

Reply via email to