Commit 8221fb01 by Ian Lance Taylor

compiler: track //go:nointerface in export data

    
    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
parent 0444aa9c
7e94bac5676afc8188677c98ecb263c78c1a7f8d 89105404f94005ffa8e2b08df78015dc9ac91362
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -5189,17 +5189,24 @@ Function::defer_stack(Location location) ...@@ -5189,17 +5189,24 @@ Function::defer_stack(Location location)
void void
Function::export_func(Export* exp, const std::string& name) const 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. // Export a function with a type.
void void
Function::export_func_with_type(Export* exp, const std::string& name, 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 "); exp->write_c_string("func ");
if (nointerface)
{
go_assert(fntype->is_method());
exp->write_c_string("/*nointerface*/ ");
}
if (fntype->is_method()) if (fntype->is_method())
{ {
exp->write_c_string("("); exp->write_c_string("(");
...@@ -5280,10 +5287,21 @@ Function::import_func(Import* imp, std::string* pname, ...@@ -5280,10 +5287,21 @@ Function::import_func(Import* imp, std::string* pname,
Typed_identifier** preceiver, Typed_identifier** preceiver,
Typed_identifier_list** pparameters, Typed_identifier_list** pparameters,
Typed_identifier_list** presults, Typed_identifier_list** presults,
bool* is_varargs) bool* is_varargs,
bool* nointerface)
{ {
imp->require_c_string("func "); 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; *preceiver = NULL;
if (imp->peek_char() == '(') if (imp->peek_char() == '(')
{ {
...@@ -6213,6 +6231,32 @@ Bindings_snapshot::check_goto_defs(Location loc, const Block* block, ...@@ -6213,6 +6231,32 @@ Bindings_snapshot::check_goto_defs(Location loc, const Block* block,
// Class Function_declaration. // 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. // Return the function descriptor.
Expression* Expression*
......
...@@ -1476,13 +1476,14 @@ class Function ...@@ -1476,13 +1476,14 @@ class Function
// Export a function with a type. // Export a function with a type.
static void static void
export_func_with_type(Export*, const std::string& name, export_func_with_type(Export*, const std::string& name,
const Function_type*); const Function_type*, bool nointerface);
// Import a function. // Import a function.
static void static void
import_func(Import*, std::string* pname, Typed_identifier** receiver, import_func(Import*, std::string* pname, Typed_identifier** receiver,
Typed_identifier_list** pparameters, Typed_identifier_list** pparameters,
Typed_identifier_list** presults, bool* is_varargs); Typed_identifier_list** presults, bool* is_varargs,
bool* nointerface);
private: private:
// Type for mapping from label names to Label objects. // Type for mapping from label names to Label objects.
...@@ -1607,6 +1608,10 @@ class Function_declaration ...@@ -1607,6 +1608,10 @@ class Function_declaration
location() const location() const
{ return this->location_; } { return this->location_; }
// Return whether this function declaration is a method.
bool
is_method() const;
const std::string& const std::string&
asm_name() const asm_name() const
{ return this->asm_name_; } { return this->asm_name_; }
...@@ -1628,6 +1633,16 @@ class Function_declaration ...@@ -1628,6 +1633,16 @@ class Function_declaration
this->pragmas_ = pragmas; 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 // Return an expression for the function descriptor, given the named
// object for this function. This may only be called for functions // object for this function. This may only be called for functions
// without a closure. This will be an immutable struct with one // without a closure. This will be an immutable struct with one
...@@ -1652,7 +1667,10 @@ class Function_declaration ...@@ -1652,7 +1667,10 @@ class Function_declaration
// Export a function declaration. // Export a function declaration.
void void
export_func(Export* exp, const std::string& name) const 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. // Check that the types used in this declaration's signature are defined.
void void
......
...@@ -607,8 +607,9 @@ Import::import_func(Package* package) ...@@ -607,8 +607,9 @@ Import::import_func(Package* package)
Typed_identifier_list* parameters; Typed_identifier_list* parameters;
Typed_identifier_list* results; Typed_identifier_list* results;
bool is_varargs; bool is_varargs;
bool nointerface;
Function::import_func(this, &name, &receiver, Function::import_func(this, &name, &receiver,
&parameters, &results, &is_varargs); &parameters, &results, &is_varargs, &nointerface);
Function_type *fntype = Type::make_function_type(receiver, parameters, Function_type *fntype = Type::make_function_type(receiver, parameters,
results, this->location_); results, this->location_);
if (is_varargs) if (is_varargs)
...@@ -648,6 +649,10 @@ Import::import_func(Package* package) ...@@ -648,6 +649,10 @@ Import::import_func(Package* package)
if (this->add_to_globals_) if (this->add_to_globals_)
this->gogo_->add_dot_import_object(no); this->gogo_->add_dot_import_object(no);
} }
if (nointerface)
no->func_declaration_value()->set_nointerface();
return no; return no;
} }
......
...@@ -9742,7 +9742,12 @@ bool ...@@ -9742,7 +9742,12 @@ bool
Named_method::do_nointerface() const Named_method::do_nointerface() const
{ {
Named_object* no = this->named_object_; 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. // Class Interface_method.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment