From: David Malcolm Date: Wed, 21 Mar 2018 18:21:39 +0000 (+0000) Subject: C++: show private field accessor hints with -g and optimization (PR c++/84994) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5afef8b119ac69393900a8be42cc6b69ad0bcbd0;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8fc9314ac0f..c8b6b1703bd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2018-03-21 David Malcolm + + 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 PR c++/84804 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 9e813bf0bcd..bebd9f5b5d0 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 4df16e2e1ca..d5382c2604f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7424,6 +7424,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 ddcff69ae6f..b4366102e23 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: - - >>. */ + >>>>. */ 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: - + + 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 * gcc.dg/tree-ssa/pr84512.c: xfail on 64-bit SPARC. 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 fd46a522486..00000000000 --- 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 e1a2b7865b5..00000000000 --- 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 27d2eb4d048..00000000000 --- 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 c03dd4ea487..00000000000 --- 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 cf72d784330..00000000000 --- 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 00000000000..fd46a522486 --- /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 00000000000..e1a2b7865b5 --- /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 00000000000..27d2eb4d048 --- /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 00000000000..c03dd4ea487 --- /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 00000000000..cf72d784330 --- /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 00000000000..ae2f180a8f2 --- /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 00000000000..3b5babdc513 --- /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 00000000000..1338b7d1349 --- /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. */ +}