public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c: don't drop typedef information in casts
@ 2021-03-10  1:28 David Lamparter
  2021-03-10  1:46 ` David Lamparter
  0 siblings, 1 reply; 12+ messages in thread
From: David Lamparter @ 2021-03-10  1:28 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]


The TYPE_MAIN_VARIANT() here was, for casts to a typedef'd type name,
resulting in all information about the typedef's involvement getting
lost.  This drops necessary information for warnings and can make them
confusing or even misleading.  It also makes specialized warnings for
unspecified-size system types (pid_t, uid_t, ...) impossible.

gcc/c/ChangeLog:
2021-03-09  David Lamparter  <equinox@diac24.net>

        * c-typeck.c (build_c_cast): retain (unqualified) typedefs in
          casts rather than stripping down to basic type.
---
 gcc/c/c-typeck.c              | 11 +++++++----
 gcc/testsuite/gcc.dg/cast-5.c | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/cast-5.c


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-c-don-t-drop-typedef-information-in-casts.patch --]
[-- Type: text/x-patch; name="0001-c-don-t-drop-typedef-information-in-casts.patch", Size: 2669 bytes --]

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4e6d369c4c9c..0f67753be4d7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5816,6 +5816,7 @@ c_safe_function_type_cast_p (tree t1, tree t2)
 tree
 build_c_cast (location_t loc, tree type, tree expr)
 {
+  tree res_type;
   tree value;
 
   bool int_operands = EXPR_INT_CONST_OPERANDS (expr);
@@ -5836,7 +5837,9 @@ build_c_cast (location_t loc, tree type, tree expr)
   if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
     return build1 (NOP_EXPR, type, expr);
 
-  type = TYPE_MAIN_VARIANT (type);
+  /* rvalue - retain typedefs w/o qualifier, but use actual type for checks */
+  res_type = build_qualified_type (type, TYPE_UNQUALIFIED);
+  type = TYPE_MAIN_VARIANT (res_type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -5864,7 +5867,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		 "ISO C forbids casting nonscalar to the same type");
 
       /* Convert to remove any qualifiers from VALUE's type.  */
-      value = convert (type, value);
+      value = convert (res_type, value);
     }
   else if (TREE_CODE (type) == UNION_TYPE)
     {
@@ -6018,7 +6021,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		    " from %qT to %qT", otype, type);
 
       ovalue = value;
-      value = convert (type, value);
+      value = convert (res_type, value);
 
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST && !FLOAT_TYPE_P (otype))
@@ -6054,7 +6057,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		&& INTEGRAL_TYPE_P (TREE_TYPE (expr)))
 	       || TREE_CODE (expr) == REAL_CST
 	       || TREE_CODE (expr) == COMPLEX_CST)))
-      value = build1 (NOP_EXPR, type, value);
+      value = build1 (NOP_EXPR, res_type, value);
 
   /* If the expression has integer operands and so can occur in an
      unevaluated part of an integer constant expression, ensure the
diff --git a/gcc/testsuite/gcc.dg/cast-5.c b/gcc/testsuite/gcc.dg/cast-5.c
new file mode 100644
index 000000000000..dcd9b290653d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cast-5.c
@@ -0,0 +1,19 @@
+/* Test cast <> typedef interactions */
+/* Origin: David Lamparter <equinox@diac24.net> */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+typedef int typedefname;
+typedef volatile int qualtypedefname;
+
+extern int val;
+extern void f2(unsigned char arg);
+
+void
+f (void)
+{
+  /* -Wconversion just used to print out the actual type */
+
+  f2 ((typedefname) val); /* { dg-warning "typedefname" } */
+  f2 ((qualtypedefname) val); /* { dg-warning "qualtypedefname" } */ /* { dg-bogus "volatile" } */
+}

^ permalink raw reply	[flat|nested] 12+ messages in thread
* [PATCH] c: don't drop typedef information in casts
@ 2021-05-07 16:09 David Lamparter
  2021-05-18 11:13 ` David Lamparter
  0 siblings, 1 reply; 12+ messages in thread
From: David Lamparter @ 2021-05-07 16:09 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1177 bytes --]


The TYPE_MAIN_VARIANT() here was, for casts to a typedef'd type name,
resulting in all information about the typedef's involvement getting
lost.  This drops necessary information for warnings and can make them
confusing or even misleading.  It also makes specialized warnings for
unspecified-size system types (pid_t, uid_t, ...) impossible.

gcc/c/ChangeLog:
2021-03-09  David Lamparter  <equinox@diac24.net>

	PR c/99526
	* c-typeck.c (build_c_cast): retain (unqualified) typedefs in
	  casts rather than stripping down to basic type.
---
 gcc/c/c-typeck.c                    | 39 ++++++++++++++++++++++++++---
 gcc/testsuite/gcc.dg/cast-typedef.c | 35 ++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/cast-typedef.c
---

Hi GCC hackers,


now that gcc 12 is open for development, I'd like to submit this patch
for reconsideration.  I've already gone through a bit of feedback while
the gcc 11 release was happening, cf. here:
https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566513.html

I've repeated my testing (full bootstrap & make check on x86_64) and
found nothing changed.


Cheers,

