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 >