Commit 5afef8b1 by David Malcolm Committed by David Malcolm

C++: show private field accessor hints with -g and optimization (PR c++/84994)

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.

From-SVN: r258731
parent aa3dd753
2018-03-21 David Malcolm <dmalcolm@redhat.com>
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.
2018-03-21 Nathan Sidwell <nathan@acm.org> 2018-03-21 Nathan Sidwell <nathan@acm.org>
PR c++/84804 PR c++/84804
......
...@@ -657,7 +657,7 @@ get_function_named_in_call (tree t) ...@@ -657,7 +657,7 @@ get_function_named_in_call (tree t)
return value if suitable, error_mark_node for a statement not allowed in 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. */ a constexpr function, or NULL_TREE if no return value was found. */
static tree tree
constexpr_fn_retval (tree body) constexpr_fn_retval (tree body)
{ {
switch (TREE_CODE (body)) switch (TREE_CODE (body))
......
...@@ -7424,6 +7424,7 @@ extern bool literal_type_p (tree); ...@@ -7424,6 +7424,7 @@ extern bool literal_type_p (tree);
extern tree register_constexpr_fundef (tree, tree); extern tree register_constexpr_fundef (tree, tree);
extern bool is_valid_constexpr_fn (tree, bool); extern bool is_valid_constexpr_fn (tree, bool);
extern bool check_constexpr_ctor_body (tree, 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 tree ensure_literal_type_for_constexpr_object (tree);
extern bool potential_constant_expression (tree); extern bool potential_constant_expression (tree);
extern bool is_constant_expression (tree); extern bool is_constant_expression (tree);
......
...@@ -1657,8 +1657,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type) ...@@ -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: Specifically, a simple accessor within struct S of the form:
T get_field () { return m_field; } T get_field () { return m_field; }
should have a DECL_SAVED_TREE of the form: should have a constexpr_fn_retval (saved_tree) of the form:
<return_expr
<init_expr:T <init_expr:T
<result_decl:T <result_decl:T
<nop_expr:T <nop_expr:T
...@@ -1666,7 +1665,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type) ...@@ -1666,7 +1665,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type)
<indirect_ref:S> <indirect_ref:S>
<nop_expr:P* <nop_expr:P*
<parm_decl (this)> <parm_decl (this)>
<field_decl (FIELD_DECL)>>>. */ <field_decl (FIELD_DECL)>>>>>. */
static bool static bool
direct_accessor_p (tree init_expr, tree field_decl, tree field_type) 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) ...@@ -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: Specifically, a simple accessor within struct S of the form:
T& get_field () { return m_field; } T& get_field () { return m_field; }
should have a DECL_SAVED_TREE of the form: should have a constexpr_fn_retval (saved_tree) of the form:
<return_expr
<init_expr:T& <init_expr:T&
<result_decl:T& <result_decl:T&
<nop_expr: T& <nop_expr: T&
...@@ -1757,16 +1755,19 @@ field_accessor_p (tree fn, tree field_decl, bool const_p) ...@@ -1757,16 +1755,19 @@ field_accessor_p (tree fn, tree field_decl, bool const_p)
if (saved_tree == NULL_TREE) if (saved_tree == NULL_TREE)
return false; 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; return false;
/* Require an INIT_EXPR. */
tree init_expr = TREE_OPERAND (saved_tree, 0); if (TREE_CODE (retval) != INIT_EXPR)
if (TREE_CODE (init_expr) != INIT_EXPR)
return false; return false;
tree init_expr = retval;
/* Determine if this is a simple accessor within struct S of the form: /* Determine if this is a simple accessor within struct S of the form:
T get_field () { return m_field; }. */ 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)) if (cxx_types_compatible_p (TREE_TYPE (init_expr), field_type))
return direct_accessor_p (init_expr, field_decl, field_type); return direct_accessor_p (init_expr, field_decl, field_type);
......
2018-03-21 David Malcolm <dmalcolm@redhat.com>
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.
2018-03-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2018-03-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc.dg/tree-ssa/pr84512.c: xfail on 64-bit SPARC. * gcc.dg/tree-ssa/pr84512.c: xfail on 64-bit SPARC.
......
// 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 }
}
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 }
}
// { 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. */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment