Skip to content

Commit

Permalink
c++: adjust accessor fixits for explicit object parm
Browse files Browse the repository at this point in the history
In a couple of places in the xobj patch I noticed that is_this_parameter
probably wanted to change to is_object_parameter; this implements that and
does the additional adjustments needed to make the accessor fixits handle
xobj parms.

gcc/cp/ChangeLog:

	* semantics.cc (is_object_parameter): New.
	* cp-tree.h (is_object_parameter): Declare.
	* call.cc (maybe_warn_class_memaccess): Use it.
	* search.cc (field_access_p): Use it.
	(class_of_object_parm): New.
	(field_accessor_p): Adjust for explicit object parms.

gcc/testsuite/ChangeLog:

	* g++.dg/torture/accessor-fixits-9-xobj.C: New test.
  • Loading branch information
jicama authored and Liaoshihua committed Mar 13, 2024
1 parent 283f10d commit ba36d15
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 7 deletions.
3 changes: 1 addition & 2 deletions gcc/cp/call.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10815,8 +10815,7 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl,
be more permissive. */
if (current_function_decl
&& DECL_OBJECT_MEMBER_FUNCTION_P (current_function_decl)
/* ??? is_object_parameter? */
&& is_this_parameter (tree_strip_nop_conversions (dest)))
&& is_object_parameter (tree_strip_nop_conversions (dest)))
{
tree ctx = DECL_CONTEXT (current_function_decl);
bool special = same_type_ignoring_top_level_qualifiers_p (ctx, desttype);
Expand Down
1 change: 1 addition & 0 deletions gcc/cp/cp-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -7781,6 +7781,7 @@ extern void finish_handler_parms (tree, tree);
extern void finish_handler (tree);
extern void finish_cleanup (tree, tree);
extern bool is_this_parameter (tree);
extern bool is_object_parameter (tree);

enum {
BCS_NORMAL = 0,
Expand Down
19 changes: 14 additions & 5 deletions gcc/cp/search.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1737,8 +1737,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type)
return false;

tree ptr = STRIP_NOPS (TREE_OPERAND (indirect_ref, 0));
/* ??? is_object_parameter? */
if (!is_this_parameter (ptr))
if (!is_object_parameter (ptr))
return false;

/* Must access the correct field. */
Expand Down Expand Up @@ -1818,6 +1817,17 @@ reference_accessor_p (tree init_expr, tree field_decl, tree field_type,
return true;
}

/* Return the class of the `this' or explicit object parameter of FN. */

static tree
class_of_object_parm (const_tree fn)
{
tree fntype = TREE_TYPE (fn);
if (DECL_XOBJ_MEMBER_FUNCTION_P (fn))
return non_reference (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
return class_of_this_parm (fntype);
}

/* Return true if FN is an accessor method for FIELD_DECL.
i.e. a method of the form { return FIELD; }, with no
conversions.
Expand All @@ -1835,15 +1845,14 @@ field_accessor_p (tree fn, tree field_decl, bool const_p)
if (TREE_CODE (field_decl) != FIELD_DECL)
return false;

tree fntype = TREE_TYPE (fn);
if (TREE_CODE (fntype) != METHOD_TYPE)
if (!DECL_OBJECT_MEMBER_FUNCTION_P (fn))
return false;

/* If the field is accessed via a const "this" argument, verify
that the "this" parameter is const. */
if (const_p)
{
tree this_class = class_of_this_parm (fntype);
tree this_class = class_of_object_parm (fn);
if (!TYPE_READONLY (this_class))
return false;
}
Expand Down
14 changes: 14 additions & 0 deletions gcc/cp/semantics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12835,6 +12835,20 @@ is_this_parameter (tree t)
return true;
}

/* As above, or a C++23 explicit object parameter. */

bool
is_object_parameter (tree t)
{
if (is_this_parameter (t))
return true;
if (TREE_CODE (t) != PARM_DECL)
return false;
tree ctx = DECL_CONTEXT (t);
return (ctx && DECL_XOBJ_MEMBER_FUNCTION_P (ctx)
&& t == DECL_ARGUMENTS (ctx));
}

/* Insert the deduced return type for an auto function. */

void
Expand Down
119 changes: 119 additions & 0 deletions gcc/testsuite/g++.dg/torture/accessor-fixits-9-xobj.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// PR c++/84993
// { dg-options "-fdiagnostics-show-caret -std=c++23" }

/* Misspelling (by omitting a leading "m_") of a private member for which
there's a public accessor.
We expect a fix-it hint suggesting the accessor. */

class t1
{
public:
int get_ratio (this const t1& x) { return x.m_ratio; }

private:
int m_ratio;
};

int test (t1 *ptr_1)
{
return ptr_1->ratio; // { dg-error "'class t1' has no member named 'ratio'; did you mean 'int t1::m_ratio'\\? \\(accessible via 'int t1::get_ratio\\(this const t1&\\)'\\)" }
/* { dg-begin-multiline-output "" }
return ptr_1->ratio;
^~~~~
get_ratio()
{ dg-end-multiline-output "" } */
}


/* Misspelling of a private member for which there's a public accessor.
We expect a fix-it hint suggesting the accessor. */

class t2
{
public:
int get_color (this const t2& x) { return x.m_color; }

private:
int m_color;
};

int test (t2 *ptr_2)
{
return ptr_2->m_colour; // { dg-error "'class t2' has no member named 'm_colour'; did you mean 'int t2::m_color'\\? \\(accessible via 'int t2::get_color\\(this const t2&\\)'\\)" }
/* { dg-begin-multiline-output "" }
return ptr_2->m_colour;
^~~~~~~~
get_color()
{ dg-end-multiline-output "" } */
}


/* Misspelling of a private member via a subclass pointer, for which there's
a public accessor in the base class.
We expect a fix-it hint suggesting the accessor. */

class t3 : public t2 {};

int test (t3 *ptr_3)
{
return ptr_3->m_colour; // { dg-error "'class t3' has no member named 'm_colour'; did you mean 'int t2::m_color'\\? \\(accessible via 'int t2::get_color\\(this const t2&\\)'\\)" }
/* { dg-begin-multiline-output "" }
return ptr_3->m_colour;
^~~~~~~~
get_color()
{ dg-end-multiline-output "" } */
}


/* Misspelling of a protected member, for which there's isn't a public
accessor.
We expect no fix-it hint; instead a message identifying where the
data member was declared. */

class t4
{
protected:
int m_color; // { dg-message "declared protected here" }
};

int test (t4 *ptr_4)
{
return ptr_4->m_colour; // { dg-error "'class t4' has no member named 'm_colour'; did you mean 'int t4::m_color'\\? \\(not accessible from this context\\)" }
/* { dg-begin-multiline-output "" }
return ptr_4->m_colour;
^~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
int m_color;
^~~~~~~
{ dg-end-multiline-output "" } */
}


/* Misspelling of a private member, for which the accessor is also private.
We expect no fix-it hint; instead a message identifying where the
data member was declared. */

class t5
{
int get_color (this const t5& x) { return x.m_color; }
int m_color; // { dg-message "declared private here" }
};

int test (t5 *ptr_5)
{
return ptr_5->m_colour; // { dg-error "'class t5' has no member named 'm_colour'; did you mean 'int t5::m_color'\\? \\(not accessible from this context\\)" }
/* { dg-begin-multiline-output "" }
return ptr_5->m_colour;
^~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
int m_color;
^~~~~~~
{ dg-end-multiline-output "" } */
}

0 comments on commit ba36d15

Please sign in to comment.