public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/ieee)] c: Handle C_TYPE_INCOMPLETE_VARS even for ENUMERAL_TYPEs [PR94172]
@ 2020-03-18 17:22 Michael Meissner
  0 siblings, 0 replies; only message in thread
From: Michael Meissner @ 2020-03-18 17:22 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:046c58907ec85884042d9937ea9c25ef9fe57b1d

commit 046c58907ec85884042d9937ea9c25ef9fe57b1d
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Mar 17 22:32:34 2020 +0100

    c: Handle C_TYPE_INCOMPLETE_VARS even for ENUMERAL_TYPEs [PR94172]
    
    The following testcases ICE, because they contain extern variable
    declarations with incomplete enum types that is later completed and after
    that those variables are accessed.  The ICEs are because the vars then may have
    incorrect DECL_MODE etc., e.g. in the first case the var has SImode
    DECL_MODE (the guessed mode for the enum), but the enum then actually has
    DImode because its enumerators don't fit into unsigned int.
    
    The following patch fixes it by using C_TYPE_INCOMPLETE_VARS not just on
    incomplete struct/union types, but also incomplete enum types.
    TYPE_VFIELD can't be used as it is TYPE_MIN_VALUE on ENUMERAL_TYPE,
    thankfully TYPE_LANG_SLOT_1 has been used in the C FE only on
    FUNCTION_TYPEs.
    
    2020-03-17  Jakub Jelinek  <jakub@redhat.com>
    
            PR c/94172
            * c-tree.h (C_TYPE_INCOMPLETE_VARS): Define to TYPE_LANG_SLOT_1
            instead of TYPE_VFIELD, and support it on {RECORD,UNION,ENUMERAL}_TYPE.
            (TYPE_ACTUAL_ARG_TYPES): Check that it is only used on FUNCTION_TYPEs.
            * c-decl.c (pushdecl): Push C_TYPE_INCOMPLETE_VARS also to
            ENUMERAL_TYPEs.
            (finish_incomplete_vars): New function, moved from finish_struct.  Use
            relayout_decl instead of layout_decl.
            (finish_struct): Remove obsolete comment about C_TYPE_INCOMPLETE_VARS
            being TYPE_VFIELD.  Use finish_incomplete_vars.
            (finish_enum): Clear C_TYPE_INCOMPLETE_VARS.  Call
            finish_incomplete_vars.
            * c-typeck.c (c_build_qualified_type): Clear C_TYPE_INCOMPLETE_VARS
            also on ENUMERAL_TYPEs.
    
            * gcc.dg/pr94172-1.c: New test.
            * gcc.dg/pr94172-2.c: New test.

Diff:
---
 gcc/c/ChangeLog                  | 17 ++++++++++++++
 gcc/c/c-decl.c                   | 50 ++++++++++++++++++++++------------------
 gcc/c/c-tree.h                   | 12 ++++++----
 gcc/c/c-typeck.c                 |  3 ++-
 gcc/testsuite/ChangeLog          |  4 ++++
 gcc/testsuite/gcc.dg/pr94172-1.c | 12 ++++++++++
 gcc/testsuite/gcc.dg/pr94172-2.c | 19 +++++++++++++++
 7 files changed, 89 insertions(+), 28 deletions(-)

diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 240859e9fed..25f8f5b6b7b 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,20 @@
+2020-03-17  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/94172
+	* c-tree.h (C_TYPE_INCOMPLETE_VARS): Define to TYPE_LANG_SLOT_1
+	instead of TYPE_VFIELD, and support it on {RECORD,UNION,ENUMERAL}_TYPE.
+	(TYPE_ACTUAL_ARG_TYPES): Check that it is only used on FUNCTION_TYPEs.
+	* c-decl.c (pushdecl): Push C_TYPE_INCOMPLETE_VARS also to
+	ENUMERAL_TYPEs.
+	(finish_incomplete_vars): New function, moved from finish_struct.  Use
+	relayout_decl instead of layout_decl.
+	(finish_struct): Remove obsolete comment about C_TYPE_INCOMPLETE_VARS
+	being TYPE_VFIELD.  Use finish_incomplete_vars.
+	(finish_enum): Clear C_TYPE_INCOMPLETE_VARS.  Call
+	finish_incomplete_vars.
+	* c-typeck.c (c_build_qualified_type): Clear C_TYPE_INCOMPLETE_VARS
+	also on ENUMERAL_TYPEs.
+
 2020-03-16  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c/94179
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 87a0734b715..ed5163dd465 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3312,7 +3312,8 @@ pushdecl (tree x)
 	element = TREE_TYPE (element);
       element = TYPE_MAIN_VARIANT (element);
 
-      if (RECORD_OR_UNION_TYPE_P (element)
+      if ((RECORD_OR_UNION_TYPE_P (element)
+	   || TREE_CODE (element) == ENUMERAL_TYPE)
 	  && (TREE_CODE (x) != TYPE_DECL
 	      || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
 	  && !COMPLETE_TYPE_P (element))
@@ -8354,6 +8355,26 @@ field_decl_cmp (const void *x_p, const void *y_p)
   return 1;
 }
 
+/* If this structure or union completes the type of any previous
+   variable declaration, lay it out and output its rtl.  */
+static void
+finish_incomplete_vars (tree incomplete_vars, bool toplevel)
+{
+  for (tree x = incomplete_vars; x; x = TREE_CHAIN (x))
+    {
+      tree decl = TREE_VALUE (x);
+      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+	layout_array_type (TREE_TYPE (decl));
+      if (TREE_CODE (decl) != TYPE_DECL)
+	{
+	  relayout_decl (decl);
+	  if (c_dialect_objc ())
+	    objc_check_decl (decl);
+	  rest_of_decl_compilation (decl, toplevel, 0);
+	}
+    }
+}
+
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
@@ -8612,13 +8633,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       warning_at (loc, 0, "union cannot be made transparent");
     }
 