-David


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-c-don-t-drop-typedef-information-in-casts.patch --]
[-- Type: text/x-patch; name="0001-c-don-t-drop-typedef-information-in-casts.patch", Size: 4406 bytes --]

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index fdc7bb6125c2..ba6014726a4b 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5876,6 +5876,7 @@ c_safe_function_type_cast_p (tree t1, tree t2)
 tree
 build_c_cast (location_t loc, tree type, tree expr)
 {
+  tree res_type, walk_type;
   tree value;
 
   bool int_operands = EXPR_INT_CONST_OPERANDS (expr);
@@ -5896,7 +5897,39 @@ build_c_cast (location_t loc, tree type, tree expr)
   if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
     return build1 (NOP_EXPR, type, expr);
 
+  /* Want to keep typedef information, but at the same time we need to strip
+     qualifiers for a proper rvalue.  Unfortunately, we don't know if any
+     qualifiers on a typedef are part of the typedef or were locally supplied.
+     So grab the original typedef and use that only if it has no qualifiers.
+     cf. cast-typedef testcase */
+
+  res_type = NULL;
+
+  for (walk_type = type;
+       walk_type && TYPE_NAME (walk_type)
+	 && TREE_CODE (TYPE_NAME (walk_type)) == TYPE_DECL;
+       walk_type = DECL_ORIGINAL_TYPE (TYPE_NAME (walk_type)))
+    {
+      tree walk_unqual, orig_type, orig_decl;
+
+      walk_unqual = build_qualified_type (walk_type, TYPE_UNQUALIFIED);
+
+      orig_decl = lookup_name (TYPE_IDENTIFIER (walk_type));
+      if (!orig_decl || TREE_CODE (orig_decl) != TYPE_DECL)
+	continue;
+      orig_type = TREE_TYPE (orig_decl);
+
+      if (walk_unqual == orig_type)
+	{
+	  res_type = walk_unqual;
+	  break;
+	}
+    }
+
   type = TYPE_MAIN_VARIANT (type);
+  if (!res_type)
+    res_type = type;
+  gcc_assert (TYPE_MAIN_VARIANT (res_type) == type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -5924,7 +5957,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		 "ISO C forbids casting nonscalar to the same type");
 
       /* Convert to remove any qualifiers from VALUE's type.  */
-      value = convert (type, value);
+      value = convert (res_type, value);
     }
   else if (TREE_CODE (type) == UNION_TYPE)
     {
@@ -6078,7 +6111,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		    " from %qT to %qT", otype, type);
 
       ovalue = value;
-      value = convert (type, value);
+      value = convert (res_type, value);
 
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST && !FLOAT_TYPE_P (otype))
@@ -6114,7 +6147,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 		&& INTEGRAL_TYPE_P (TREE_TYPE (expr)))
 	       || TREE_CODE (expr) == REAL_CST
 	       || TREE_CODE (expr) == COMPLEX_CST)))
-      value = build1 (NOP_EXPR, type, value);
+      value = build1 (NOP_EXPR, res_type, value);
 
   /* If the expression has integer operands and so can occur in an
      unevaluated part of an integer constant expression, ensure the
diff --git a/gcc/testsuite/gcc.dg/cast-typedef.c b/gcc/testsuite/gcc.dg/cast-typedef.c
new file mode 100644
index 000000000000..3058e5a0b190
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cast-typedef.c
@@ -0,0 +1,35 @@
+/* Test cast <> typedef interactions */
+/* Origin: David Lamparter <equinox@diac24.net> */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+typedef int typedefname;
+typedef volatile int qual1;
+typedef volatile typedefname qual2;
+
+extern int val;
+extern void f2(unsigned char arg);
+
+void
+f (void)
+{
+  /* -Wconversion just used to print out the actual type */
+
+  f2 ((typedefname) val); /* { dg-warning "typedefname" } */
+  f2 ((volatile typedefname) val); /* { dg-warning "typedefname" } */
+  f2 ((qual1) val); /* { dg-warning "int" } */
+  f2 ((qual2) val); /* { dg-warning "typedefname" } */
+
+  /* { dg-bogus "volatile" "qualifiers should be stripped" { target { "*-*-*" } } 19  } */
+  /* { dg-bogus "volatile" "qualifiers should be stripped" { target { "*-*-*" } } 20  } */
+  /* { dg-bogus "volatile" "qualifiers should be stripped" { target { "*-*-*" } } 21  } */
+
+  /* { dg-bogus "qual1" "typedef with qualifier should not be used" { target { "*-*-*" } } 20  } */
+  /* { dg-bogus "qual2" "typedef with qualifier should not be used" { target { "*-*-*" } } 21  } */
+
+  /* shadow "typedefname" & make sure it's not used */
+  typedef short typedefname;
+  f2 ((qual2) val); /* { dg-warning "int" } */
+
+  /* { dg-bogus "typedefname" "retaining a shadowed typedef would be confusing" { target { "*-*-*" } } 32 } */
+}

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-05-18 20:32 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-10  1:28 [PATCH] c: don't drop typedef information in casts David Lamparter
2021-03-10  1:46 ` David Lamparter
2021-03-10 17:01   ` Martin Sebor
2021-03-10 19:02     ` David Lamparter
2021-03-10 19:06       ` David Lamparter
2021-03-12  3:08       ` [PATCH v2] " David Lamparter
2021-03-12  8:35         ` Jakub Jelinek
2021-03-15 18:14           ` David Lamparter
2021-03-15 18:16             ` [PATCH v3] " David Lamparter
2021-05-07 16:09 [PATCH] " David Lamparter
2021-05-18 11:13 ` David Lamparter
2021-05-18 20:32   ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).