Patchwork C++ PATCH for c++/50207 (ICE on bogus decimal::decimal32)

login
register
mail settings
Submitter Jason Merrill
Date Aug. 30, 2011, 4:27 a.m.
Message ID <4E5C66C4.1020403@redhat.com>
Download mbox | patch
Permalink /patch/112176/
State New
Headers show

Comments

Jason Merrill - Aug. 30, 2011, 4:27 a.m.
The DFP classes are treated as transparent aggregates, so they get 
mangled and passed like their first field.  In the testcase it is 
defined to have a base class, so the first field is an artificial base 
field, which doesn't make any sense.

Tested x86_64-pc-linux-gnu, applying to trunk.
Peter Bergner - Aug. 30, 2011, 9:32 p.m.
On Tue, 2011-08-30 at 00:27 -0400, Jason Merrill wrote:
> The DFP classes are treated as transparent aggregates, so they get 
> mangled and passed like their first field.  In the testcase it is 
> defined to have a base class, so the first field is an artificial base 
> field, which doesn't make any sense.
> 
> Tested x86_64-pc-linux-gnu, applying to trunk.

Thanks for fixing this Jason!  The same error also occurs on 4.6.
Do you plan on fixing it there too?

Peter

Patch

commit a32242269caefe41d24777d21920775b464ba938
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Aug 29 10:55:05 2011 -0400

    	PR c++/50207
    	* class.c (finish_struct_1): Complain if the first field is
    	artificial.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 89063ca..ca0529d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5796,10 +5796,25 @@  finish_struct_1 (tree t)
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
 
-  if (TYPE_TRANSPARENT_AGGR (t) && first_field (t) == NULL_TREE)
+  if (TYPE_TRANSPARENT_AGGR (t))
     {
-      error ("type transparent class %qT does not have any fields", t);
-      TYPE_TRANSPARENT_AGGR (t) = 0;
+      tree field = first_field (t);
+      if (field == NULL_TREE || error_operand_p (field))
+	{
+	  error ("type transparent class %qT does not have any fields", t);
+	  TYPE_TRANSPARENT_AGGR (t) = 0;
+	}
+      else if (DECL_ARTIFICIAL (field))
+	{
+	  if (DECL_FIELD_IS_BASE (field))
+	    error ("type transparent class %qT has base classes", t);
+	  else
+	    {
+	      gcc_checking_assert (DECL_VIRTUAL_P (field));
+	      error ("type transparent class %qT has virtual functions", t);
+	    }
+	  TYPE_TRANSPARENT_AGGR (t) = 0;
+	}
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/dfp/base.C b/gcc/testsuite/g++.dg/dfp/base.C
new file mode 100644
index 0000000..3e5dc50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/dfp/base.C
@@ -0,0 +1,23 @@ 
+// PR c++/50207
+// { dg-do compile }
+
+namespace std
+{
+  namespace decimal
+  {
+    template <class _Fmt> struct _FmtTraits;
+    class decimal32;
+    template <> struct _FmtTraits <decimal32>
+    {
+      static const long _NumBytes = 4UL;
+    };
+    template <class _Tr> class _DecBase
+    {
+      unsigned char _Bytes[_Tr::_NumBytes];
+    };
+    class decimal32 : public _DecBase <_FmtTraits <decimal32> >	// { dg-error "has base" }
+    {
+      decimal32 () { }
+    };
+  }
+}