Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
Since -Wdangling-reference has false positives that can't be
prevented, we should offer an easy way to suppress the warning.
Currently, that is only possible by using a #pragma, either around the
enclosing class or around the call site. But #pragma GCC diagnostic tend
to be onerous. A better solution would be to have an attribute. Such
an attribute should not be tied to this particular warning though. [*]
The warning bogusly triggers for classes that are like std::span,
std::reference_wrapper, and std::ranges::ref_view. The common property
seems to be that these classes are only wrappers around some data. So
I chose the name non_owning, but I'm not attached to it. I hope that
in the future the attribute can be used for something other than this
diagnostic.
[*] As I'm typing this, it's occurring to me that we might consider
having a general attribute allowing users to do [[gnu::ignore("-Wfoo")]].
PR c++/110358
PR c++/109642
gcc/cp/ChangeLog:
* call.cc (do_warn_dangling_reference): Don't warn when the function
or its enclosing class has attribute gnu::non_owning.
* tree.cc (cxx_gnu_attributes): Add gnu::non_owning.
(handle_non_owning_attribute): New.
gcc/ChangeLog:
* doc/extend.texi: Document gnu::non_owning.
* doc/invoke.texi: Mention that gnu::non_owning disables
-Wdangling-reference.
gcc/testsuite/ChangeLog:
* g++.dg/ext/attr-non-owning1.C: New test.
* g++.dg/ext/attr-non-owning2.C: New test.
* g++.dg/ext/attr-non-owning3.C: New test.
* g++.dg/ext/attr-non-owning4.C: New test.
* g++.dg/ext/attr-non-owning5.C: New test.
---
gcc/cp/call.cc | 9 -
gcc/cp/tree.cc | 20 +++
gcc/doc/extend.texi | 15
gcc/doc/invoke.texi | 21
gcc/testsuite/g++.dg/ext/attr-non-owning1.C | 38 +
gcc/testsuite/g++.dg/ext/attr-non-owning2.C | 28 +++
gcc/testsuite/g++.dg/ext/attr-non-owning3.C | 24 +
gcc/testsuite/g++.dg/ext/attr-non-owning4.C | 14
gcc/testsuite/g++.dg/ext/attr-non-owning5.C | 29
9 files changed, 197 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning1.C
create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning2.C
create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning3.C
create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning4.C
create mode 100644 gcc/testsuite/g++.dg/ext/attr-non-owning5.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 9de0d77c423..88ddba825a9 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14157,9 +14157,16 @@ do_warn_dangling_reference (tree expr, bool arg_p)
but probably not to one of its arguments. */
|| (DECL_OBJECT_MEMBER_FUNCTION_P (fndecl)
&& DECL_OVERLOADED_OPERATOR_P (fndecl)
- && DECL_OVERLOADED_OPERATOR_IS (fndecl, INDIRECT_REF)))
+ && DECL_OVERLOADED_OPERATOR_IS (fndecl, INDIRECT_REF))
+ || lookup_attribute ("non_owning",
+TYPE_ATTRIBUTES (TREE_TYPE (fndecl
return NULL_TREE;
+ if (tree ctx = CP_DECL_CONTEXT (fndecl))
+ if (TYPE_P (ctx)
+ && lookup_attribute ("non_owning", TYPE_ATTRIBUTES (ctx)))
+ return NULL_TREE;
+
tree rettype = TREE_TYPE (TREE_TYPE (fndecl));
/* If the function doesn't return a reference, don't warn. This
can be e.g.
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 77f57e0f9ac..2adf59b22d4 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -47,6 +47,7 @@ static tree verify_stmt_tree_r (tree *, int *, void *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *);
static tree handle_contract_attribute (tree *, tree, tree, int, bool *);
+static tree handle_non_owning_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. */
@@ -5096,6 +5097,8 @@ static const attribute_spec cxx_gnu_attributes[] =
handle_init_priority_attribute, NULL },
{ "abi_tag", 1, -1, false, false, false, true,
handle_abi_tag_attribute, NULL },
+ { "non_owning", 0, 0, false, true, false, false,
+handle_non_owning_attribute, NULL },
};
const scoped_attribute_specs cxx_gnu_attribute_table =
@@ -5385,6 +5388,23 @@ handle_contract_attribute (tree *ARG_UNUSED (node), tree
ARG_UNUSED (name),
return NULL_TREE;
}
+/* Handle a "non_owning" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+tree
+handle_non_owning_attribute (tree *node, tree name, tree args, int,
+bool *no_add_attrs)
+{