diff mbox series

c++: Fix up handling of dependent (late) attributes on function/method types [PR116175]

Message ID ZqvWUUv6P0K561JG@tucnak
State New
Headers show
Series c++: Fix up handling of dependent (late) attributes on function/method types [PR116175] | expand

Commit Message

Jakub Jelinek Aug. 1, 2024, 6:39 p.m. UTC
Hi!

When working on unsequenced/reproducible attributes, I've noticed that on
templates for some attributes decl_attributes isn't called at all, so they
are kept in TYPE_ATTRIBUTES without any verification/transformations and
also without argument substitution.

The following patch fixes that for FUNCTION/METHOD_TYPE attributes.
The included testcase ICEs without the pt.cc changes.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-08-01  Jakub Jelinek  <jakub@redhat.com>

	PR c++/116175
	* pt.cc (apply_late_template_attributes): For function/method types
	call cp_build_type_attribute_variant on the non-dependent attributes.
	(rebuild_function_or_method_type): Add ARGS argument.  Use
	apply_late_template_attributes rather than
	cp_build_type_attribute_variant.
	(maybe_rebuild_function_decl_type): Add ARGS argument, pass it to
	rebuild_function_or_method_type.
	(tsubst_function_decl): Adjust caller.
	(tsubst_function_type): Adjust rebuild_function_or_method_type caller.

	* g++.dg/ext/attr-format4.C: New test.


	Jakub

Comments

