diff mbox

Go 4.7 patch committed: Bring 4.7 branch up to date

Message ID mcrtxuspr0n.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 20, 2012, 5:01 p.m. UTC
I have committed this patch to the GCC 4.7 branch to bring it up to date
with the bug fixes that I have already committed to mainline.
Bootstrapped 4.7 branch and ran Go testsuite on
x86_64-unknown-linux-gnu.

Ian


2012-09-20  Ian Lance Taylor  <iant@google.com>

	* Make-lang.in (go/gogo.o): Depend on filenames.h.
diff mbox

Patch

Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 190405)
+++ gcc/go/Make-lang.in	(working copy)
@@ -289,10 +289,11 @@  go/gogo-tree.o: go/gofrontend/gogo-tree.
 	convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \
 	$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) \
 	go/gofrontend/backend.h $(GO_GOGO_H)
-go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
-	go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
-	$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \
-	$(GO_IMPORT_H) $(GO_EXPORT_H) go/gofrontend/backend.h $(GO_GOGO_H)
+go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) \
+	$(srcdir)/../include/filenames.h $(GO_C_H) go/gofrontend/go-dump.h \
+	$(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) \
+	go/gofrontend/dataflow.h $(GO_RUNTIME_H) $(GO_IMPORT_H) \
+	$(GO_EXPORT_H) go/gofrontend/backend.h $(GO_GOGO_H)
 go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \
 	$(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \
 	$(GO_C_H) $(GO_GOGO_H) $(GO_LEX_H) $(GO_TYPES_H) $(GO_EXPORT_H) \
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 190405)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -6,6 +6,8 @@ 
 
 #include "go-system.h"
 
+#include "filenames.h"
+
 #include "go-c.h"
 #include "go-dump.h"
 #include "lex.h"
