diff mbox series

[C] Fix thinko in new warning on type punning for storage order purposes

Message ID 12784528.uLZWGnKmhe@fomalhaut
State New
Headers show
Series [C] Fix thinko in new warning on type punning for storage order purposes | expand

Commit Message

Eric Botcazou June 6, 2021, 9:43 a.m. UTC
I obviously forgot that in C, unlike in Ada, the storage order of arrays is 
that of their component type, so you need to look at it when deciding to warn.
The bug reporter also complains about a bogus warning on the assignment of a 
pointer returned by alloca or malloc, so this also fixes that.

Tested on x86-64/Linux, applied on the mainline as obvious.


2021-06-06  Eric Botcazou  <ebotcazou@adacore.com>

	PR c/100920
	* c-decl.c (finish_struct): Fix thinko in previous change.
	* c-typeck.c (convert_for_assignment): Do not warn on pointer
	assignment and initialization for storage order purposes if the
	RHS is a call to a DECL_IS_MALLOC function.


2021-06-06  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.dg/sso-14.c: New test.
diff mbox series

Patch

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 28f851b9d0b..a86792bbe06 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -8854,12 +8854,21 @@  finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 	    }
 	}
 
+      /* Warn on problematic type punning for storage order purposes.  */
       if (TREE_CODE (t) == UNION_TYPE
-	  && AGGREGATE_TYPE_P (TREE_TYPE (field))
-	  && TYPE_REVERSE_STORAGE_ORDER (t)
-	     != TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (field)))
-	warning_at (DECL_SOURCE_LOCATION (field), OPT_Wscalar_storage_order,
-		    "type punning toggles scalar storage order");
+	  && TREE_CODE (field) == FIELD_DECL
+	  && AGGREGATE_TYPE_P (TREE_TYPE (field)))
+	{
+	  tree ftype = TREE_TYPE (field);
+	  if (TREE_CODE (ftype) == ARRAY_TYPE)
+	    ftype = strip_array_types (ftype);
+	  if (RECORD_OR_UNION_TYPE_P (ftype)
+	      && TYPE_REVERSE_STORAGE_ORDER (ftype)
+		 != TYPE_REVERSE_STORAGE_ORDER (t))
+	    warning_at (DECL_SOURCE_LOCATION (field),
+			OPT_Wscalar_storage_order,
+			"type punning toggles scalar storage order");
+	}
     }
 
   /* Now we have the truly final field list.
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index be3f4f09f6e..daa2e12a25f 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -7295,6 +7295,8 @@  convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	  && (AGGREGATE_TYPE_P (ttl) && TYPE_REVERSE_STORAGE_ORDER (ttl))
 	     != (AGGREGATE_TYPE_P (ttr) && TYPE_REVERSE_STORAGE_ORDER (ttr)))
 	{
+	  tree t;
+
 	  switch (errtype)
 	  {
 	  case ic_argpass:
@@ -7307,14 +7309,23 @@  convert_for_assignment (location_t location, location_t expr_loc, tree type,
 			  "scalar storage order", parmnum, rname);
 	    break;
 	  case ic_assign:
-	    warning_at (location, OPT_Wscalar_storage_order,
-			"assignment to %qT from pointer type %qT with "
-			"incompatible scalar storage order", type, rhstype);
+	    /* Do not warn if the RHS is a call to a function that returns a
+	       pointer that is not an alias.  */
+	    if (TREE_CODE (rhs) != CALL_EXPR
+		|| (t = get_callee_fndecl (rhs)) == NULL_TREE
+		|| !DECL_IS_MALLOC (t))
+	      warning_at (location, OPT_Wscalar_storage_order,
+			  "assignment to %qT from pointer type %qT with "
+			  "incompatible scalar storage order", type, rhstype);
 	    break;
 	  case ic_init:
-	    warning_at (location, OPT_Wscalar_storage_order,
-			"initialization of %qT from pointer type %qT with "
-			"incompatible scalar storage order", type, rhstype);
+	    /* Likewise.  */
+	    if (TREE_CODE (rhs) != CALL_EXPR
+		|| (t = get_callee_fndecl (rhs)) == NULL_TREE
+		|| !DECL_IS_MALLOC (t))
+	      warning_at (location, OPT_Wscalar_storage_order,
+			  "initialization of %qT from pointer type %qT with "
+			  "incompatible scalar storage order", type, rhstype);
 	    break;
 	  case ic_return:
 	    warning_at (location, OPT_Wscalar_storage_order,