136 lines
4.3 KiB
Diff
136 lines
4.3 KiB
Diff
|
From abdf0b6cdff5783b97f35ad61ae31433f0569dfd Mon Sep 17 00:00:00 2001
|
||
|
From: Jason Merrill <jason@redhat.com>
|
||
|
Date: Tue, 27 Jun 2023 05:15:01 -0400
|
||
|
Subject: [PATCH] c++: inherited constructor attributes
|
||
|
To: gcc-patches@gcc.gnu.org
|
||
|
|
||
|
Inherited constructors are like constructor clones; they don't exist from
|
||
|
the language perspective, so they should copy the attributes in the same
|
||
|
way. But it doesn't make sense to copy alias or ifunc attributes in either
|
||
|
case. Unlike handle_copy_attribute, we do want to copy inlining attributes.
|
||
|
|
||
|
The discussion of PR110334 pointed out that we weren't copying the
|
||
|
always_inline attribute, leading to poor inlining choices.
|
||
|
|
||
|
PR c++/110334
|
||
|
|
||
|
gcc/cp/ChangeLog:
|
||
|
|
||
|
* cp-tree.h (clone_attrs): Declare.
|
||
|
* method.cc (implicitly_declare_fn): Use it for inherited
|
||
|
constructor.
|
||
|
* optimize.cc (clone_attrs): New.
|
||
|
(maybe_clone_body): Use it.
|
||
|
|
||
|
gcc/testsuite/ChangeLog:
|
||
|
|
||
|
* g++.dg/cpp1z/nodiscard-inh1.C: New test.
|
||
|
---
|
||
|
gcc/cp/cp-tree.h | 1 +
|
||
|
gcc/cp/method.cc | 2 ++
|
||
|
gcc/cp/optimize.cc | 26 ++++++++++++++++++++-
|
||
|
gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C | 15 ++++++++++++
|
||
|
4 files changed, 43 insertions(+), 1 deletion(-)
|
||
|
create mode 100644 gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C
|
||
|
|
||
|
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
|
||
|
index 83982233111..0d7a6c153dc 100644
|
||
|
--- a/gcc/cp/cp-tree.h
|
||
|
+++ b/gcc/cp/cp-tree.h
|
||
|
@@ -7282,6 +7282,7 @@ extern void module_preprocess_options (cpp_reader *);
|
||
|
extern bool handle_module_option (unsigned opt, const char *arg, int value);
|
||
|
|
||
|
/* In optimize.cc */
|
||
|
+extern tree clone_attrs (tree);
|
||
|
extern bool maybe_clone_body (tree);
|
||
|
|
||
|
/* In parser.cc */
|
||
|
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
|
||
|
index 91cf943f110..8ed967ddb21 100644
|
||
|
--- a/gcc/cp/method.cc
|
||
|
+++ b/gcc/cp/method.cc
|
||
|
@@ -3294,6 +3294,8 @@ implicitly_declare_fn (special_function_kind kind, tree type,
|
||
|
/* Copy constexpr from the inherited constructor even if the
|
||
|
inheriting constructor doesn't satisfy the requirements. */
|
||
|
constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor);
|
||
|
+ /* Also copy any attributes. */
|
||
|
+ DECL_ATTRIBUTES (fn) = clone_attrs (DECL_ATTRIBUTES (inherited_ctor));
|
||
|
}
|
||
|
|
||
|
/* Add the "this" parameter. */
|
||
|
diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
|
||
|
index f73d86b6c6b..9e8926e4cc6 100644
|
||
|
--- a/gcc/cp/optimize.cc
|
||
|
+++ b/gcc/cp/optimize.cc
|
||
|
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
|
||
|
#include "debug.h"
|
||
|
#include "tree-inline.h"
|
||
|
#include "tree-iterator.h"
|
||
|
+#include "attribs.h"
|
||
|
|
||
|
/* Prototypes. */
|
||
|
|
||
|
@@ -446,6 +447,29 @@ maybe_thunk_body (tree fn, bool force)
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+/* Copy most attributes from ATTRS, omitting attributes that can really only
|
||
|
+ apply to a single decl. */
|
||
|
+
|
||
|
+tree
|
||
|
+clone_attrs (tree attrs)
|
||
|
+{
|
||
|
+ tree new_attrs = NULL_TREE;
|
||
|
+ tree *p = &new_attrs;
|
||
|
+
|
||
|
+ for (tree a = attrs; a; a = TREE_CHAIN (a))
|
||
|
+ {
|
||
|
+ tree aname = get_attribute_name (a);
|
||
|
+ if (is_attribute_namespace_p ("", a)
|
||
|
+ && (is_attribute_p ("alias", aname)
|
||
|
+ || is_attribute_p ("ifunc", aname)))
|
||
|
+ continue;
|
||
|
+ *p = copy_node (a);
|
||
|
+ p = &TREE_CHAIN (*p);
|
||
|
+ }
|
||
|
+ *p = NULL_TREE;
|
||
|
+ return new_attrs;
|
||
|
+}
|
||
|
+
|
||
|
/* FN is a function that has a complete body. Clone the body as
|
||
|
necessary. Returns nonzero if there's no longer any need to
|
||
|
process the main body. */
|
||
|
@@ -503,7 +527,7 @@ maybe_clone_body (tree fn)
|
||
|
DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
|
||
|
DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
|
||
|
DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
|
||
|
- DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
|
||
|
+ DECL_ATTRIBUTES (clone) = clone_attrs (DECL_ATTRIBUTES (fn));
|
||
|
DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
|
||
|
set_decl_section_name (clone, fn);
|
||
|
|
||
|
diff --git a/gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C b/gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C
|
||
|
new file mode 100644
|
||
|
index 00000000000..bc2555930f1
|
||
|
--- /dev/null
|
||
|
+++ b/gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C
|
||
|
@@ -0,0 +1,15 @@
|
||
|
+// [[nodiscard]] should apply to inherited constructors.
|
||
|
+// { dg-do compile { target c++11 } }
|
||
|
+
|
||
|
+struct A {
|
||
|
+ [[nodiscard]] A(int);
|
||
|
+};
|
||
|
+
|
||
|
+struct B: A {
|
||
|
+ using A::A;
|
||
|
+};
|
||
|
+
|
||
|
+int main()
|
||
|
+{
|
||
|
+ B(42); // { dg-warning nodiscard }
|
||
|
+}
|
||
|
--
|
||
|
2.35.3
|
||
|
|