-  /* Note: C_TYPE_INCOMPLETE_VARS overloads TYPE_VFIELD which is used
-     in dwarf2out via rest_of_decl_compilation below and means
-     something totally different.  Since we will be clearing
-     C_TYPE_INCOMPLETE_VARS shortly after we iterate through them,
-     clear it ahead of time and avoid problems in dwarf2out.  Ideally,
-     C_TYPE_INCOMPLETE_VARS should use some language specific
-     node.  */
   tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {
@@ -8639,21 +8653,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
-  /* If this structure or union completes the type of any previous
-     variable declaration, lay it out and output its rtl.  */
-  for (x = incomplete_vars; x; x = TREE_CHAIN (x))
-    {
-      tree decl = TREE_VALUE (x);
-      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-	layout_array_type (TREE_TYPE (decl));
-      if (TREE_CODE (decl) != TYPE_DECL)
-	{
-	  layout_decl (decl, 0);
-	  if (c_dialect_objc ())
-	    objc_check_decl (decl);
-	  rest_of_decl_compilation (decl, toplevel, 0);
-	}
-    }
+  finish_incomplete_vars (incomplete_vars, toplevel);
 
   /* If we're inside a function proper, i.e. not file-scope and not still
      parsing parameters, then arrange for the size of a variable sized type
@@ -8932,8 +8932,10 @@ finish_enum (tree enumtype, tree values, tree attributes)
   TYPE_LANG_SPECIFIC (enumtype) = lt;
 
   /* Fix up all variant types of this enum type.  */
+  tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (enumtype));
   for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
     {
+      C_TYPE_INCOMPLETE_VARS (tem) = NULL_TREE;
       if (tem == enumtype)
 	continue;
       TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
@@ -8952,6 +8954,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, toplevel);
 
+  finish_incomplete_vars (incomplete_vars, toplevel);
+
   /* If this enum is defined inside a struct, add it to
      struct_types.  */
   if (warn_cxx_compat
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 71229927cb6..364d7e03398 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -38,9 +38,12 @@ along with GCC; see the file COPYING3.  If not see
    nonzero if the definition of the type has already started.  */
 #define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
 
-/* In an incomplete RECORD_TYPE or UNION_TYPE, a list of variable
-   declarations whose type would be completed by completing that type.  */
-#define C_TYPE_INCOMPLETE_VARS(TYPE) TYPE_VFIELD (TYPE)
+/* In an incomplete RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE, a list of
+   variable declarations whose type would be completed by completing
+   that type.  */
+#define C_TYPE_INCOMPLETE_VARS(TYPE) \
+  TYPE_LANG_SLOT_1 (TREE_CHECK4 (TYPE, RECORD_TYPE, UNION_TYPE, \
+				 QUAL_UNION_TYPE, ENUMERAL_TYPE))
 
 /* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
    keyword.  C_RID_CODE (node) is then the RID_* value of the keyword.  */
@@ -108,7 +111,8 @@ along with GCC; see the file COPYING3.  If not see
 /* For FUNCTION_TYPE, a hidden list of types of arguments.  The same as
    TYPE_ARG_TYPES for functions with prototypes, but created for functions
    without prototypes.  */
-#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
+#define TYPE_ACTUAL_ARG_TYPES(NODE) \
+  TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE))
 
 /* For a CONSTRUCTOR, whether some initializer contains a
    subexpression meaning it is not a constant expression.  */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 490d8fc5f4a..385bf3a1c7b 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -15207,7 +15207,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type,
 		   : build_qualified_type (type, type_quals));
   /* A variant type does not inherit the list of incomplete vars from the
      type main variant.  */
-  if (RECORD_OR_UNION_TYPE_P (var_type)
+  if ((RECORD_OR_UNION_TYPE_P (var_type)
+       || TREE_CODE (var_type) == ENUMERAL_TYPE)
       && TYPE_MAIN_VARIANT (var_type) != var_type)
     C_TYPE_INCOMPLETE_VARS (var_type) = 0;
   return var_type;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 45fb82941cc..dae22c27764 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2020-03-17  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c/94172
+	* gcc.dg/pr94172-1.c: New test.
+	* gcc.dg/pr94172-2.c: New test.
+
 	PR c++/90995
 	* g++.dg/cpp0x/enum40.C: New test.
 
diff --git a/gcc/testsuite/gcc.dg/pr94172-1.c b/gcc/testsuite/gcc.dg/pr94172-1.c
new file mode 100644
index 00000000000..12f84af42dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94172-1.c
@@ -0,0 +1,12 @@
+/* PR c/94172 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern enum E e;
+enum E { l = 0x100000000ULL };
+
+unsigned long long
+foo (void)
+{
+  return e;
+}
diff --git a/gcc/testsuite/gcc.dg/pr94172-2.c b/gcc/testsuite/gcc.dg/pr94172-2.c
new file mode 100644
index 00000000000..bb7b060d7b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94172-2.c
@@ -0,0 +1,19 @@
+/* PR c/94172 */
+/* { dg-do compile } */
+/* { dg-options "-Os -g -fshort-enums" } */
+
+extern enum E e;
+extern void bar (int a);
+enum E { F };
+
+void
+foo (int a)
+{
+  int l = e;
+  if (a)
+    {
+      __asm volatile ("nop");
+      l = 0;
+    }
+  bar (l);
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-03-18 17:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-18 17:22 [gcc(refs/users/meissner/heads/ieee)] c: Handle C_TYPE_INCOMPLETE_VARS even for ENUMERAL_TYPEs [PR94172] Michael Meissner

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).