PR c++/84892 reports that we fail to offer fix-it hints about accessor member functions when complaining about accesses to private fields through const pointers and references.
It turns out that field_accessor_p was incorrectly checking for "this" being a "const *T", rather than being a "const T*". We were also missing test coverage for this ("offer it for const") case (we were only checking for the "don't offer it for non-const" case). Successfully bootstrapped and regression-tested on x86_64-pc-linux-gnu. OK for trunk? (not technically a regression, but affects a new feature) gcc/cp/ChangeLog: PR c++/84892 * search.c (field_accessor_p): Use class_of_this_parm rather than type_of_this_parm, to check that "this" is a "const T *", rather than a "T const *". gcc/testsuite/ChangeLog: PR c++/84892 * g++.dg/other/accessor-fixits-1.C (test_access_const_t1_color): New. (test_deref_const_t1_color): New. * g++.dg/other/accessor-fixits-5.C: New testcase. --- gcc/cp/search.c | 4 +-- gcc/testsuite/g++.dg/other/accessor-fixits-1.C | 44 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/other/accessor-fixits-5.C | 33 +++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/accessor-fixits-5.C diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 796209f..ddcff69 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1747,8 +1747,8 @@ field_accessor_p (tree fn, tree field_decl, bool const_p) that the "this" parameter is const. */ if (const_p) { - tree this_type = type_of_this_parm (fntype); - if (!TYPE_READONLY (this_type)) + tree this_class = class_of_this_parm (fntype); + if (!TYPE_READONLY (this_class)) return false; } diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-1.C b/gcc/testsuite/g++.dg/other/accessor-fixits-1.C index cc96b87..fd46a52 100644 --- a/gcc/testsuite/g++.dg/other/accessor-fixits-1.C +++ b/gcc/testsuite/g++.dg/other/accessor-fixits-1.C @@ -35,6 +35,28 @@ int test_access_t1_color (t1 &ref) { 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" } @@ -79,6 +101,28 @@ int test_deref_t1_color (t1 *ptr) { 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" } diff --git a/gcc/testsuite/g++.dg/other/accessor-fixits-5.C b/gcc/testsuite/g++.dg/other/accessor-fixits-5.C new file mode 100644 index 0000000..cf72d78 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/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 "" } */ +} -- 1.8.5.3