@@ -385,6 +387,57 @@  Gogo::import_package(const std::string& 
 		     bool is_local_name_exported,
 		     Location location)
 {
+  if (filename.empty())
+    {
+      error_at(location, "import path is empty");
+      return;
+    }
+
+  const char *pf = filename.data();
+  const char *pend = pf + filename.length();
+  while (pf < pend)
+    {
+      unsigned int c;
+      int adv = Lex::fetch_char(pf, &c);
+      if (adv == 0)
+	{
+	  error_at(location, "import path contains invalid UTF-8 sequence");
+	  return;
+	}
+      if (c == '\0')
+	{
+	  error_at(location, "import path contains NUL");
+	  return;
+	}
+      if (c < 0x20 || c == 0x7f)
+	{
+	  error_at(location, "import path contains control character");
+	  return;
+	}
+      if (c == '\\')
+	{
+	  error_at(location, "import path contains backslash; use slash");
+	  return;
+	}
+      if (Lex::is_unicode_space(c))
+	{
+	  error_at(location, "import path contains space character");
+	  return;
+	}
+      if (c < 0x7f && strchr("!\"#$%&'()*,:;<=>?[]^`{|}", c) != NULL)
+	{
+	  error_at(location, "import path contains invalid character '%c'", c);
+	  return;
+	}
+      pf += adv;
+    }
+
+  if (IS_ABSOLUTE_PATH(filename.c_str()))
+    {
+      error_at(location, "import path cannot be absolute path");
+      return;
+    }
+
   if (filename == "unsafe")
     {
       this->import_unsafe(local_name, is_local_name_exported, location);
@@ -1003,7 +1056,15 @@  Gogo::add_type(const std::string& name, 
   Named_object* no = this->current_bindings()->add_type(name, NULL, type,
 							location);
   if (!this->in_global_scope() && no->is_type())
-    no->type_value()->set_in_function(this->functions_.back().function);
+    {
+      Named_object* f = this->functions_.back().function;
+      unsigned int index;
+      if (f->is_function())
+	index = f->func_value()->new_local_type_index();
+      else
+	index = 0;
+      no->type_value()->set_in_function(f, index);
+    }
 }
 
 // Add a named type.
@@ -1025,7 +1086,12 @@  Gogo::declare_type(const std::string& na
   if (!this->in_global_scope() && no->is_type_declaration())
     {
       Named_object* f = this->functions_.back().function;
-      no->type_declaration_value()->set_in_function(f);
+      unsigned int index;
+      if (f->is_function())
+	index = f->func_value()->new_local_type_index();
+      else
+	index = 0;
+      no->type_declaration_value()->set_in_function(f, index);
     }
   return no;
 }
@@ -2989,9 +3055,10 @@  Gogo::convert_named_types_in_bindings(Bi
 Function::Function(Function_type* type, Function* enclosing, Block* block,
 		   Location location)
   : type_(type), enclosing_(enclosing), results_(NULL),
-    closure_var_(NULL), block_(block), location_(location), fndecl_(NULL),
-    defer_stack_(NULL), results_are_named_(false), calls_recover_(false),
-    is_recover_thunk_(false), has_recover_thunk_(false)
+    closure_var_(NULL), block_(block), location_(location), labels_(),
+    local_type_count_(0), fndecl_(NULL), defer_stack_(NULL),
+    results_are_named_(false), calls_recover_(false), is_recover_thunk_(false),
+    has_recover_thunk_(false)
 {
 }
 
@@ -4599,9 +4666,10 @@  Named_object::set_type_value(Named_type*
   go_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
   Type_declaration* td = this->u_.type_declaration;
   td->define_methods(named_type);
-  Named_object* in_function = td->in_function();
+  unsigned int index;
+  Named_object* in_function = td->in_function(&index);
   if (in_function != NULL)
-    named_type->set_in_function(in_function);
+    named_type->set_in_function(in_function, index);
   delete td;
   this->classification_ = NAMED_OBJECT_TYPE;
   this->u_.type_value = named_type;
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 190405)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -963,6 +963,11 @@  class Function
   void
   check_labels() const;
 
+  // Note that a new local type has been added.  Return its index.
+  unsigned int
+  new_local_type_index()
+  { return this->local_type_count_++; }
+
   // Whether this function calls the predeclared recover function.
   bool
   calls_recover() const
@@ -1084,6 +1089,8 @@  class Function
   Location location_;
   // Labels defined or referenced in the function.
   Labels labels_;
+  // The number of local types defined in this function.
+  unsigned int local_type_count_;
   // The function decl.
   tree fndecl_;
   // The defer stack variable.  A pointer to this variable is used to
@@ -1638,8 +1645,8 @@  class Type_declaration
 {
  public:
   Type_declaration(Location location)
-    : location_(location), in_function_(NULL), methods_(),
-      issued_warning_(false)
+    : location_(location), in_function_(NULL), in_function_index_(0),
+      methods_(), issued_warning_(false)
   { }
 
   // Return the location.
@@ -1650,13 +1657,19 @@  class Type_declaration
   // Return the function in which this type is declared.  This will
   // return NULL for a type declared in global scope.
   Named_object*
-  in_function()
-  { return this->in_function_; }
+  in_function(unsigned int* pindex)
+  {
+    *pindex = this->in_function_index_;
+    return this->in_function_;
+  }
 
   // Set the function in which this type is declared.
   void
-  set_in_function(Named_object* f)
-  { this->in_function_ = f; }
+  set_in_function(Named_object* f, unsigned int index)
+  {
+    this->in_function_ = f;
+    this->in_function_index_ = index;
+  }
 
   // Add a method to this type.  This is used when methods are defined
   // before the type.
@@ -1689,6 +1702,8 @@  class Type_declaration
   // If this type is declared in a function, a pointer back to the
   // function in which it is defined.
   Named_object* in_function_;
+  // The index of this type in IN_FUNCTION_.
+  unsigned int in_function_index_;
   // Methods defined before the type is defined.
   Methods methods_;
   // True if we have issued a warning about a use of this type
Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 190405)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -2623,8 +2623,8 @@  class Named_type : public Type
  public:
   Named_type(Named_object* named_object, Type* type, Location location)
     : Type(TYPE_NAMED),
-      named_object_(named_object), in_function_(NULL), type_(type),
-      local_methods_(NULL), all_methods_(NULL),
+      named_object_(named_object), in_function_(NULL), in_function_index_(0),
+      type_(type), local_methods_(NULL), all_methods_(NULL),
       interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
       location_(location), named_btype_(NULL), dependencies_(),
       is_visible_(true), is_error_(false), is_placeholder_(false),
@@ -2651,13 +2651,19 @@  class Named_type : public Type
   // Return the function in which this type is defined.  This will
   // return NULL for a type defined in global scope.
   const Named_object*
-  in_function() const
-  { return this->in_function_; }
+  in_function(unsigned int *pindex) const
+  {
+    *pindex = this->in_function_index_;
+    return this->in_function_;
+  }
 
   // Set the function in which this type is defined.
   void
-  set_in_function(Named_object* f)
-  { this->in_function_ = f; }
+  set_in_function(Named_object* f, unsigned int index)
+  {
+    this->in_function_ = f;
+    this->in_function_index_ = index;
+  }
 
   // Return the name of the type.
   const std::string&
@@ -2865,6 +2871,8 @@  class Named_type : public Type
   // If this type is defined in a function, a pointer back to the
   // function in which it is defined.
   Named_object* in_function_;
+  // The index of this type in IN_FUNCTION_.
+  unsigned int in_function_index_;
   // The actual type.
   Type* type_;
   // The list of methods defined for this type.  Any named type can
Index: gcc/go/gofrontend/parse.cc
===================================================================
--- gcc/go/gofrontend/parse.cc	(revision 190405)
+++ gcc/go/gofrontend/parse.cc	(working copy)
@@ -5337,7 +5337,8 @@  Parse::import_spec(void*)
 
   if (!token->is_string())
     {
-      error_at(this->location(), "missing import package name");
+      error_at(this->location(), "import statement not a string");
+      this->advance_token();
       return;
     }
 
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 190405)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -1002,9 +1002,19 @@  Named_object::get_id(Gogo* gogo)
     }
   if (this->is_type())
     {
-      const Named_object* in_function = this->type_value()->in_function();
+      unsigned int index;
+      const Named_object* in_function = this->type_value()->in_function(&index);
       if (in_function != NULL)
-	decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+	{
+	  decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+	  if (index > 0)
+	    {
+	      char buf[30];
+	      snprintf(buf, sizeof buf, "%u", index);
+	      decl_name += '$';
+	      decl_name += buf;
+	    }
+	}
     }
   return get_identifier_from_string(decl_name);
 }
