https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84993

--- Comment #3 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Author: dmalcolm
Date: Thu Oct 11 19:03:33 2018
New Revision: 265056

URL: https://gcc.gnu.org/viewcvs?rev=265056&root=gcc&view=rev
Log:
C++: suggestions for misspelled private members (PR c++/84993)

PR c++/84993 identifies a problem with our suggestions for
misspelled member names in the C++ FE for the case where the
member is private.

For example, given:

class foo
{
public:
  double get_ratio() const { return m_ratio; }

private:
  double m_ratio;
};

void test(foo *ptr)
{
  if (ptr->ratio >= 0.5)
    ;// etc
}

...we currently emit this suggestion:

<source>: In function 'void test(foo*)':
<source>:12:12: error: 'class foo' has no member named 'ratio'; did you mean
'm_ratio'?
   if (ptr->ratio >= 0.5)
            ^~~~~
            m_ratio

...but if the user follows this suggestion, they get:

<source>: In function 'void test(foo*)':
<source>:12:12: error: 'double foo::m_ratio' is private within this context
   if (ptr->m_ratio >= 0.5)
            ^~~~~~~
<source>:7:10: note: declared private here
   double m_ratio;
          ^~~~~~~
<source>:12:12: note: field 'double foo::m_ratio' can be accessed via 'double
foo::get_ratio() const'
   if (ptr->m_ratio >= 0.5)
            ^~~~~~~
            get_ratio()

It feels wrong to be emitting a fix-it hint that doesn't compile, so this
patch adds the accessor fix-it hint logic to this case, so that we directly
offer a valid suggestion:

<source>: In function 'void test(foo*)':
<source>:12:12: error: 'class foo' has no member named 'ratio'; did you mean
'double foo::m_ratio'? (accessible via 'double foo::get_ratio() const')
   if (ptr->ratio >= 0.5)
            ^~~~~
            get_ratio()

gcc/cp/ChangeLog:
        PR c++/84993
        * call.c (enforce_access): Move diagnostics to...
        (complain_about_access): ...this new function.
        * cp-tree.h (class access_failure_info): Rename split out field
        "m_field_decl" into "m_decl" and "m_diag_decl".
        (access_failure_info::record_access_failure): Add tree param.
        (access_failure_info::was_inaccessible_p): New accessor.
        (access_failure_info::get_decl): New accessor.
        (access_failure_info::get_diag_decl): New accessor.
        (access_failure_info::get_any_accessor): New member function.
        (access_failure_info::add_fixit_hint): New static member function.
        (complain_about_access): New decl.
        * typeck.c (access_failure_info::record_access_failure): Update
        for change to fields.
        (access_failure_info::maybe_suggest_accessor): Split out into...
        (access_failure_info::get_any_accessor): ...this new function...
        (access_failure_info::add_fixit_hint): ...and this new function.
        (finish_class_member_access_expr): Split out "has no member named"
        error-handling into...
        (complain_about_unrecognized_member): ...this new function, and
        check that the guessed name is accessible along the access path.
        Only provide a spell-correction fix-it hint if it is; otherwise,
        attempt to issue an accessor fix-it hint.

gcc/testsuite/ChangeLog:
        PR c++/84993
        * g++.dg/torture/accessor-fixits-9.C: New test.


Added:
    trunk/gcc/testsuite/g++.dg/torture/accessor-fixits-9.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog

Reply via email to