This patch to the Go frontend by Cherry Zhang adds support for the go:noescape compilation pragma across packages. https://golang.org/cl/83876 added support for the go:noescape pragma, but only for functions called from the same package. The pragma did not take effect for exported functions that are not called from the same package. This is because top level function declarations are not traversed, and are only reached from calls from other functions. This patch adds support for uncalled function declarations. The Traverse class is extended with a mode to traverse function declarations. Bootstrapped on x86_64-pc-linux-gnu. Committed to mainline.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 256404) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -b361bec95927fd6209c286906f98deeedcfe1da3 +cf5a64066fa21b20beae0b895c05d26af53e13e0 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/escape.cc =================================================================== --- gcc/go/gofrontend/escape.cc (revision 256393) +++ gcc/go/gofrontend/escape.cc (working copy) @@ -997,7 +997,7 @@ class Escape_analysis_discover : public { public: Escape_analysis_discover(Gogo* gogo) - : Traverse(traverse_functions), + : Traverse(traverse_functions | traverse_func_declarations), gogo_(gogo), component_ids_() { } @@ -1005,6 +1005,9 @@ class Escape_analysis_discover : public function(Named_object*); int + function_declaration(Named_object*); + + int visit(Named_object*); int @@ -1034,6 +1037,13 @@ Escape_analysis_discover::function(Named { this->visit(fn); return TRAVERSE_CONTINUE; +} + +int +Escape_analysis_discover::function_declaration(Named_object* fn) +{ + this->visit(fn); + return TRAVERSE_CONTINUE; } // Visit a function FN, adding it to the current stack of functions Index: gcc/go/gofrontend/gogo.cc =================================================================== --- gcc/go/gofrontend/gogo.cc (revision 256398) +++ gcc/go/gofrontend/gogo.cc (working copy) @@ -7912,6 +7912,21 @@ Bindings::traverse(Traverse* traverse, b } } + // Traverse function declarations when needed. + if ((traverse_mask & Traverse::traverse_func_declarations) != 0) + { + for (Bindings::const_declarations_iterator p = this->begin_declarations(); + p != this->end_declarations(); + ++p) + { + if (p->second->is_function_declaration()) + { + if (traverse->function_declaration(p->second) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + } + } + return TRAVERSE_CONTINUE; } @@ -8220,6 +8235,12 @@ Traverse::type(Type*) { go_unreachable(); } + +int +Traverse::function_declaration(Named_object*) +{ + go_unreachable(); +} // Class Statement_inserter. Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 256398) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -3271,13 +3271,14 @@ class Traverse { public: // These bitmasks say what to traverse. - static const unsigned int traverse_variables = 0x1; - static const unsigned int traverse_constants = 0x2; - static const unsigned int traverse_functions = 0x4; - static const unsigned int traverse_blocks = 0x8; - static const unsigned int traverse_statements = 0x10; - static const unsigned int traverse_expressions = 0x20; - static const unsigned int traverse_types = 0x40; + static const unsigned int traverse_variables = 0x1; + static const unsigned int traverse_constants = 0x2; + static const unsigned int traverse_functions = 0x4; + static const unsigned int traverse_blocks = 0x8; + static const unsigned int traverse_statements = 0x10; + static const unsigned int traverse_expressions = 0x20; + static const unsigned int traverse_types = 0x40; + static const unsigned int traverse_func_declarations = 0x80; Traverse(unsigned int traverse_mask) : traverse_mask_(traverse_mask), types_seen_(NULL), expressions_seen_(NULL) @@ -3342,6 +3343,11 @@ class Traverse virtual int type(Type*); + // If traverse_func_declarations is set in the mask, this is called + // for every function declarations in the tree. + virtual int + function_declaration(Named_object*); + private: // A hash table for types we have seen during this traversal. Note // that this uses the default hash functions for pointers rather