compiler: track //go:nointerface in export data
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 9 Feb 2018 19:39:14 +0000 (19:39 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 9 Feb 2018 19:39:14 +0000 (19:39 +0000)
    The magic //go:nointerface comment, used for field tracking, was only
    implemented for conversions to interface types in the same package.
    Record it in the export data, so that it works as expected for types
    imported from a different package.

    Reviewed-on: https://go-review.googlesource.com/93075

From-SVN: r257540

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/types.cc

index edffc11eec10ea7e0db437567fbe9c6ef7c7cd60..3d73330d13d2ebdf3dbe919515d5268b718bfecd 100644 (file)
@@ -1,4 +1,4 @@
-7e94bac5676afc8188677c98ecb263c78c1a7f8d
+89105404f94005ffa8e2b08df78015dc9ac91362
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index ab0c27b7588f67007f33fe11139bd66ded06be87..11ac33840707e580a3b11c06701fdb6ec5e3465a 100644 (file)
@@ -5189,17 +5189,24 @@ Function::defer_stack(Location location)
 void
 Function::export_func(Export* exp, const std::string& name) const
 {
-  Function::export_func_with_type(exp, name, this->type_);
+  Function::export_func_with_type(exp, name, this->type_,
+                                 this->is_method() && this->nointerface());
 }
 
 // Export a function with a type.
 
 void
 Function::export_func_with_type(Export* exp, const std::string& name,
-                               const Function_type* fntype)
+                               const Function_type* fntype, bool nointerface)
 {
   exp->write_c_string("func ");
 
+  if (nointerface)
+    {
+      go_assert(fntype->is_method());
+      exp->write_c_string("/*nointerface*/ ");
+    }
+
   if (fntype->is_method())
     {
       exp->write_c_string("(");
@@ -5280,10 +5287,21 @@ Function::import_func(Import* imp, std::string* pname,
                      Typed_identifier** preceiver,
                      Typed_identifier_list** pparameters,
                      Typed_identifier_list** presults,
-                     bool* is_varargs)
+                     bool* is_varargs,
+                     bool* nointerface)
 {
   imp->require_c_string("func ");
 
+  *nointerface = false;
+  if (imp->match_c_string("/*"))
+    {
+      imp->require_c_string("/*nointerface*/ ");
+      *nointerface = true;
+
+      // Only a method can be nointerface.
+      go_assert(imp->peek_char() == '(');
+    }
+
   *preceiver = NULL;
   if (imp->peek_char() == '(')
     {
@@ -6213,6 +6231,32 @@ Bindings_snapshot::check_goto_defs(Location loc, const Block* block,
 
 // Class Function_declaration.
 
+// Whether this declares a method.
+
+bool
+Function_declaration::is_method() const
+{
+  return this->fntype_->is_method();
+}
+
+// Whether this method should not be included in the type descriptor.
+
+bool
+Function_declaration::nointerface() const
+{
+  go_assert(this->is_method());
+  return (this->pragmas_ & GOPRAGMA_NOINTERFACE) != 0;
+}
+
+// Record that this method should not be included in the type
+// descriptor.
+
+void
+Function_declaration::set_nointerface()
+{
+  this->pragmas_ |= GOPRAGMA_NOINTERFACE;
+}
+
 // Return the function descriptor.
 
 Expression*
index dfff5c170c974cabe0defa5caf47f6292a472875..139df1785d45fa2ae12adfc6babbfaebf005ddf5 100644 (file)
@@ -1476,13 +1476,14 @@ class Function
   // Export a function with a type.
   static void
   export_func_with_type(Export*, const std::string& name,
-                       const Function_type*);
+                       const Function_type*, bool nointerface);
 
   // Import a function.
   static void
   import_func(Import*, std::string* pname, Typed_identifier** receiver,
              Typed_identifier_list** pparameters,
-             Typed_identifier_list** presults, bool* is_varargs);
+             Typed_identifier_list** presults, bool* is_varargs,
+             bool* nointerface);
 
  private:
   // Type for mapping from label names to Label objects.
@@ -1607,6 +1608,10 @@ class Function_declaration
   location() const
   { return this->location_; }
 
+  // Return whether this function declaration is a method.
+  bool
+  is_method() const;
+
   const std::string&
   asm_name() const
   { return this->asm_name_; }
@@ -1628,6 +1633,16 @@ class Function_declaration
     this->pragmas_ = pragmas;
   }
 
+  // Whether this method should not be included in the type
+  // descriptor.
+  bool
+  nointerface() const;
+
+  // Record that this method should not be included in the type
+  // descriptor.
+  void
+  set_nointerface();
+
   // Return an expression for the function descriptor, given the named
   // object for this function.  This may only be called for functions
   // without a closure.  This will be an immutable struct with one
@@ -1652,7 +1667,10 @@ class Function_declaration
   // Export a function declaration.
   void
   export_func(Export* exp, const std::string& name) const
-  { Function::export_func_with_type(exp, name, this->fntype_); }
+  {
+    Function::export_func_with_type(exp, name, this->fntype_,
+                                   this->is_method() && this->nointerface());
+  }
 
   // Check that the types used in this declaration's signature are defined.
   void
index 2a3ea83ca78962c2b0626485b8c4a6e9a175194b..7e06a3c085047d9531434756e805302ba307d7ee 100644 (file)
@@ -607,8 +607,9 @@ Import::import_func(Package* package)
   Typed_identifier_list* parameters;
   Typed_identifier_list* results;
   bool is_varargs;
+  bool nointerface;
   Function::import_func(this, &name, &receiver,
-                       &parameters, &results, &is_varargs);
+                       &parameters, &results, &is_varargs, &nointerface);
   Function_type *fntype = Type::make_function_type(receiver, parameters,
                                                   results, this->location_);
   if (is_varargs)
@@ -648,6 +649,10 @@ Import::import_func(Package* package)
       if (this->add_to_globals_)
        this->gogo_->add_dot_import_object(no);
     }
+
+  if (nointerface)
+    no->func_declaration_value()->set_nointerface();
+
   return no;
 }
 
index eb04fe1e2293bb52984527ec67a82e71e9a5b2a3..40eccfcadcaf8b70a7b04abf55d7adf1a6c4faf9 100644 (file)
@@ -9742,7 +9742,12 @@ bool
 Named_method::do_nointerface() const
 {
   Named_object* no = this->named_object_;
-  return no->is_function() && no->func_value()->nointerface();
+  if (no->is_function())
+    return no->func_value()->nointerface();
+  else if (no->is_function_declaration())
+    return no->func_declaration_value()->nointerface();
+  else
+    go_unreachable();
 }
 
 // Class Interface_method.