Index: gcc/go/gofrontend/lex.cc
===================================================================
--- gcc/go/gofrontend/lex.cc	(revision 190405)
+++ gcc/go/gofrontend/lex.cc	(working copy)
@@ -722,7 +722,16 @@  Lex::next_token()
 		unsigned int ci;
 		bool issued_error;
 		this->lineoff_ = p - this->linebuf_;
-		this->advance_one_utf8_char(p, &ci, &issued_error);
+		const char *pnext = this->advance_one_utf8_char(p, &ci,
+								&issued_error);
+
+		// Ignore byte order mark at start of file.
+		if (ci == 0xfeff)
+		  {
+		    p = pnext;
+		    break;
+		  }
+
 		if (Lex::is_unicode_letter(ci))
 		  return this->gather_identifier();
 
@@ -831,6 +840,14 @@  Lex::advance_one_utf8_char(const char* p
       *issued_error = true;
       return p + 1;
     }
+
+  // Warn about byte order mark, except at start of file.
+  if (*value == 0xfeff && (this->lineno_ != 1 || this->lineoff_ != 0))
+    {
+      error_at(this->location(), "Unicode (UTF-8) BOM in middle of file");
+      *issued_error = true;
+    }
+
   return p + adv;
 }
 
@@ -1705,6 +1722,27 @@  struct Unicode_range
   unsigned int stride;
 };
 
+// A table of whitespace characters--Unicode code points classified as
+// "Space", "C" locale whitespace characters, the "next line" control
+// character (0085), the line separator (2028), the paragraph
+// separator (2029), and the "zero-width non-break space" (feff).
+
+static const Unicode_range unicode_space[] =
+{
+  { 0x0009, 0x000d, 1 },
+  { 0x0020, 0x0020, 1 },
+  { 0x0085, 0x0085, 1 },
+  { 0x00a0, 0x00a0, 1 },
+  { 0x1680, 0x1680, 1 },
+  { 0x180e, 0x180e, 1 },
+  { 0x2000, 0x200a, 1 },
+  { 0x2028, 0x2029, 1 },
+  { 0x202f, 0x202f, 1 },
+  { 0x205f, 0x205f, 1 },
+  { 0x3000, 0x3000, 1 },
+  { 0xfeff, 0xfeff, 1 },
+};
+
 // A table of Unicode digits--Unicode code points classified as
 // "Digit".
 
@@ -2294,6 +2332,15 @@  Lex::is_in_unicode_range(unsigned int c,
     }
 }
 
