Patchwork [C++] PR 44625, v2

login
register
mail settings
Submitter Paolo Carlini
Date July 5, 2010, 8:45 p.m.
Message ID <4C32446B.90807@oracle.com>
Download mbox | patch
Permalink /patch/57930/
State New
Headers show

Comments

Paolo Carlini - July 5, 2010, 8:45 p.m.
Hi again,

this is my second try: the idea is avoiding completely creating
COMPONENT_REFs with a null operand 1, as suggested by Jason. I also
tidied a bit the original testcase and added a second for anonymous
union inside anonymous union. About error17.C, we now emit one less
diagnostic message, similarly to ICC, turns out.

Tested x86_64-linux. Is this one better? Mainline only, in my opinion...

Paolo.

////////////////////
/cp
2010-07-05  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44625
	* decl2.c (build_anon_union_vars): Avoid creating COMPONENT_REFs
	with a null operand 1; tidy, reformat.

/testsuite
2010-07-05  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44625
	* g++.dg/template/crash102.C: New.
	* g++.dg/template/crash103.C: Likewise.
	* g++.dg/template/error17.C: Adjust.
Jason Merrill - Aug. 17, 2010, 3:44 p.m.
On 07/05/2010 04:45 PM, Paolo Carlini wrote:
> +      name = DECL_NAME (field);
> +
>         if (processing_template_decl)
> -	ref = build_min_nt (COMPONENT_REF, object,
> -			    DECL_NAME (field), NULL_TREE);
> +	{
> +	  if (name)
> +	    ref = build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
> +	}

How about just

if (!name) continue;

Jason

Patch

Index: testsuite/g++.dg/template/crash102.C
===================================================================
--- testsuite/g++.dg/template/crash102.C	(revision 0)
+++ testsuite/g++.dg/template/crash102.C	(revision 0)
@@ -0,0 +1,19 @@ 
+// PR c++/44625
+// { dg-do compile }
+// { dg-options "" }
+
+template<typename FP_> struct Vec {
+    Vec& operator^=(Vec& rhs)     {
+        union {
+            struct {FP_ x,y,z;};
+        }; // { dg-error "anonymous struct" }
+        y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" }
+	return *this;
+    }
+    Vec& operator^(Vec& rhs) {
+        return Vec(*this)^=rhs; // { dg-message "instantiated" }
+    }
+};
+Vec<double> v;
+Vec<double> V;
+Vec<double> c = v^V;  // { dg-message "instantiated" }
Index: testsuite/g++.dg/template/error17.C
===================================================================
--- testsuite/g++.dg/template/error17.C	(revision 161841)
+++ testsuite/g++.dg/template/error17.C	(working copy)
@@ -4,7 +4,6 @@  template <typename T>
 void
 foo()
 {
-  union { struct { }; }; // { dg-error "prohibits anonymous struct" "anon" }
+  union { struct { }; }; // { dg-error "prohibits anonymous struct" }
   // { dg-error "not inside" "not inside" { target *-*-* } 7 }
-  // { dg-warning "no members" "no members" { target *-*-* } 7 }
 }
Index: testsuite/g++.dg/template/crash103.C
===================================================================
--- testsuite/g++.dg/template/crash103.C	(revision 0)
+++ testsuite/g++.dg/template/crash103.C	(revision 0)
@@ -0,0 +1,19 @@ 
+// PR c++/44625
+// { dg-do compile }
+// { dg-options "" }
+
+template<typename FP_> struct Vec {
+    Vec& operator^=(Vec& rhs)     {
+        union {
+            union {FP_ x,y,z;};
+        };
+        y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" }
+	return *this;
+    }
+    Vec& operator^(Vec& rhs) {
+        return Vec(*this)^=rhs; // { dg-message "instantiated" }
+    }
+};
+Vec<double> v;
+Vec<double> V;
+Vec<double> c = v^V;  // { dg-message "instantiated" }
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 161844)
+++ cp/decl2.c	(working copy)
@@ -1319,40 +1319,50 @@  build_anon_union_vars (tree type, tree object)
   if (TREE_CODE (type) != UNION_TYPE)
     error ("anonymous struct not inside named type");
 
+  if (!object)
+    return error_mark_node;
+
   for (field = TYPE_FIELDS (type);
        field != NULL_TREE;
        field = TREE_CHAIN (field))
     {
       tree decl;
-      tree ref;
+      tree ref = NULL_TREE;
+      tree name;
 
       if (DECL_ARTIFICIAL (field))
 	continue;
       if (TREE_CODE (field) != FIELD_DECL)
 	{
-	  permerror (input_location, "%q+#D invalid; an anonymous union can only "
-		     "have non-static data members", field);
+	  permerror (input_location, "%q+#D invalid; an anonymous union can "
+		     "only have non-static data members", field);
 	  continue;
 	}
 
       if (TREE_PRIVATE (field))
-	permerror (input_location, "private member %q+#D in anonymous union", field);
+	permerror (input_location, "private member %q+#D in anonymous union",
+		   field);
       else if (TREE_PROTECTED (field))
-	permerror (input_location, "protected member %q+#D in anonymous union", field);
+	permerror (input_location, "protected member %q+#D in anonymous union",
+		   field);
 
+      name = DECL_NAME (field);
+
       if (processing_template_decl)
-	ref = build_min_nt (COMPONENT_REF, object,
-			    DECL_NAME (field), NULL_TREE);
+	{
+	  if (name)
+	    ref = build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
+	}
       else
 	ref = build_class_member_access_expr (object, field, NULL_TREE,
 					      false, tf_warning_or_error);
 
-      if (DECL_NAME (field))
+      if (name)
 	{
 	  tree base;
 
 	  decl = build_decl (input_location,
-			     VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+			     VAR_DECL, name, TREE_TYPE (field));
 	  DECL_ANON_UNION_VAR_P (decl) = 1;
 	  DECL_ARTIFICIAL (decl) = 1;