This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RFC: DWARF2 vs. qualified array types



PR1657 is one of those bugs that shouldn't exist: turning on -ggdb
causes the C++ front-end to emit an error message where it doesn't
otherwise.

In detail:

  - modified_type_die contains this code:

      type = build_type_variant (type, is_const_type, is_volatile_type);

  - If type is an ARRAY_TYPE, this is incorrect for C++.  (As in C,
    the meaning of `const int[4]' is that you hvae an array of
    `const ints', not that you have a `const' version of `int [4]'.)
    There is no such thing as a qualified array type in C++.

  - The C++ front-end doesn't check for these bogus types and 
    ignore them because they shouldn't exist.  So, later, when we
    need an `int[4]' we decide that the weird const-qualified version
    is what we want.  But then we notice later that it's not.

There are several problems here:

  - Ideally, dwarf2out wouldn't be creating trees.  The
    front-end should create trees, not the debugging generation code.

  - If it *does* create trees, it shouldn't chain them into otherwise
    accessible trees.  Calling build_type_variant creates a type that
    is chained, via TYPE_MAIN_VARIANT, to other types, and so it
    is visible to the rest of the compiler later.

  - More subtly, we have a global function (build_type_variant)
    that doesn't do the right thing for all languages, but not
    everyone can be reasonably expected to know this.  This is again
    where we desparately need object-orientation, modules, or some
    other kind of interface hiding.  It would be ideal if each
    front-end could replace build_type_variant with an appropriate
    function, and then code like this would probably just work,
    despite the caveats above.

Anyhow, here's my attempt at a patch, which does indeed fix the
test-case in question.  

However, I can't quite convince myself that we'll still get the right
DWARF2 output.  I'd appreciate it if Jason or Jim (or someone else
expert in the area) could look at the patch.  I intend to check it in
(even without such an opinion) in an hour or two -- it is certainly
better to generate slightly incorrect debug information than to refuse
to compile legal code -- but I would like to avoid both eventualities.

