This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

[gccgo] Fix for type assertions


This gccgo patch does three things.  It fixes type assertions for global
variables, by not creating an unnecessary temporary variable.  It fixes
the unsafe.Pointer checks for type assertions, by only permitting a
conversion to uintptr.  It gives an error for impossible type assertions
that can never be satisfied.  Committed to gccgo  branch.

Ian

diff -r 1c23caeb2ccd go/expressions.cc
--- a/go/expressions.cc	Wed Sep 08 16:24:55 2010 -0700
+++ b/go/expressions.cc	Wed Sep 08 17:35:24 2010 -0700
@@ -704,25 +704,16 @@
   tree val = build3(COMPONENT_REF, TREE_TYPE(rhs_field), rhs_tree, rhs_field,
 		    NULL_TREE);
 
-  // If the value is a pointer, then we can just get it from the
-  // interface.  Otherwise we have to make a copy.
-  if (lhs_type->points_to() != NULL)
-    return build2(COMPOUND_EXPR, lhs_type_tree, call,
-		  fold_convert_loc(location, lhs_type_tree, val));
-
-  tree tmp = create_tmp_var(lhs_type_tree, NULL);
-  DECL_IGNORED_P(tmp) = 0;
-
-  tree make_tmp = fold_build1_loc(location, DECL_EXPR, void_type_node, tmp);
-  tree s = build2(COMPOUND_EXPR, void_type_node, call, make_tmp);
-
-  val = fold_convert_loc(location, build_pointer_type(lhs_type_tree), val);
-  val = build_fold_indirect_ref_loc(location, val);
-  tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
-			     tmp, val);
-  s = build2(COMPOUND_EXPR, void_type_node, s, set);
-
-  return build2(COMPOUND_EXPR, lhs_type_tree, s, tmp);
+  // If the value is a pointer, then it is the value we want.
+  // Otherwise it points to the value.
+  if (lhs_type->points_to() == NULL)
+    {
+      val = fold_convert_loc(location, build_pointer_type(lhs_type_tree), val);
+      val = build_fold_indirect_ref_loc(location, val);
+    }
+
+  return build2(COMPOUND_EXPR, lhs_type_tree, call,
+		fold_convert_loc(location, lhs_type_tree, val));
 }
 
 // Convert an expression to a tree.  This is implemented by the child
@@ -11459,18 +11450,40 @@
   if (expr_type->is_unsafe_pointer_type())
     {
       if (this->type_->points_to() == NULL
-	  && this->type_->integer_type() == NULL)
-	this->report_error(_("invalid unsafe.pointer conversion"));
+	  && (this->type_->integer_type() == NULL
+	      || (this->type_->forwarded()
+		  != Type::lookup_integer_type("uintptr"))))
+	this->report_error(_("invalid unsafe.Pointer conversion"));
     }
   else if (this->type_->is_unsafe_pointer_type())
     {
-      if (expr_type->interface_type() == NULL
-	  && expr_type->points_to() == NULL
-	  && expr_type->integer_type() == NULL)
-	this->report_error(_("invalid unsafe.pointer conversion"));
+      if (expr_type->points_to() == NULL
+	  && (expr_type->integer_type() == NULL
+	      || (expr_type->forwarded()
+		  != Type::lookup_integer_type("uintptr"))))
+	this->report_error(_("invalid unsafe.Pointer conversion"));
     }
   else if (expr_type->interface_type() == NULL)
-    this->report_error(_("type guard only valid for interface types"));
+    this->report_error(_("type assertion only valid for interface types"));
+  else if (this->type_->interface_type() == NULL)
+    {
+      std::string reason;
+      if (!expr_type->interface_type()->implements_interface(this->type_,
+							     &reason))
+	{
+	  if (reason.empty())
+	    this->report_error(_("impossible type assertion: "
+				 "type does not implement interface"));
+	  else
+	    {
+	      error_at(this->location(),
+		       ("impossible type assertion: "
+			"type does not implement interface (%s)"),
+		       reason.c_str());
+	      this->set_is_error();
+	    }
+	}
+    }
 }
 
 // Return a tree for a type guard expression.

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