C++: show private field accessor hints with -g and optimization (PR c++/84994)
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 21 Mar 2018 18:21:39 +0000 (18:21 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Wed, 21 Mar 2018 18:21:39 +0000 (18:21 +0000)
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

18 files changed:
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/accessor-fixits-1.C [deleted file]
gcc/testsuite/g++.dg/other/accessor-fixits-2.C [deleted file]
gcc/testsuite/g++.dg/other/accessor-fixits-3.C [deleted file]
gcc/testsuite/g++.dg/other/accessor-fixits-4.C [deleted file]
gcc/testsuite/g++.dg/other/accessor-fixits-5.C [deleted file]
gcc/testsuite/g++.dg/torture/accessor-fixits-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/accessor-fixits-8.C [new file with mode: 0644]

index 8fc9314ac0f684187df9705081cae2722a29a822..c8b6b1703bd6ebba59840e879599b47da0dc6e20 100644 (file)
@@ -1,3 +1,14 @@
+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>
 
        PR c++/84804
index 9e813bf0bcd385005942e81213ce4a4e95a36e71..bebd9f5b5d0b9d43ea96037fa4a4858fe3ef720c 100644 (file)
@@ -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))
index 4df16e2e1caf7b5e3e58ed4b7a960618f9056aac..d5382c2604f08eaf28644bfd33e198a81c53157f 100644 (file)
@@ -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);
index ddcff69ae6f7fefbcf1ff0a183cb4736ab20cb7e..b4366102e23839ab6474efd8a8228e9f67bc1144 100644 (file)
@@ -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:
-       <return_expr
+   should have a constexpr_fn_retval (saved_tree) of the form:
         <init_expr:T
           <result_decl:T
           <nop_expr:T
@@ -1666,7 +1665,7 @@ field_access_p (tree component_ref, tree field_decl, tree field_type)
               <indirect_ref:S>
                 <nop_expr:P*
                   <parm_decl (this)>
-                <field_decl (FIELD_DECL)>>>.  */
+                <field_decl (FIELD_DECL)>>>>>.  */
 
 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:
-       <return_expr
+   should have a constexpr_fn_retval (saved_tree) of the form:
         <init_expr:T&
           <result_decl:T&
           <nop_expr: T&
@@ -1757,16 +1755,19 @@ field_accessor_p (tree fn, tree field_decl, bool const_p)
   if (saved_tree == NULL_TREE)
     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;
-
-  tree init_expr = TREE_OPERAND (saved_tree, 0);
-  if (TREE_CODE (init_expr) != INIT_EXPR)
+  /* Require an INIT_EXPR.  */
+  if (TREE_CODE (retval) != INIT_EXPR)
     return false;
+  tree init_expr = retval;
 
   /* Determine if this is a simple accessor within struct S of the form:
        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))
     return direct_accessor_p (init_expr, field_decl, field_type);
 
index 00fba27f6833d66f78ffdba68e9c4b22fdbeeb30..5d25d56226a76a0d8cb0b8a954998b422894e975 100644 (file)
@@ -1,3 +1,20 @@
+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>
 
        * 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 (file)
index fd46a52..0000000
+++ /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 (file)
index e1a2b78..0000000
+++ /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 (file)
index 27d2eb4..0000000
+++ /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 (file)
index c03dd4e..0000000
+++ /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 (file)
index cf72d78..0000000
+++ /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 (file)
index 0000000..fd46a52
--- /dev/null
@@ -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 (file)
index 0000000..e1a2b78
--- /dev/null
@@ -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 (file)
index 0000000..27d2eb4
--- /dev/null
@@ -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 (file)
index 0000000..c03dd4e
--- /dev/null
@@ -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 (file)
index 0000000..cf72d78
--- /dev/null
@@ -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 (file)
index 0000000..ae2f180
--- /dev/null
@@ -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 (file)
index 0000000..3b5babd
--- /dev/null
@@ -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 (file)
index 0000000..1338b7d
--- /dev/null
@@ -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.  */
+}