Thanks, 

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.242.2.5
diff -c -p -r1.242.2.5 dwarf2out.c
*** dwarf2out.c	2001/04/03 01:46:20	1.242.2.5
--- dwarf2out.c	2001/04/11 19:46:05
*************** modified_type_die (type, is_const_type, 
*** 7522,7543 ****
  
    if (code != ERROR_MARK)
      {
!       type = build_type_variant (type, is_const_type, is_volatile_type);
  
!       mod_type_die = lookup_type_die (type);
!       if (mod_type_die)
! 	return mod_type_die;
  
        /* Handle C typedef types.  */
!       if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
! 	  && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
  	{
! 	  tree dtype = TREE_TYPE (TYPE_NAME (type));
! 	  if (type == dtype)
  	    {
  	      /* For a named type, use the typedef.  */
! 	      gen_type_die (type, context_die);
! 	      mod_type_die = lookup_type_die (type);
  	    }
  
  	  else if (is_const_type < TYPE_READONLY (dtype)
--- 7522,7556 ----
  
    if (code != ERROR_MARK)
      {
!       tree qualified_type;
  
!       /* See if we already have the appropriately qualified variant of
! 	 this type.  */
!       qualified_type 
! 	= get_qualified_type (type,
! 			      ((is_const_type ? TYPE_QUAL_CONST : 0)
! 			       | (is_volatile_type 
! 				  ? TYPE_QUAL_VOLATILE : 0)));
!       /* If we do, then we can just use its DIE, if it exists.  */
!       if (qualified_type)
! 	{
! 	  mod_type_die = lookup_type_die (qualified_type);
! 	  if (mod_type_die)
! 	    return mod_type_die;
! 	}
  
        /* Handle C typedef types.  */
!       if (qualified_type && TYPE_NAME (qualified_type) 
! 	  && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
! 	  && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
  	{
! 	  tree type_name = TYPE_NAME (qualified_type);
! 	  tree dtype = TREE_TYPE (type_name);
! 	  if (qualified_type == dtype)
  	    {
  	      /* For a named type, use the typedef.  */
! 	      gen_type_die (qualified_type, context_die);
! 	      mod_type_die = lookup_type_die (qualified_type);
  	    }
  
  	  else if (is_const_type < TYPE_READONLY (dtype)
*************** modified_type_die (type, is_const_type, 
*** 7545,7551 ****
  	    /* cv-unqualified version of named type.  Just use the unnamed
  	       type to which it refers.  */
  	    mod_type_die
! 	      = modified_type_die (DECL_ORIGINAL_TYPE (TYPE_NAME (type)),
  				   is_const_type, is_volatile_type,
  				   context_die);
  	  /* Else cv-qualified version of named type; fall through.  */
--- 7558,7564 ----
  	    /* cv-unqualified version of named type.  Just use the unnamed
  	       type to which it refers.  */
  	    mod_type_die
! 	      = modified_type_die (DECL_ORIGINAL_TYPE (type_name),
  				   is_const_type, is_volatile_type,
  				   context_die);
  	  /* Else cv-qualified version of named type; fall through.  */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.185.2.4
diff -c -p -r1.185.2.4 tree.c
*** tree.c	2001/03/20 22:03:34	1.185.2.4
--- tree.c	2001/04/11 19:46:06
*************** set_type_quals (type, type_quals)
*** 2993,3023 ****
    TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
  }
  
! /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
!    the same kind of data as TYPE describes.  Variants point to the
!    "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
!    and it points to a chain of other variants so that duplicate
!    variants are never made.  Only main variants should ever appear as
!    types of expressions.  */
  
  tree
! build_qualified_type (type, type_quals)
       tree type;
       int type_quals;
  {
!   register tree t;
  
    /* Search the chain of variants to see if there is already one there just
       like the one we need to have.  If so, use that existing one.  We must
       preserve the TYPE_NAME, since there is code that depends on this.  */
- 
    for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
      if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
        return t;
  
-   /* We need a new one.  */
-   t = build_type_copy (type);
-   set_type_quals (t, type_quals);
    return t;
  }
  
--- 2993,3039 ----
    TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
  }
  
! /* Return a version of the TYPE, qualified as indicated by the
!    TYPE_QUALS, if one exists.  If no qualified version exists yet,
!    return NULL_TREE.  */
  
  tree
! get_qualified_type (type, type_quals)
       tree type;
       int type_quals;
  {
!   tree t;
  
    /* Search the chain of variants to see if there is already one there just
       like the one we need to have.  If so, use that existing one.  We must
       preserve the TYPE_NAME, since there is code that depends on this.  */
    for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
      if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
        return t;
+ 
+   return NULL_TREE;
+ }
+ 
+ /* Like get_qualified_type, but creates the type if it does not
+    exist.  This function never returns NULL_TREE.  */
+ 
+ tree
+ build_qualified_type (type, type_quals)
+      tree type;
+      int type_quals;
+ {
+   tree t;
+ 
+   /* See if we already have the appropriate qualified variant.  */
+   t = get_qualified_type (type, type_quals);
+ 
+   /* If not, build it.  */
+   if (!t)
+     {
+       t = build_type_copy (type);
+       set_type_quals (t, type_quals);
+     }
  
    return t;
  }
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.223.2.7
diff -c -p -r1.223.2.7 tree.h
*** tree.h	2001/03/27 04:41:16	1.223.2.7
--- tree.h	2001/04/11 19:46:07
*************** extern tree lookup_attribute		PARAMS ((c
*** 2071,2082 ****
  
  extern tree merge_attributes		PARAMS ((tree, tree));
  
! /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
!    the same kind of data as TYPE describes.  Variants point to the
!    "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
!    and it points to a chain of other variants so that duplicate
!    variants are never made.  Only main variants should ever appear as
!    types of expressions.  */
  
  extern tree build_qualified_type        PARAMS ((tree, int));
  
--- 2071,2084 ----
  
  extern tree merge_attributes		PARAMS ((tree, tree));
  
! /* Return a version of the TYPE, qualified as indicated by the
!    TYPE_QUALS, if one exists.  If no qualified version exists yet,
!    return NULL_TREE.  */
! 
! extern tree get_qualified_type          PARAMS ((tree, int));
! 
! /* Like get_qualified_type, but creates the type if it does not
!    exist.  This function never returns NULL_TREE.  */
  
  extern tree build_qualified_type        PARAMS ((tree, int));
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]