+// Return whether C is a space character.
+
+bool
+Lex::is_unicode_space(unsigned int c)
+{
+  return Lex::is_in_unicode_range(c, unicode_space,
+				  ARRAY_SIZE(unicode_space));
+}
+
 // Return whether C is a Unicode digit--a Unicode code point
 // classified as "Digit".
 
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 190405)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -588,6 +588,9 @@  Type::are_compatible_for_comparison(bool
 	       p != fields->end();
 	       ++p)
 	    {
+	      if (Gogo::is_sink_name(p->field_name()))
+		continue;
+
 	      if (!p->type()->is_comparable())
 		{
 		  if (reason != NULL)
@@ -1295,7 +1298,8 @@  Type::type_descriptor_var_name(Gogo* gog
     return "__go_td_" + this->mangled_name(gogo);
 
   Named_object* no = nt->named_object();
-  const Named_object* in_function = nt->in_function();
+  unsigned int index;
+  const Named_object* in_function = nt->in_function(&index);
   std::string ret = "__go_tdn_";
   if (nt->is_builtin())
     go_assert(in_function == NULL);
@@ -1310,6 +1314,13 @@  Type::type_descriptor_var_name(Gogo* gog
 	{
 	  ret.append(Gogo::unpack_hidden_name(in_function->name()));
 	  ret.append(1, '.');
+	  if (index > 0)
+	    {
+	      char buf[30];
+	      snprintf(buf, sizeof buf, "%u", index);
+	      ret.append(buf);
+	      ret.append(1, '.');
+	    }
 	}
     }
 
@@ -1746,9 +1757,19 @@  Type::specific_type_functions(Gogo* gogo
     {
       // This name is already hidden or not as appropriate.
       base_name = name->name();
-      const Named_object* in_function = name->in_function();
+      unsigned int index;
+      const Named_object* in_function = name->in_function(&index);
       if (in_function != NULL)
-	base_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+	{
+	  base_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+	  if (index > 0)
+	    {
+	      char buf[30];
+	      snprintf(buf, sizeof buf, "%u", index);
+	      base_name += '$';
+	      base_name += buf;
+	    }
+	}
     }
   std::string hash_name = base_name + "$hash";
   std::string equal_name = base_name + "$equal";
@@ -1989,10 +2010,19 @@  Type::uncommon_type_constructor(Gogo* go
 				     ? gogo->pkgpath()
 				     : package->pkgpath());
 	  n.assign(pkgpath);
-	  if (name->in_function() != NULL)
+	  unsigned int index;
+	  const Named_object* in_function = name->in_function(&index);
+	  if (in_function != NULL)
 	    {
 	      n.append(1, '.');
-	      n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
+	      n.append(Gogo::unpack_hidden_name(in_function->name()));
+	      if (index > 0)
+		{
+		  char buf[30];
+		  snprintf(buf, sizeof buf, "%u", index);
+		  n.append(1, '.');
+		  n.append(buf);
+		}
 	    }
 	  s = Expression::make_string(n, bloc);
 	  vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
@@ -4276,6 +4306,9 @@  Struct_type::do_compare_is_identity(Gogo
        pf != fields->end();
        ++pf)
     {
+      if (Gogo::is_sink_name(pf->field_name()))
+	return false;
+
       if (!pf->type()->compare_is_identity(gogo))
 	return false;
 
@@ -4749,6 +4782,9 @@  Struct_type::write_hash_function(Gogo* g
        pf != fields->end();
        ++pf)
     {
+      if (Gogo::is_sink_name(pf->field_name()))
+	continue;
+
       if (first)
 	first = false;
       else
@@ -4840,6 +4876,9 @@  Struct_type::write_equal_function(Gogo* 
        pf != fields->end();
        ++pf, ++field_index)
     {
+      if (Gogo::is_sink_name(pf->field_name()))
+	continue;
+
       // Compare one field in both P1 and P2.
       Expression* f1 = Expression::make_temporary_reference(p1, bloc);
       f1 = Expression::make_unary(OPERATOR_MULT, f1, bloc);
@@ -8360,6 +8399,13 @@  Named_type::do_reflection(Gogo* gogo, st
     {
       ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
       ret->push_back('$');
+      if (this->in_function_index_ > 0)
+	{
+	  char buf[30];
+	  snprintf(buf, sizeof buf, "%u", this->in_function_index_);
+	  ret->append(buf);
+	  ret->push_back('$');
+	}
     }
   ret->append(Gogo::unpack_hidden_name(this->named_object_->name()));
 }
@@ -8389,6 +8435,13 @@  Named_type::do_mangled_name(Gogo* gogo, 
 	{
 	  name.append(Gogo::unpack_hidden_name(this->in_function_->name()));
 	  name.append(1, '$');
+	  if (this->in_function_index_ > 0)
+	    {
+	      char buf[30];
+	      snprintf(buf, sizeof buf, "%u", this->in_function_index_);
+	      name.append(buf);
+	      name.append(1, '$');
+	    }
 	}
     }
   name.append(Gogo::unpack_hidden_name(no->name()));
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 190613)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -5184,6 +5184,9 @@  Binary_expression::lower_struct_comparis
        pf != fields->end();
        ++pf, ++field_index)
     {
+      if (Gogo::is_sink_name(pf->field_name()))
+	continue;
+
       if (field_index > 0)
 	{
 	  if (left_temp == NULL)
Index: gcc/go/gofrontend/lex.h
===================================================================
--- gcc/go/gofrontend/lex.h	(revision 190405)
+++ gcc/go/gofrontend/lex.h	(working copy)
@@ -375,6 +375,10 @@  class Lex
   static int
   fetch_char(const char* str, unsigned int *value);
 
+  // Return whether C is a Unicode or "C" locale space character.
+  static bool
+  is_unicode_space(unsigned int c);
+
  private:
   ssize_t
   get_line();