Jason Merrill Aug. 6, 2024, 9:44 p.m. UTC | #1
On 8/1/24 2:39 PM, Jakub Jelinek wrote:
> Hi!
> 
> When working on unsequenced/reproducible attributes, I've noticed that on
> templates for some attributes decl_attributes isn't called at all, so they
> are kept in TYPE_ATTRIBUTES without any verification/transformations and
> also without argument substitution.
> 
> The following patch fixes that for FUNCTION/METHOD_TYPE attributes.
> The included testcase ICEs without the pt.cc changes.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> 2024-08-01  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/116175
> 	* pt.cc (apply_late_template_attributes): For function/method types
> 	call cp_build_type_attribute_variant on the non-dependent attributes.
> 	(rebuild_function_or_method_type): Add ARGS argument.  Use
> 	apply_late_template_attributes rather than
> 	cp_build_type_attribute_variant.
> 	(maybe_rebuild_function_decl_type): Add ARGS argument, pass it to
> 	rebuild_function_or_method_type.
> 	(tsubst_function_decl): Adjust caller.
> 	(tsubst_function_type): Adjust rebuild_function_or_method_type caller.
> 
> 	* g++.dg/ext/attr-format4.C: New test.
> 
> --- gcc/cp/pt.cc.jj	2024-07-31 14:38:54.405628645 +0200
> +++ gcc/cp/pt.cc	2024-08-01 16:29:59.671779469 +0200
> @@ -12219,6 +12219,8 @@ apply_late_template_attributes (tree *de
>            to our attributes parameter.  */
>         gcc_assert (*p == attributes);
>       }
> +  else if (FUNC_OR_METHOD_TYPE_P (*decl_p))
> +    p = NULL;
>     else
>       {
>         p = &TYPE_ATTRIBUTES (*decl_p);
> @@ -12237,7 +12239,10 @@ apply_late_template_attributes (tree *de
>     tree nondep = t;
>   
>     /* Apply any non-dependent attributes.  */
> -  *p = nondep;
> +  if (p)
> +    *p = nondep;
> +  else if (nondep)
> +    *decl_p = cp_build_type_attribute_variant (*decl_p, nondep);
>   
>     if (nondep == attributes)
>       return true;
> @@ -14375,8 +14380,9 @@ lookup_explicit_specifier (tree v)
>      identical to T.  */
>   
>   static tree
> -rebuild_function_or_method_type (tree t, tree return_type, tree arg_types,
> -				 tree raises, tsubst_flags_t complain)
> +rebuild_function_or_method_type (tree t, tree args, tree return_type,
> +				 tree arg_types, tree raises,
> +				 tsubst_flags_t complain)
>   {
>     gcc_assert (FUNC_OR_METHOD_TYPE_P (t));
>   
> @@ -14409,7 +14415,9 @@ rebuild_function_or_method_type (tree t,
>         new_type = build_method_type_directly (r, return_type,
>   					     TREE_CHAIN (arg_types));
>       }
> -  new_type = cp_build_type_attribute_variant (new_type, TYPE_ATTRIBUTES (t));
> +  if (!apply_late_template_attributes (&new_type, TYPE_ATTRIBUTES (t), 0,
> +				       args, complain, NULL_TREE))
> +    return error_mark_node;
>   
>     cp_ref_qualifier rqual = type_memfn_rqual (t);
>     bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t);
> @@ -14422,7 +14430,7 @@ rebuild_function_or_method_type (tree t,
>      resolution for Core issues 1001/1322.  */
>   
>   static void
> -maybe_rebuild_function_decl_type (tree decl)
> +maybe_rebuild_function_decl_type (tree decl, tree args)
>   {
>     bool function_type_needs_rebuilding = false;
>     if (tree parm_list = FUNCTION_FIRST_USER_PARM (decl))
> @@ -14474,7 +14482,7 @@ maybe_rebuild_function_decl_type (tree d
>       *q = void_list_node;
>   
>     TREE_TYPE (decl)
> -    = rebuild_function_or_method_type (fntype,
> +    = rebuild_function_or_method_type (fntype, args,
>   				       TREE_TYPE (fntype), new_parm_type_list,
>   				       TYPE_RAISES_EXCEPTIONS (fntype), tf_none);
>   }
> @@ -14657,7 +14665,7 @@ tsubst_function_decl (tree t, tree args,
>     DECL_ARGUMENTS (r) = parms;
>     DECL_RESULT (r) = NULL_TREE;
>   
> -  maybe_rebuild_function_decl_type (r);
> +  maybe_rebuild_function_decl_type (r, args);
>   
>     TREE_STATIC (r) = 0;
>     TREE_PUBLIC (r) = TREE_PUBLIC (t);
> @@ -15925,7 +15933,7 @@ tsubst_function_type (tree t,
>       }
>   
>     /* Construct a new type node and return it.  */
> -  return rebuild_function_or_method_type (t, return_type, arg_types,
> +  return rebuild_function_or_method_type (t, args, return_type, arg_types,
>   					  /*raises=*/NULL_TREE, complain);
>   }
>   
> --- gcc/testsuite/g++.dg/ext/attr-format4.C.jj	2024-08-01 17:44:35.492269816 +0200
> +++ gcc/testsuite/g++.dg/ext/attr-format4.C	2024-08-01 17:43:27.340127120 +0200
> @@ -0,0 +1,12 @@
> +// PR c++/116175
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wformat" }
> +
> +template <typename ...T>
> +int foo (T ...args, const char *fmt, ...)
> +[[gnu::format (printf, 1 + sizeof... (T), 2 + sizeof... (T))]];
> +
> +int a = foo <> ("%d", 1);
> +int b = foo <int, int, int, int, int> (1, 2, 3, 4, 5, "%d", 1);
> +int c = foo <> ("%f", 1);	// { dg-warning "format '%f' expects argument of type 'double', but argument 2 has type 'int'" }
> +int d = foo <int, int, int, int, int> (1, 2, 3, 4, 5, "%f", 1);	// { dg-warning "format '%f' expects argument of type 'double', but argument 7 has type 'int'" }
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/cp/pt.cc.jj	2024-07-31 14:38:54.405628645 +0200
+++ gcc/cp/pt.cc	2024-08-01 16:29:59.671779469 +0200
@@ -12219,6 +12219,8 @@  apply_late_template_attributes (tree *de
          to our attributes parameter.  */
       gcc_assert (*p == attributes);
     }
+  else if (FUNC_OR_METHOD_TYPE_P (*decl_p))
+    p = NULL;
   else
     {
       p = &TYPE_ATTRIBUTES (*decl_p);
@@ -12237,7 +12239,10 @@  apply_late_template_attributes (tree *de
   tree nondep = t;
 
   /* Apply any non-dependent attributes.  */
-  *p = nondep;
+  if (p)
+    *p = nondep;
+  else if (nondep)
+    *decl_p = cp_build_type_attribute_variant (*decl_p, nondep);
 
   if (nondep == attributes)
     return true;
@@ -14375,8 +14380,9 @@  lookup_explicit_specifier (tree v)
    identical to T.  */
 
 static tree
-rebuild_function_or_method_type (tree t, tree return_type, tree arg_types,
-				 tree raises, tsubst_flags_t complain)
+rebuild_function_or_method_type (tree t, tree args, tree return_type,
+				 tree arg_types, tree raises,
+				 tsubst_flags_t complain)
 {
   gcc_assert (FUNC_OR_METHOD_TYPE_P (t));
 
@@ -14409,7 +14415,9 @@  rebuild_function_or_method_type (tree t,
       new_type = build_method_type_directly (r, return_type,
 					     TREE_CHAIN (arg_types));
     }
-  new_type = cp_build_type_attribute_variant (new_type, TYPE_ATTRIBUTES (t));
+  if (!apply_late_template_attributes (&new_type, TYPE_ATTRIBUTES (t), 0,
+				       args, complain, NULL_TREE))
+    return error_mark_node;
 
   cp_ref_qualifier rqual = type_memfn_rqual (t);
   bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t);
@@ -14422,7 +14430,7 @@  rebuild_function_or_method_type (tree t,
    resolution for Core issues 1001/1322.  */
 
 static void
-maybe_rebuild_function_decl_type (tree decl)
+maybe_rebuild_function_decl_type (tree decl, tree args)
 {
   bool function_type_needs_rebuilding = false;
   if (tree parm_list = FUNCTION_FIRST_USER_PARM (decl))
@@ -14474,7 +14482,7 @@  maybe_rebuild_function_decl_type (tree d
     *q = void_list_node;
 
   TREE_TYPE (decl)
-    = rebuild_function_or_method_type (fntype,
+    = rebuild_function_or_method_type (fntype, args,
 				       TREE_TYPE (fntype), new_parm_type_list,
 				       TYPE_RAISES_EXCEPTIONS (fntype), tf_none);
 }
@@ -14657,7 +14665,7 @@  tsubst_function_decl (tree t, tree args,
   DECL_ARGUMENTS (r) = parms;
   DECL_RESULT (r) = NULL_TREE;
 
-  maybe_rebuild_function_decl_type (r);
+  maybe_rebuild_function_decl_type (r, args);
 
   TREE_STATIC (r) = 0;
   TREE_PUBLIC (r) = TREE_PUBLIC (t);
@@ -15925,7 +15933,7 @@  tsubst_function_type (tree t,
     }
 
   /* Construct a new type node and return it.  */
-  return rebuild_function_or_method_type (t, return_type, arg_types,
+  return rebuild_function_or_method_type (t, args, return_type, arg_types,
 					  /*raises=*/NULL_TREE, complain);
 }
 
--- gcc/testsuite/g++.dg/ext/attr-format4.C.jj	2024-08-01 17:44:35.492269816 +0200
+++ gcc/testsuite/g++.dg/ext/attr-format4.C	2024-08-01 17:43:27.340127120 +0200
@@ -0,0 +1,12 @@ 
+// PR c++/116175
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wformat" }
+
+template <typename ...T>
+int foo (T ...args, const char *fmt, ...)
+[[gnu::format (printf, 1 + sizeof... (T), 2 + sizeof... (T))]];
+
+int a = foo <> ("%d", 1);
+int b = foo <int, int, int, int, int> (1, 2, 3, 4, 5, "%d", 1);
+int c = foo <> ("%f", 1);	// { dg-warning "format '%f' expects argument of type 'double', but argument 2 has type 'int'" }
+int d = foo <int, int, int, int, int> (1, 2, 3, 4, 5, "%f", 1);	// { dg-warning "format '%f' expects argument of type 'double', but argument 7 has type 'int'" }