+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
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))
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);
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
<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)
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&
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);
+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.
--- /dev/null
+// 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 }
+}
--- /dev/null
+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 }
+}
--- /dev/null
+// { 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. */
+}