From 8221fb01d690820cb4e9fe4a8b4e33ddcf686029 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 9 Feb 2018 19:39:14 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 50 ++++++++++++++++++++++++++++++++++--- gcc/go/gofrontend/gogo.h | 24 +++++++++++++++--- gcc/go/gofrontend/import.cc | 7 +++++- gcc/go/gofrontend/types.cc | 7 +++++- 5 files changed, 81 insertions(+), 9 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index edffc11eec1..3d73330d13d 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index ab0c27b7588..11ac3384070 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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* diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index dfff5c170c9..139df1785d4 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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 diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index 2a3ea83ca78..7e06a3c0850 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -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, - ¶meters, &results, &is_varargs); + ¶meters, &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; } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index eb04fe1e229..40eccfcadca 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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. -- 2.30.2