]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: inherited constructor attributes
authorJason Merrill <jason@redhat.com>
Tue, 27 Jun 2023 09:15:01 +0000 (05:15 -0400)
committerJason Merrill <jason@redhat.com>
Wed, 28 Jun 2023 04:42:12 +0000 (00:42 -0400)
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
gcc/cp/method.cc
gcc/cp/optimize.cc
gcc/testsuite/g++.dg/cpp1z/nodiscard-inh1.C [new file with mode: 0644]

index 8398223311194837441107cb335d497ff5f5ec1c..0d7a6c153dc69857a71d80e6025117e5fcd78696 100644 (file)
@@ -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 */
index 91cf943f11089c0e6bcbe8377daa4e016f956d56..8ed967ddb215a123c17a91a35fad40e6727ee6fe 100644 (file)
@@ -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.  */
index f73d86b6c6b4c71f622b5362673f8c86b2bb2f06..9e8926e4cc6030280a1c66c47141e8ae332a64aa 100644 (file)
@@ -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 (file)
index 0000000..bc25559
--- /dev/null
@@ -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 }
+}