aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-06-27 05:15:01 -0400
committerJason Merrill <jason@redhat.com>2023-06-28 00:42:12 -0400
commitabdf0b6cdff5783b97f35ad61ae31433f0569dfd (patch)
tree883f684665687209e8f4b227992d40086420227c /gcc
parent83f69969c0f3eb93302f6ef7714884db9079e803 (diff)
downloadgcc-abdf0b6cdff5783b97f35ad61ae31433f0569dfd.zip
gcc-abdf0b6cdff5783b97f35ad61ae31433f0569dfd.tar.gz
gcc-abdf0b6cdff5783b97f35ad61ae31433f0569dfd.tar.bz2
c++: inherited constructor attributes
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/method.cc2
-rw-r--r--gcc/cp/optimize.cc26
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C15
4 files changed, 43 insertions, 1 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8398223..0d7a6c1 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 91cf943..8ed967d 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 f73d86b..9e8926e 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 0000000..bc25559
--- /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 }
+}