aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-09 19:39:14 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-09 19:39:14 +0000
commit8221fb01d690820cb4e9fe4a8b4e33ddcf686029 (patch)
treea02a65515fd99462d3424ce0a5dda6b342833b75
parent0444aa9c0a3357707624263ec2fd13d8f156016e (diff)
downloadgcc-8221fb01d690820cb4e9fe4a8b4e33ddcf686029.zip
gcc-8221fb01d690820cb4e9fe4a8b4e33ddcf686029.tar.gz
gcc-8221fb01d690820cb4e9fe4a8b4e33ddcf686029.tar.bz2
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
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/gogo.cc50
-rw-r--r--gcc/go/gofrontend/gogo.h24
-rw-r--r--gcc/go/gofrontend/import.cc7
-rw-r--r--gcc/go/gofrontend/types.cc7
5 files changed, 81 insertions, 9 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index edffc11..3d73330 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 ab0c27b..11ac338 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 dfff5c1..139df17 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 2a3ea83..7e06a3c 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,
- &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;
}
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index eb04fe1..40eccfc 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.