LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - import.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 76.1 % 940 715
Test Date: 2026-02-28 14:20:25 Functions: 86.5 % 52 45
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // import.cc -- Go frontend import declarations.
       2              : 
       3              : // Copyright 2009 The Go Authors. All rights reserved.
       4              : // Use of this source code is governed by a BSD-style
       5              : // license that can be found in the LICENSE file.
       6              : 
       7              : #include "go-system.h"
       8              : 
       9              : #include "filenames.h"
      10              : 
      11              : #include "go-c.h"
      12              : #include "go-diagnostics.h"
      13              : #include "gogo.h"
      14              : #include "lex.h"
      15              : #include "types.h"
      16              : #include "export.h"
      17              : #include "import.h"
      18              : 
      19              : #ifndef O_BINARY
      20              : #define O_BINARY 0
      21              : #endif
      22              : 
      23              : // The list of paths we search for import files.
      24              : 
      25              : static std::vector<std::string> search_path;
      26              : 
      27              : // Add a directory to the search path.  This is called from the option
      28              : // handling language hook.
      29              : 
      30              : GO_EXTERN_C
      31              : void
      32        38836 : go_add_search_path(const char* path)
      33              : {
      34        38836 :   search_path.push_back(std::string(path));
      35        38836 : }
      36              : 
      37              : // Read an importcfg file.
      38              : 
      39              : void
      40          380 : Gogo::read_importcfg(const char* filename)
      41              : {
      42          380 :   std::string data;
      43          380 :   if (!Gogo::read_file(filename, Linemap::unknown_location(), &data))
      44              :     return;
      45          380 :   const char* p = data.data();
      46          380 :   const char* pend = p + data.length();
      47          380 :   int lineno = 0;
      48          380 :   const char *pnext = NULL;
      49         1483 :   for (; p < pend; p = pnext)
      50              :     {
      51              :       // Line numbers start at 1.
      52         1103 :       lineno++;
      53              : 
      54              :       // Find end of line.
      55         1103 :       const char* pnl = static_cast<const char*>(memchr(p, '\n', pend - p));
      56         1103 :       if (pnl != NULL)
      57         1103 :         pnext = pnl + 1;
      58              :       else
      59              :         {
      60         1103 :           pnl = pend;
      61         1103 :           pnext = pnl;
      62              :         }
      63              : 
      64              :       // Trim leading spaces.
      65         1103 :       while (p < pnl)
      66              :         {
      67         1103 :           unsigned int rune;
      68         1103 :           int rune_len = Lex::fetch_char(p, &rune);
      69         1103 :           if (rune_len == 0)
      70              :             {
      71            0 :               go_error_at(Linemap::unknown_location(),
      72              :                           "%s:%d: invalid character in importcfg file",
      73              :                           filename, lineno);
      74            0 :               return;
      75              :             }
      76         1103 :           if (!Lex::is_unicode_space(rune))
      77              :             break;
      78            0 :           p += rune_len;
      79              :         }
      80              : 
      81              :       // Trim trailing spaces.
      82         1103 :       while (pnl > p)
      83              :         {
      84         1103 :           size_t start = pnl - p - 1;
      85         1103 :           unsigned int rune = (unsigned char)p[start];
      86         1103 :           int rune_len = 1;
      87         1103 :           if (rune > 0x7f)
      88              :             {
      89            0 :               for (start--; start > 0; start--)
      90              :                 {
      91            0 :                   unsigned char c = p[start];
      92            0 :                   if ((c & 0xc0) != 0x80)
      93              :                     break;
      94              :                 }
      95            0 :               rune_len = Lex::fetch_char(p + start, &rune);
      96            0 :               if (static_cast<size_t>(rune_len) != (pnl - p) - start)
      97              :                 {
      98            0 :                   go_error_at(Linemap::unknown_location(),
      99              :                               "%s:%d: invalid character in importcfg file",
     100              :                               filename, lineno);
     101            0 :                   return;
     102              :                 }
     103              :             }
     104         1103 :           if (!Lex::is_unicode_space(rune))
     105              :             break;
     106            0 :           pnl -= rune_len;
     107              :         }
     108              : 
     109              :       // Skip empty lines and comment lines.
     110         1103 :       if (p == pnl || *p == '#')
     111          380 :         continue;
     112              : 
     113          723 :       size_t verb_len;
     114          723 :       const char* psp = static_cast<const char*>(memchr(p, ' ', pnl - p));
     115          723 :       if (psp == NULL)
     116              :         verb_len = pnl - p;
     117              :       else
     118          723 :         verb_len = psp - p;
     119              : 
     120          723 :       bool importmap = false;
     121          723 :       bool packagefile = false;
     122          723 :       if (strncmp(p, "importmap", verb_len) == 0)
     123              :         importmap = true;
     124          703 :       else if (strncmp(p, "packagefile", verb_len) == 0)
     125              :         packagefile = true;
     126              :       else
     127              :         {
     128            0 :           go_error_at(Linemap::unknown_location(),
     129              :                       "%s:%d: unknown directive in importcfg file",
     130              :                       filename, lineno);
     131            0 :           return;
     132              :         }
     133              : 
     134          723 :       const char* peq;
     135          723 :       if (psp == NULL)
     136              :         peq = NULL;
     137              :       else
     138              :         {
     139          723 :           psp++;
     140          723 :           peq = static_cast<const char*>(memchr(psp, '=', pnl - psp));
     141              :         }
     142          723 :       if (peq == NULL || peq + 1 == pnl)
     143              :         {
     144            0 :           go_error_at(Linemap::unknown_location(),
     145              :                       "%s:%d: invalid syntax in importcfg file",
     146              :                       filename, lineno);
     147            0 :           return;
     148              :         }
     149              : 
     150          723 :       std::string first(psp, peq - psp);
     151          723 :       std::string second(peq + 1, pnl - (peq + 1));
     152          723 :       if (importmap)
     153           20 :         this->import_map_[first] = second;
     154          703 :       else if (packagefile)
     155          703 :         this->package_file_[first] = second;
     156              :       else
     157            0 :         go_unreachable();
     158          723 :     }
     159          380 : }
     160              : 
     161              : // Find import data.  This searches the file system for FILENAME and
     162              : // returns a pointer to a Stream object to read the data that it
     163              : // exports.  If the file is not found, it returns NULL.
     164              : 
     165              : // When FILENAME is not an absolute path and does not start with ./ or
     166              : // ../, we use the search path provided by -I and -L options.
     167              : 
     168              : // When FILENAME does start with ./ or ../, we use
     169              : // RELATIVE_IMPORT_PATH as a prefix.
     170              : 
     171              : // When FILENAME does not exist, we try modifying FILENAME to find the
     172              : // file.  We use the first of these which exists:
     173              : //   * We append ".gox".
     174              : //   * We turn the base of FILENAME into libFILENAME.so.
     175              : //   * We turn the base of FILENAME into libFILENAME.a.
     176              : //   * We append ".o".
     177              : 
     178              : // When using a search path, we apply each of these transformations at
     179              : // each entry on the search path before moving on to the next entry.
     180              : // If the file exists, but does not contain any Go export data, we
     181              : // stop; we do not keep looking for another file with the same name
     182              : // later in the search path.
     183              : 
     184              : Import::Stream*
     185        21818 : Import::open_package(const std::string& filename, Location location,
     186              :                      const std::string& relative_import_path)
     187              : {
     188        21818 :   bool is_local;
     189        21818 :   if (IS_ABSOLUTE_PATH(filename))
     190              :     is_local = true;
     191        21116 :   else if (filename[0] == '.'
     192        21116 :            && (filename[1] == '\0' || IS_DIR_SEPARATOR(filename[1])))
     193              :     is_local = true;
     194        20475 :   else if (filename[0] == '.'
     195            0 :            && filename[1] == '.'
     196        20475 :            && (filename[2] == '\0' || IS_DIR_SEPARATOR(filename[2])))
     197              :     is_local = true;
     198              :   else
     199              :     is_local = false;
     200              : 
     201        21818 :   std::string fn = filename;
     202        21818 :   if (is_local && !IS_ABSOLUTE_PATH(filename) && !relative_import_path.empty())
     203              :     {
     204            0 :       if (fn == ".")
     205              :         {
     206              :           // A special case.
     207            0 :           fn = relative_import_path;
     208              :         }
     209            0 :       else if (fn[0] == '.' && fn[1] == '.'
     210            0 :                && (fn[2] == '\0' || IS_DIR_SEPARATOR(fn[2])))
     211              :         {
     212              :           // We are going to join relative_import_path and fn, and it
     213              :           // will look like DIR/../PATH.  But DIR does not necessarily
     214              :           // exist in this case, and if it doesn't the use of .. will
     215              :           // fail although it shouldn't.  The gc compiler uses
     216              :           // path.Join here, which cleans up the .., so we need to do
     217              :           // the same.
     218            0 :           size_t index;
     219            0 :           for (index = relative_import_path.length() - 1;
     220            0 :                index > 0 && !IS_DIR_SEPARATOR(relative_import_path[index]);
     221              :                index--)
     222              :             ;
     223            0 :           if (index > 0)
     224            0 :             fn = relative_import_path.substr(0, index) + fn.substr(2);
     225              :           else
     226            0 :             fn = relative_import_path + '/' + fn;
     227              :         }
     228              :       else
     229            0 :         fn = relative_import_path + '/' + fn;
     230              :       is_local = false;
     231              :     }
     232              : 
     233        21818 :   if (!is_local)
     234              :     {
     235        20475 :       for (std::vector<std::string>::const_iterator p = search_path.begin();
     236        27204 :            p != search_path.end();
     237         6729 :            ++p)
     238              :         {
     239        27190 :           std::string indir = *p;
     240        54380 :           if (!indir.empty() && indir[indir.size() - 1] != '/')
     241        27190 :             indir += '/';
     242        27190 :           indir += fn;
     243        27190 :           Stream* s = Import::try_package_in_directory(indir, location);
     244        27190 :           if (s != NULL)
     245        20461 :             return s;
     246        27190 :         }
     247              :     }
     248              : 
     249         1357 :   Stream* s = Import::try_package_in_directory(fn, location);
     250         1357 :   if (s != NULL)
     251              :     return s;
     252              : 
     253              :   return NULL;
     254        21818 : }
     255              : 
     256              : // Try to find the export data for FILENAME.
     257              : 
     258              : Import::Stream*
     259        28547 : Import::try_package_in_directory(const std::string& filename,
     260              :                                  Location location)
     261              : {
     262        28547 :   std::string found_filename = filename;
     263        28547 :   int fd = open(found_filename.c_str(), O_RDONLY | O_BINARY);
     264              : 
     265        28547 :   if (fd >= 0)
     266              :     {
     267        11144 :       struct stat s;
     268        11144 :       if (fstat(fd, &s) >= 0 && S_ISDIR(s.st_mode))
     269              :         {
     270        10442 :           close(fd);
     271        10442 :           fd = -1;
     272        10442 :           errno = EISDIR;
     273              :         }
     274              :     }
     275              : 
     276        11144 :   if (fd < 0)
     277              :     {
     278        27845 :       if (errno != ENOENT && errno != EISDIR)
     279            0 :         go_warning_at(location, 0, "%s: %m", filename.c_str());
     280              : 
     281        27845 :       fd = Import::try_suffixes(&found_filename);
     282        27845 :       if (fd < 0)
     283              :         return NULL;
     284              :     }
     285              : 
     286              :   // The export data may not be in this file.
     287        21808 :   Stream* s = Import::find_export_data(found_filename, fd, location);
     288        21808 :   if (s != NULL)
     289              :     return s;
     290              : 
     291            0 :   close(fd);
     292              : 
     293            0 :   go_error_at(location, "%s exists but does not contain any Go export data",
     294              :               found_filename.c_str());
     295              : 
     296            0 :   return NULL;
     297        28547 : }
     298              : 
     299              : // Given import "*PFILENAME", where *PFILENAME does not exist, try
     300              : // various suffixes.  If we find one, set *PFILENAME to the one we
     301              : // found.  Return the open file descriptor.
     302              : 
     303              : int
     304        27845 : Import::try_suffixes(std::string* pfilename)
     305              : {
     306        27845 :   std::string filename = *pfilename + ".gox";
     307        27845 :   int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
     308        27845 :   if (fd >= 0)
     309              :     {
     310        20189 :       *pfilename = filename;
     311        20189 :       return fd;
     312              :     }
     313              : 
     314         7656 :   const char* basename = lbasename(pfilename->c_str());
     315         7656 :   size_t basename_pos = basename - pfilename->c_str();
     316        30624 :   filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".so";
     317         7656 :   fd = open(filename.c_str(), O_RDONLY | O_BINARY);
     318         7656 :   if (fd >= 0)
     319              :     {
     320            0 :       *pfilename = filename;
     321            0 :       return fd;
     322              :     }
     323              : 
     324        30624 :   filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".a";
     325         7656 :   fd = open(filename.c_str(), O_RDONLY | O_BINARY);
     326         7656 :   if (fd >= 0)
     327              :     {
     328          198 :       *pfilename = filename;
     329          198 :       return fd;
     330              :     }
     331              : 
     332         7458 :   filename = *pfilename + ".o";
     333         7458 :   fd = open(filename.c_str(), O_RDONLY | O_BINARY);
     334         7458 :   if (fd >= 0)
     335              :     {
     336          719 :       *pfilename = filename;
     337          719 :       return fd;
     338              :     }
     339              : 
     340              :   return -1;
     341        27845 : }
     342              : 
     343              : // Look for export data in the file descriptor FD.
     344              : 
     345              : Import::Stream*
     346        21808 : Import::find_export_data(const std::string& filename, int fd, Location location)
     347              : {
     348              :   // See if we can read this as an object file.
     349        21808 :   Import::Stream* stream = Import::find_object_export_data(filename, fd, 0,
     350              :                                                            location);
     351        21808 :   if (stream != NULL)
     352              :     return stream;
     353              : 
     354          702 :   const int len = MAX(Export::magic_len, Import::archive_magic_len);
     355              : 
     356          702 :   if (lseek(fd, 0, SEEK_SET) < 0)
     357              :     {
     358            0 :       go_error_at(location, "lseek %s failed: %m", filename.c_str());
     359            0 :       return NULL;
     360              :     }
     361              : 
     362          702 :   char buf[len];
     363          702 :   ssize_t c = ::read(fd, buf, len);
     364          702 :   if (c < len)
     365              :     return NULL;
     366              : 
     367              :   // Check for a file containing nothing but Go export data.
     368          702 :   if (memcmp(buf, Export::cur_magic, Export::magic_len) == 0
     369          702 :       || memcmp(buf, Export::v1_magic, Export::magic_len) == 0
     370          702 :       || memcmp(buf, Export::v2_magic, Export::magic_len) == 0)
     371            0 :     return new Stream_from_file(fd);
     372              : 
     373              :   // See if we can read this as an archive.
     374          702 :   if (Import::is_archive_magic(buf))
     375          702 :     return Import::find_archive_export_data(filename, fd, location);
     376              : 
     377              :   return NULL;
     378              : }
     379              : 
     380              : // Look for export data in an object file.
     381              : 
     382              : Import::Stream*
     383        23332 : Import::find_object_export_data(const std::string& filename,
     384              :                                 int fd,
     385              :                                 off_t offset,
     386              :                                 Location location)
     387              : {
     388        23332 :   char *buf;
     389        23332 :   size_t len;
     390        23332 :   int err;
     391        23332 :   const char *errmsg = go_read_export_data(fd, offset, &buf, &len, &err);
     392        23332 :   if (errmsg != NULL)
     393              :     {
     394            0 :       if (err == 0)
     395            0 :         go_error_at(location, "%s: %s", filename.c_str(), errmsg);
     396              :       else
     397            0 :         go_error_at(location, "%s: %s: %s", filename.c_str(), errmsg,
     398              :                     xstrerror(err));
     399            0 :       return NULL;
     400              :     }
     401              : 
     402        23332 :   if (buf == NULL)
     403              :     return NULL;
     404              : 
     405        21808 :   return new Stream_from_buffer(buf, len);
     406              : }
     407              : 
     408              : // Class Import.
     409              : 
     410              : // Construct an Import object.  We make the builtin_types_ vector
     411              : // large enough to hold all the builtin types.
     412              : 
     413        21808 : Import::Import(Stream* stream, Location location)
     414        21808 :   : gogo_(NULL), stream_(stream), location_(location), package_(NULL),
     415        21808 :     add_to_globals_(false), packages_(), type_data_(), type_pos_(0),
     416        21808 :     type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
     417        21808 :     types_(), version_(EXPORT_FORMAT_UNKNOWN)
     418              : {
     419        21808 : }
     420              : 
     421              : // Import the data in the associated stream.
     422              : 
     423              : Package*
     424        21808 : Import::import(Gogo* gogo, const std::string& local_name,
     425              :                bool is_local_name_exported)
     426              : {
     427              :   // Hold on to the Gogo structure.  Otherwise we need to pass it
     428              :   // through all the import functions, because we need it when reading
     429              :   // a type.
     430        21808 :   this->gogo_ = gogo;
     431              : 
     432              :   // A stream of export data can include data from more than one input
     433              :   // file.  Here we loop over each input file.
     434        21808 :   Stream* stream = this->stream_;
     435        43616 :   while (!stream->at_eof() && !stream->saw_error())
     436              :     {
     437              :       // The vector of types is package specific.
     438        21808 :       this->types_.clear();
     439              : 
     440              :       // Check magic string / version number.
     441        21808 :       if (stream->match_bytes(Export::cur_magic, Export::magic_len))
     442              :         {
     443        21808 :           stream->require_bytes(this->location_, Export::cur_magic,
     444              :                                 Export::magic_len);
     445        21808 :           this->version_ = EXPORT_FORMAT_CURRENT;
     446              :         }
     447            0 :       else if (stream->match_bytes(Export::v1_magic, Export::magic_len))
     448              :         {
     449            0 :           stream->require_bytes(this->location_, Export::v1_magic,
     450              :                                 Export::magic_len);
     451            0 :           this->version_ = EXPORT_FORMAT_V1;
     452              :         }
     453            0 :       else if (stream->match_bytes(Export::v2_magic, Export::magic_len))
     454              :         {
     455            0 :           stream->require_bytes(this->location_, Export::v2_magic,
     456              :                                 Export::magic_len);
     457            0 :           this->version_ = EXPORT_FORMAT_V2;
     458              :         }
     459              :       else
     460              :         {
     461            0 :           go_error_at(this->location_,
     462              :                       ("error in import data at %d: invalid magic string"),
     463              :                       stream->pos());
     464            0 :           return NULL;
     465              :         }
     466              : 
     467        21808 :       this->require_c_string("package ");
     468        21808 :       std::string package_name = this->read_identifier();
     469        21808 :       this->require_semicolon_if_old_version();
     470        21808 :       this->require_c_string("\n");
     471              : 
     472        21808 :       std::string pkgpath;
     473        21808 :       std::string pkgpath_symbol;
     474        21808 :       if (this->match_c_string("prefix "))
     475              :         {
     476          175 :           this->advance(7);
     477          175 :           std::string unique_prefix = this->read_identifier();
     478          175 :           this->require_semicolon_if_old_version();
     479          175 :           this->require_c_string("\n");
     480          175 :           pkgpath = unique_prefix + '.' + package_name;
     481          350 :           pkgpath_symbol = (Gogo::pkgpath_for_symbol(unique_prefix) + '.'
     482          525 :                             + Gogo::pkgpath_for_symbol(package_name));
     483          175 :         }
     484              :       else
     485              :         {
     486        21633 :           this->require_c_string("pkgpath ");
     487        21633 :           pkgpath = this->read_identifier();
     488        21633 :           this->require_semicolon_if_old_version();
     489        21633 :           this->require_c_string("\n");
     490        21633 :           pkgpath_symbol = Gogo::pkgpath_for_symbol(pkgpath);
     491              :         }
     492              : 
     493        21808 :       if (stream->saw_error())
     494              :         return NULL;
     495              : 
     496        21808 :       this->package_ = gogo->add_imported_package(package_name, local_name,
     497              :                                                   is_local_name_exported,
     498              :                                                   pkgpath, pkgpath_symbol,
     499              :                                                   this->location_,
     500              :                                                   &this->add_to_globals_);
     501        21808 :       if (this->package_ == NULL)
     502              :         {
     503            0 :           stream->set_saw_error();
     504            0 :           return NULL;
     505              :         }
     506              : 
     507              :       // Read and discard priority if older V1 export data format.
     508        21808 :       if (version() == EXPORT_FORMAT_V1)
     509              :         {
     510            0 :           this->require_c_string("priority ");
     511            0 :           std::string priority_string = this->read_identifier();
     512            0 :           int prio;
     513            0 :           if (!this->string_to_int(priority_string, false, &prio))
     514            0 :             return NULL;
     515            0 :           this->require_c_string(";\n");
     516            0 :         }
     517              : 
     518        22015 :       while (stream->match_c_string("package"))
     519          207 :         this->read_one_package();
     520              : 
     521       211683 :       while (stream->match_c_string("import"))
     522       189875 :         this->read_one_import();
     523              : 
     524        46024 :       while (stream->match_c_string("indirectimport"))
     525        24216 :         this->read_one_indirect_import();
     526              : 
     527        21808 :       if (stream->match_c_string("init"))
     528        21808 :         this->read_import_init_fns(gogo);
     529              : 
     530        21808 :       if (stream->match_c_string("types "))
     531              :         {
     532        21808 :           if (!this->read_types())
     533              :             return NULL;
     534              :         }
     535              : 
     536              :       // Loop over all the input data for this package.
     537      2471041 :       while (!stream->saw_error())
     538              :         {
     539      2471041 :           if (stream->match_c_string("const "))
     540       851537 :             this->import_const();
     541      1619504 :           else if (stream->match_c_string("type "))
     542            0 :             this->import_type();
     543      1619504 :           else if (stream->match_c_string("var "))
     544       326311 :             this->import_var();
     545      1293193 :           else if (stream->match_c_string("func "))
     546      1271385 :             this->import_func(this->package_);
     547        21808 :           else if (stream->match_c_string("checksum "))
     548              :             break;
     549              :           else
     550              :             {
     551            0 :               go_error_at(this->location_,
     552              :                           ("error in import data at %d: "
     553              :                            "expected %<const%>, %<type%>, %<var%>, "
     554              :                            "%<func%>, or %<checksum%>"),
     555              :                           stream->pos());
     556            0 :               stream->set_saw_error();
     557            0 :               return NULL;
     558              :             }
     559              :         }
     560              : 
     561              :       // We currently ignore the checksum.  In the future we could
     562              :       // store the checksum somewhere in the generated object and then
     563              :       // verify that the checksum matches at link time or at dynamic
     564              :       // load time.
     565        21808 :       this->require_c_string("checksum ");
     566        21808 :       stream->advance(Export::checksum_len * 2);
     567        21808 :       this->require_semicolon_if_old_version();
     568        21808 :       this->require_c_string("\n");
     569        21808 :     }
     570              : 
     571              :   // Finalize methods for any imported types. This call is made late in the
     572              :   // import process so as to A) avoid finalization of a type whose methods
     573              :   // refer to types that are only partially read in, and B) capture both the
     574              :   // types imported by read_types() directly, and those imported indirectly
     575              :   // because they are referenced by an imported function or variable.
     576              :   // See issues #33013 and #33219 for more on why this is needed.
     577        21808 :   this->finalize_methods();
     578              : 
     579        21808 :   return this->package_;
     580              : }
     581              : 
     582              : // Read a package line.  This let us reliably determine the pkgpath
     583              : // symbol, even if the package was compiled with a -fgo-prefix option.
     584              : 
     585              : void
     586          207 : Import::read_one_package()
     587              : {
     588          207 :   this->require_c_string("package ");
     589          207 :   std::string package_name = this->read_identifier();
     590          207 :   this->require_c_string(" ");
     591          207 :   std::string pkgpath = this->read_identifier();
     592          207 :   this->require_c_string(" ");
     593          207 :   std::string pkgpath_symbol = this->read_identifier();
     594          207 :   this->require_semicolon_if_old_version();
     595          207 :   this->require_c_string("\n");
     596              : 
     597          207 :   Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol,
     598              :                                              Linemap::unknown_location());
     599          207 :   p->set_package_name(package_name, this->location());
     600          207 : }
     601              : 
     602              : // Read an import line.
     603              : 
     604              : void
     605       189875 : Import::read_one_import()
     606              : {
     607       189875 :   this->require_c_string("import ");
     608       189875 :   std::string package_name = this->read_identifier();
     609       189875 :   this->require_c_string(" ");
     610       189875 :   std::string pkgpath = this->read_identifier();
     611       189875 :   this->require_c_string(" \"");
     612       189875 :   Stream* stream = this->stream_;
     613      1989745 :   while (stream->peek_char() != '"')
     614      1799870 :     stream->advance(1);
     615       189875 :   this->require_c_string("\"");
     616       189875 :   this->require_semicolon_if_old_version();
     617       189875 :   this->require_c_string("\n");
     618              : 
     619       189875 :   Package* p = this->gogo_->register_package(pkgpath, "",
     620       189875 :                                              Linemap::unknown_location());
     621       189875 :   p->set_package_name(package_name, this->location());
     622              : 
     623       189875 :   this->packages_.push_back(p);
     624              : 
     625       189875 :   if (pkgpath == "unsafe")
     626         7306 :     this->gogo_->add_unsafe_bindings(p);
     627       189875 : }
     628              : 
     629              : // Read an indirectimport line.
     630              : 
     631              : void
     632        24216 : Import::read_one_indirect_import()
     633              : {
     634        24216 :   this->require_c_string("indirectimport ");
     635        24216 :   std::string package_name = this->read_identifier();
     636        24216 :   this->require_c_string(" ");
     637        24216 :   std::string pkgpath = this->read_identifier();
     638        24216 :   this->require_c_string("\n");
     639              : 
     640        24216 :   Package* p = this->gogo_->register_package(pkgpath, "",
     641        24216 :                                              Linemap::unknown_location());
     642        24216 :   p->set_package_name(package_name, this->location());
     643              : 
     644        24216 :   this->packages_.push_back(p);
     645              : 
     646        24216 :   if (pkgpath == "unsafe")
     647         3655 :     this->gogo_->add_unsafe_bindings(p);
     648        24216 : }
     649              : 
     650              : // Read the list of import control functions and/or init graph.
     651              : 
     652              : void
     653        21808 : Import::read_import_init_fns(Gogo* gogo)
     654              : {
     655        21808 :   this->require_c_string("init");
     656              : 
     657              :   // Maps init function to index in the "init" clause; needed
     658              :   // to read the init_graph section.
     659        21808 :   std::map<std::string, unsigned> init_idx;
     660              : 
     661       682010 :   while (!this->match_c_string("\n") && !this->match_c_string(";"))
     662              :     {
     663       660202 :       int priority = -1;
     664              : 
     665       660202 :       this->require_c_string(" ");
     666       660202 :       std::string package_name = this->read_identifier();
     667       660202 :       this->require_c_string(" ");
     668       660202 :       std::string init_name = this->read_identifier();
     669       660202 :       if (this->version_ == EXPORT_FORMAT_V1)
     670              :         {
     671              :           // Older version 1 init fcn export data format is:
     672              :           //
     673              :           //   <packname> <fcn> <priority>
     674            0 :           this->require_c_string(" ");
     675            0 :           std::string prio_string = this->read_identifier();
     676            0 :           if (!this->string_to_int(prio_string, false, &priority))
     677            0 :             return;
     678            0 :         }
     679       660202 :       gogo->add_import_init_fn(package_name, init_name, priority);
     680              : 
     681              :       // Record the index of this init fcn so that we can look it
     682              :       // up by index in the subsequent init_graph section.
     683       660202 :       unsigned idx = init_idx.size();
     684       660202 :       init_idx[init_name] = idx;
     685       660202 :     }
     686        21808 :   this->require_semicolon_if_old_version();
     687        21808 :   this->require_c_string("\n");
     688              : 
     689        21808 :   if (this->match_c_string("init_graph"))
     690              :     {
     691        20261 :       this->require_c_string("init_graph");
     692              : 
     693              :       // Build a vector mapping init fcn slot to Import_init pointer.
     694        20261 :       go_assert(init_idx.size() > 0);
     695        20261 :       std::vector<Import_init*> import_initvec;
     696        20261 :       import_initvec.resize(init_idx.size());
     697       678916 :       for (std::map<std::string, unsigned>::const_iterator it =
     698        20261 :                init_idx.begin();
     699       678916 :            it != init_idx.end(); ++it)
     700              :         {
     701       658655 :           const std::string& init_name = it->first;
     702       658655 :           Import_init* ii = gogo->lookup_init(init_name);
     703       658655 :           import_initvec[it->second] = ii;
     704              :         }
     705              : 
     706              :       // Init graph format is:
     707              :       //
     708              :       //    init_graph <src1> <sink1> <src2> <sink2> ... ;
     709              :       //
     710              :       // where src + sink are init functions indices.
     711              : 
     712      3322940 :       while (!this->match_c_string("\n") && !this->match_c_string(";"))
     713              :         {
     714      3302679 :           this->require_c_string(" ");
     715      3302679 :           std::string src_string = this->read_identifier();
     716      3302679 :           unsigned src;
     717      3302679 :           if (!this->string_to_unsigned(src_string, &src)) return;
     718              : 
     719      3302679 :           this->require_c_string(" ");
     720      3302679 :           std::string sink_string = this->read_identifier();
     721      3302679 :           unsigned sink;
     722      3302679 :           if (!this->string_to_unsigned(sink_string, &sink)) return;
     723              : 
     724      3302679 :           go_assert(src < import_initvec.size());
     725      3302679 :           Import_init* ii_src = import_initvec[src];
     726      3302679 :           go_assert(sink < import_initvec.size());
     727      3302679 :           Import_init* ii_sink = import_initvec[sink];
     728              : 
     729      6605358 :           ii_src->record_precursor_fcn(ii_sink->init_name());
     730      3302679 :         }
     731        20261 :       this->require_semicolon_if_old_version();
     732        20261 :       this->require_c_string("\n");
     733        20261 :     }
     734        21808 : }
     735              : 
     736              : // Import the types.  Starting in export format version 3 all the
     737              : // types are listed first.
     738              : 
     739              : bool
     740        21808 : Import::read_types()
     741              : {
     742        21808 :   this->require_c_string("types ");
     743        21808 :   std::string str = this->read_identifier();
     744        21808 :   int maxp1;
     745        21808 :   if (!this->string_to_int(str, false, &maxp1))
     746              :     return false;
     747              : 
     748        21808 :   this->require_c_string(" ");
     749        21808 :   str = this->read_identifier();
     750        21808 :   int exportedp1;
     751        21808 :   if (!this->string_to_int(str, false, &exportedp1))
     752              :     return false;
     753              : 
     754        21808 :   this->type_offsets_.resize(maxp1, std::make_pair<size_t, size_t>(0, 0));
     755        21808 :   size_t total_type_size = 0;
     756              :   // Start at 1 because type index 0 not used.
     757      3219183 :   for (int i = 1; i < maxp1; i++)
     758              :     {
     759      3197375 :       this->require_c_string(" ");
     760      3197375 :       str = this->read_identifier();
     761      3197375 :       int v;
     762      3197375 :       if (!this->string_to_int(str, false, &v))
     763            0 :         return false;
     764      3197375 :       size_t vs = static_cast<size_t>(v);
     765      3197375 :       this->type_offsets_[i] = std::make_pair(total_type_size, vs);
     766      3197375 :       total_type_size += vs;
     767              :     }
     768              : 
     769        21808 :   this->require_c_string("\n");
     770              : 
     771              :   // Types can refer to each other in an unpredictable order.  Read
     772              :   // all the type data into type_data_.  The type_offsets_ vector we
     773              :   // just initialized provides indexes into type_data_.
     774              : 
     775        21808 :   this->type_pos_ = this->stream_->pos();
     776        21808 :   const char* type_data;
     777        21808 :   if (!this->stream_->peek(total_type_size, &type_data))
     778              :     return false;
     779        21808 :   this->type_data_ = std::string(type_data, total_type_size);
     780        21808 :   this->advance(total_type_size);
     781              : 
     782        21808 :   this->types_.resize(maxp1, NULL);
     783              : 
     784              :   // Parse all the exported types now, so that the names are properly
     785              :   // bound and visible to the parser.  Parse unexported types lazily.
     786              : 
     787              :   // Start at 1 because there is no type 0.
     788       195846 :   for (int i = 1; i < exportedp1; i++)
     789              :     {
     790              :       // We may have already parsed this type when we parsed an
     791              :       // earlier type.
     792       174038 :       Type* type = this->types_[i];
     793       174038 :       if (type == NULL)
     794              :         {
     795       137360 :           if (!this->parse_type(i))
     796              :             return false;
     797       137360 :           type = this->types_[i];
     798       137360 :           go_assert(type != NULL);
     799              :         }
     800       174038 :       Named_type* nt = type->named_type();
     801       174038 :       if (nt == NULL)
     802              :         {
     803            0 :           go_error_at(this->location_,
     804              :                       "error in import data: exported unnamed type %d",
     805              :                       i);
     806            0 :           return false;
     807              :         }
     808       174038 :       nt->set_is_visible();
     809       174038 :       if (this->add_to_globals_)
     810           33 :         this->gogo_->add_named_type(nt);
     811              :     }
     812              : 
     813              :   return true;
     814        21808 : }
     815              : 
     816              : void
     817        21808 : Import::finalize_methods()
     818              : {
     819        21808 :   Finalize_methods finalizer(this->gogo_);
     820        21808 :   Unordered_set(Type*) real_for_named;
     821      3219183 :   for (size_t i = 1; i < this->types_.size(); i++)
     822              :     {
     823      3197375 :       Type* type = this->types_[i];
     824      3197375 :       if (type != NULL && type->named_type() != NULL)
     825              :         {
     826       663173 :           finalizer.type(type);
     827              : 
     828              :           // If the real type is a struct type, we don't want to
     829              :           // finalize its methods.  For a named type defined as a
     830              :           // struct type, we only want to finalize the methods of the
     831              :           // named type.  This is like Finalize_methods::type.
     832       663173 :           Type* real_type = type->named_type()->real_type();
     833      1326346 :           if (real_type->struct_type() != NULL)
     834       422259 :             real_for_named.insert(real_type);
     835              :         }
     836              :     }
     837      3219183 :   for (size_t i = 1; i < this->types_.size(); i++)
     838              :     {
     839      3197375 :       Type* type = this->types_[i];
     840      3197375 :       if (type != NULL
     841      1870394 :           && type->named_type() == NULL
     842      4404596 :           && real_for_named.find(type) == real_for_named.end())
     843       840999 :         finalizer.type(type);
     844              :     }
     845        21808 : }
     846              : 
     847              : // Import a constant.
     848              : 
     849              : void
     850       851537 : Import::import_const()
     851              : {
     852       851537 :   std::string name;
     853       851537 :   Type* type;
     854       851537 :   Expression* expr;
     855       851537 :   Named_constant::import_const(this, &name, &type, &expr);
     856       851537 :   Typed_identifier tid(name, type, this->location_);
     857       851537 :   Named_object* no = this->package_->add_constant(tid, expr);
     858       851537 :   if (this->add_to_globals_)
     859            6 :     this->gogo_->add_dot_import_object(no);
     860       851537 : }
     861              : 
     862              : // Import a type.
     863              : 
     864              : void
     865            0 : Import::import_type()
     866              : {
     867            0 :   if (this->version_ >= EXPORT_FORMAT_V3)
     868              :     {
     869            0 :       if (!this->stream_->saw_error())
     870              :         {
     871            0 :           go_error_at(this->location_,
     872              :                     "error in import data at %d: old type syntax",
     873            0 :                     this->stream_->pos());
     874            0 :           this->stream_->set_saw_error();
     875              :         }
     876            0 :       return;
     877              :     }
     878              : 
     879            0 :   Named_type* type;
     880            0 :   Named_type::import_named_type(this, &type);
     881              : 
     882              :   // The named type has been added to the package by the type import
     883              :   // process.  Here we need to make it visible to the parser, and it
     884              :   // to the global bindings if necessary.
     885            0 :   type->set_is_visible();
     886              : 
     887            0 :   if (this->add_to_globals_)
     888            0 :     this->gogo_->add_named_type(type);
     889              : }
     890              : 
     891              : // Import a variable.
     892              : 
     893              : void
     894       326311 : Import::import_var()
     895              : {
     896       326311 :   std::string name;
     897       326311 :   Package* vpkg;
     898       326311 :   bool is_exported;
     899       326311 :   Type* type;
     900       326311 :   if (!Variable::import_var(this, &name, &vpkg, &is_exported, &type))
     901            0 :     return;
     902       326311 :   if (vpkg == NULL)
     903       292670 :     vpkg = this->package_;
     904       326311 :   if (!is_exported)
     905       193687 :     name = '.' + vpkg->pkgpath() + '.' + name;
     906       326311 :   Variable* var = new Variable(type, NULL, true, false, false,
     907       326311 :                                this->location_);
     908       326311 :   Named_object* no;
     909       326311 :   no = vpkg->add_variable(name, var);
     910       326311 :   if (this->add_to_globals_ && vpkg == this->package_)
     911           24 :     this->gogo_->add_dot_import_object(no);
     912       326311 : }
     913              : 
     914              : // Import a function into PACKAGE.  PACKAGE is normally
     915              : // THIS->PACKAGE_, but it will be different for a method associated
     916              : // with a type defined in a different package.
     917              : 
     918              : void
     919      3055849 : Import::import_func(Package* package)
     920              : {
     921      3055849 :   std::string name;
     922      3055849 :   Package* fpkg;
     923      3055849 :   bool is_exported;
     924      3055849 :   Typed_identifier* receiver;
     925      3055849 :   Typed_identifier_list* parameters;
     926      3055849 :   Typed_identifier_list* results;
     927      3055849 :   bool is_varargs;
     928      3055849 :   bool nointerface;
     929      3055849 :   std::string asm_name;
     930      3055849 :   std::string body;
     931      3055849 :   if (!Function::import_func(this, &name, &fpkg, &is_exported, &receiver,
     932              :                              &parameters, &results, &is_varargs, &nointerface,
     933              :                              &asm_name, &body))
     934              :     return;
     935      3055849 :   if (fpkg == NULL)
     936      2846750 :     fpkg = package;
     937      3055849 :   if (!is_exported)
     938      1448859 :     name = '.' + fpkg->pkgpath() + '.' + name;
     939      3055849 :   Function_type *fntype = Type::make_function_type(receiver, parameters,
     940              :                                                    results, this->location_);
     941      3055849 :   if (is_varargs)
     942        52697 :     fntype->set_is_varargs();
     943              : 
     944      3055849 :   Location loc = this->location_;
     945      3055849 :   Named_object* no;
     946      3055849 :   if (fntype->is_method())
     947              :     {
     948      1784464 :       Type* rtype = receiver->type();
     949              : 
     950              :       // We may still be reading the definition of RTYPE, so we have
     951              :       // to be careful to avoid calling base or convert.  If RTYPE is
     952              :       // a named type or a forward declaration, then we know that it
     953              :       // is not a pointer, because we are reading a method on RTYPE
     954              :       // and named pointers can't have methods.
     955              : 
     956      1784464 :       if (rtype->classification() == Type::TYPE_POINTER)
     957      1351586 :         rtype = rtype->points_to();
     958              : 
     959      1784464 :       if (rtype->is_error_type())
     960              :         return;
     961      1784464 :       else if (rtype->named_type() != NULL)
     962      1784464 :         no = rtype->named_type()->add_method_declaration(name, fpkg, fntype,
     963              :                                                          loc);
     964            0 :       else if (rtype->forward_declaration_type() != NULL)
     965            0 :         no = rtype->forward_declaration_type()->add_method_declaration(name,
     966              :                                                                        fpkg,
     967              :                                                                        fntype,
     968              :                                                                        loc);
     969              :       else
     970            0 :         go_unreachable();
     971              :     }
     972              :   else
     973              :     {
     974      1271385 :       no = fpkg->add_function_declaration(name, fntype, loc);
     975      1271385 :       if (this->add_to_globals_ && fpkg == package)
     976          105 :         this->gogo_->add_dot_import_object(no);
     977              :     }
     978              : 
     979      3055849 :   if (nointerface)
     980            2 :     no->func_declaration_value()->set_nointerface();
     981      3055849 :   if (!asm_name.empty())
     982       112194 :     no->func_declaration_value()->set_asm_name(asm_name);
     983      3055849 :   if (!body.empty() && !no->func_declaration_value()->has_imported_body())
     984       492072 :     no->func_declaration_value()->set_imported_body(this, body);
     985      3055849 : }
     986              : 
     987              : // Read a type definition and initialize the entry in this->types_.
     988              : // This parses the type definition saved by read_types earlier.  This
     989              : // returns true on success, false on failure.
     990              : 
     991              : bool
     992      1976076 : Import::parse_type(int i)
     993              : {
     994      1976076 :   go_assert(i >= 0 && static_cast<size_t>(i) < this->types_.size());
     995      1976076 :   go_assert(this->types_[i] == NULL);
     996      1976076 :   size_t offset = this->type_offsets_[i].first;
     997      1976076 :   size_t len = this->type_offsets_[i].second;
     998              : 
     999      1976076 :   Stream* orig_stream = this->stream_;
    1000              : 
    1001      1976076 :   Stream_from_string_ref stream(this->type_data_, offset, len);
    1002      1976076 :   stream.set_pos(this->type_pos_ + offset);
    1003      1976076 :   this->stream_ = &stream;
    1004              : 
    1005      1976076 :   this->require_c_string("type ");
    1006      1976076 :   std::string str = this->read_identifier();
    1007      1976076 :   int id;
    1008      1976076 :   if (!this->string_to_int(str, false, &id))
    1009              :     {
    1010            0 :       this->stream_ = orig_stream;
    1011            0 :       return false;
    1012              :     }
    1013      1976076 :   if (i != id)
    1014              :     {
    1015            0 :       go_error_at(this->location_,
    1016              :                   ("error in import data at %d: "
    1017              :                    "type ID mismatch: got %d, want %d"),
    1018              :                   stream.pos(), id, i);
    1019            0 :       this->stream_ = orig_stream;
    1020            0 :       return false;
    1021              :     }
    1022              : 
    1023      1976076 :   this->require_c_string(" ");
    1024      1976076 :   if (stream.peek_char() == '"')
    1025              :     {
    1026       663506 :       stream.advance(1);
    1027       663506 :       Type* type = this->read_named_type(i);
    1028       663506 :       if (type->is_error_type())
    1029              :         {
    1030            0 :           this->stream_ = orig_stream;
    1031            0 :           return false;
    1032              :         }
    1033              :     }
    1034              :   else
    1035              :     {
    1036      1312570 :       Type* type = Type::import_type(this);
    1037      1312570 :       if (type->is_error_type())
    1038              :         {
    1039            0 :           this->stream_ = orig_stream;
    1040            0 :           return false;
    1041              :         }
    1042      1312570 :       this->types_[i] = type;
    1043              : 
    1044      1312570 :       this->require_c_string("\n");
    1045              :     }
    1046              : 
    1047      1976076 :   this->stream_ = orig_stream;
    1048      1976076 :   return true;
    1049      1976076 : }
    1050              : 
    1051              : // Read a type in the import stream.  This records the type by the
    1052              : // type index.  If the type is named (which can only happen with older
    1053              : // export formats), it registers the name, but marks it as invisible.
    1054              : 
    1055              : Type*
    1056     12323920 : Import::read_type()
    1057              : {
    1058     12323920 :   Stream* stream = this->stream_;
    1059     12323920 :   this->require_c_string("<type ");
    1060              : 
    1061     12323920 :   std::string number;
    1062     44574173 :   int c;
    1063     32250253 :   while (true)
    1064              :     {
    1065     44574173 :       c = stream->get_char();
    1066     44574173 :       if (c != '-' && (c < '0' || c > '9'))
    1067              :         break;
    1068     32250253 :       number += c;
    1069              :     }
    1070              : 
    1071     12323920 :   int index;
    1072     12323920 :   if (!this->string_to_int(number, true, &index))
    1073            0 :     return Type::make_error_type();
    1074              : 
    1075     12323920 :   if (c == '>')
    1076              :     {
    1077              :       // A reference to a type defined earlier.
    1078     12323920 :       bool parsed;
    1079     12323920 :       return this->type_for_index(index, "import data", stream->pos(),
    1080              :                                   &parsed);
    1081              :     }
    1082              : 
    1083            0 :   if (this->version_ >= EXPORT_FORMAT_V3)
    1084              :     {
    1085            0 :       if (!stream->saw_error())
    1086            0 :         go_error_at(this->location_,
    1087              :                     "error in import data at %d: expected %<>%>",
    1088              :                     stream->pos());
    1089            0 :       stream->set_saw_error();
    1090            0 :       return Type::make_error_type();
    1091              :     }
    1092              : 
    1093            0 :   if (c != ' ')
    1094              :     {
    1095            0 :       if (!stream->saw_error())
    1096            0 :         go_error_at(this->location_,
    1097              :                     "error in import data at %d: expected %< %> or %<>%>",
    1098              :                     stream->pos());
    1099            0 :       stream->set_saw_error();
    1100            0 :       stream->advance(1);
    1101            0 :       return Type::make_error_type();
    1102              :     }
    1103              : 
    1104            0 :   if (index <= 0
    1105            0 :       || (static_cast<size_t>(index) < this->types_.size()
    1106            0 :           && this->types_[index] != NULL))
    1107              :     {
    1108            0 :       go_error_at(this->location_,
    1109              :                   "error in import data at %d: type index already defined",
    1110              :                   stream->pos());
    1111            0 :       stream->set_saw_error();
    1112            0 :       return Type::make_error_type();
    1113              :     }
    1114              : 
    1115            0 :   if (static_cast<size_t>(index) >= this->types_.size())
    1116              :     {
    1117            0 :       int newsize = std::max(static_cast<size_t>(index) + 1,
    1118            0 :                              this->types_.size() * 2);
    1119            0 :       this->types_.resize(newsize, NULL);
    1120              :     }
    1121              : 
    1122            0 :   if (stream->peek_char() != '"')
    1123              :     {
    1124            0 :       Type* type = Type::import_type(this);
    1125            0 :       this->require_c_string(">");
    1126            0 :       this->types_[index] = type;
    1127            0 :       return type;
    1128              :     }
    1129              : 
    1130            0 :   stream->advance(1);
    1131              : 
    1132            0 :   Type* type = this->read_named_type(index);
    1133              : 
    1134            0 :   this->require_c_string(">");
    1135              : 
    1136            0 :   return type;
    1137     12323920 : }
    1138              : 
    1139              : // Read a named type from the import stream and store it in
    1140              : // this->types_[index].  The stream should be positioned immediately
    1141              : // after the '"' that starts the name.
    1142              : 
    1143              : Type*
    1144       663506 : Import::read_named_type(int index)
    1145              : {
    1146       663506 :   Stream* stream = this->stream_;
    1147       663506 :   std::string type_name;
    1148       663506 :   int c;
    1149     10433420 :   while ((c = stream->get_char()) != '"')
    1150      9769914 :     type_name += c;
    1151              : 
    1152              :   // If this type is in the package we are currently importing, the
    1153              :   // name will be .PKGPATH.NAME or simply NAME with no dots.
    1154              :   // Otherwise, a non-hidden symbol will be PKGPATH.NAME and a hidden
    1155              :   // symbol will be .PKGPATH.NAME.
    1156       663506 :   std::string pkgpath;
    1157       663506 :   if (type_name.find('.') != std::string::npos)
    1158              :     {
    1159       489468 :       size_t start = 0;
    1160       489468 :       if (type_name[0] == '.')
    1161       294678 :         start = 1;
    1162       489468 :       size_t dot = type_name.rfind('.');
    1163       489468 :       pkgpath = type_name.substr(start, dot - start);
    1164       489468 :       if (type_name[0] != '.')
    1165       194790 :         type_name.erase(0, dot + 1);
    1166              :     }
    1167              : 
    1168       663506 :   this->require_c_string(" ");
    1169              : 
    1170              :   // The package name may follow.  This is the name of the package in
    1171              :   // the package clause of that package.  The type name will include
    1172              :   // the pkgpath, which may be different.
    1173       663506 :   std::string package_name;
    1174       663506 :   if (stream->peek_char() == '"')
    1175              :     {
    1176            0 :       stream->advance(1);
    1177            0 :       while ((c = stream->get_char()) != '"')
    1178            0 :         package_name += c;
    1179            0 :       this->require_c_string(" ");
    1180              :     }
    1181              : 
    1182       663506 :   bool in_heap = true;
    1183       663506 :   if (this->match_c_string("notinheap"))
    1184              :     {
    1185        23369 :       this->require_c_string("notinheap ");
    1186        23369 :       in_heap = false;
    1187              :     }
    1188              : 
    1189       663506 :   bool is_alias = false;
    1190       663506 :   if (this->match_c_string("= "))
    1191              :     {
    1192        14776 :       stream->advance(2);
    1193        14776 :       is_alias = true;
    1194              :     }
    1195              : 
    1196              :   // Declare the type in the appropriate package.  If we haven't seen
    1197              :   // it before, mark it as invisible.  We declare it before we read
    1198              :   // the actual definition of the type, since the definition may refer
    1199              :   // to the type itself.
    1200       663506 :   Package* package;
    1201       663506 :   if (pkgpath.empty() || pkgpath == this->gogo_->pkgpath())
    1202       174038 :     package = this->package_;
    1203              :   else
    1204              :     {
    1205       489468 :       package = this->gogo_->register_package(pkgpath, "",
    1206              :                                               Linemap::unknown_location());
    1207       489468 :       if (!package_name.empty())
    1208            0 :         package->set_package_name(package_name, this->location());
    1209              :     }
    1210              : 
    1211       663506 :   Named_object* no = package->bindings()->lookup(type_name);
    1212       663506 :   if (no == NULL)
    1213       586329 :     no = package->add_type_declaration(type_name, this->location_);
    1214        77177 :   else if (!no->is_type_declaration() && !no->is_type())
    1215              :     {
    1216            0 :       go_error_at(this->location_, "imported %<%s.%s%> both type and non-type",
    1217            0 :                   pkgpath.c_str(), Gogo::message_name(type_name).c_str());
    1218            0 :       stream->set_saw_error();
    1219            0 :       return Type::make_error_type();
    1220              :     }
    1221              :   else
    1222        77177 :     go_assert(no->package() == package);
    1223              : 
    1224       663506 :   if (this->types_[index] == NULL)
    1225              :     {
    1226       663506 :       if (no->is_type_declaration())
    1227              :         {
    1228              :           // FIXME: It's silly to make a forward declaration every time.
    1229       586329 :           this->types_[index] = Type::make_forward_declaration(no);
    1230              :         }
    1231              :       else
    1232              :         {
    1233        77177 :           go_assert(no->is_type());
    1234        77177 :           this->types_[index] = no->type_value();
    1235              :         }
    1236              :     }
    1237              : 
    1238              :   // If there is no type definition, then this is just a forward
    1239              :   // declaration of a type defined in some other file.
    1240       663506 :   Type* type;
    1241       663506 :   if (this->match_c_string(">") || this->match_c_string("\n"))
    1242              :     {
    1243            0 :       type = this->types_[index];
    1244            0 :       if (!in_heap)
    1245            0 :         go_error_at(this->location_,
    1246              :                     ("import error at %d for type index %d: "
    1247              :                      "forward declaration marked notinheap"),
    1248              :                     this->pos(), index);
    1249              :     }
    1250              :   else
    1251              :     {
    1252       663506 :       if (no->is_type_declaration())
    1253              :         {
    1254              :           // We can define the type now.
    1255              : 
    1256       586329 :           type = this->read_type();
    1257              : 
    1258       586329 :           no = package->add_type(type_name, type, this->location_);
    1259       586329 :           Named_type* ntype = no->type_value();
    1260              : 
    1261              :           // This type has not yet been imported.
    1262       586329 :           ntype->clear_is_visible();
    1263              : 
    1264       586329 :           if (!in_heap)
    1265        23278 :             ntype->set_not_in_heap();
    1266       586329 :           if (is_alias)
    1267        13186 :             ntype->set_is_alias();
    1268              : 
    1269       586329 :           if (!type->is_undefined() && type->interface_type() != NULL)
    1270       136970 :             this->gogo_->record_interface_type(type->interface_type());
    1271              : 
    1272              :           type = ntype;
    1273              :         }
    1274        77177 :       else if (no->is_type())
    1275              :         {
    1276              :           // We have seen this type before.
    1277        77177 :           type = no->type_value();
    1278              : 
    1279              :           // Don't change the visibility of the existing type.
    1280              : 
    1281              :           // For older export versions, we need to skip the type
    1282              :           // definition in the stream.
    1283        77177 :           if (this->version_ < EXPORT_FORMAT_V3)
    1284            0 :             this->read_type();
    1285              :         }
    1286              :       else
    1287            0 :         go_unreachable();
    1288              : 
    1289       663506 :       this->types_[index] = type;
    1290              : 
    1291              :       // Read the type methods.
    1292       663506 :       if (this->match_c_string("\n"))
    1293              :         {
    1294       586329 :           this->advance(1);
    1295      2957122 :           while (this->match_c_string(" func"))
    1296              :             {
    1297      1784464 :               this->advance(1);
    1298      1784464 :               this->import_func(package);
    1299              :             }
    1300              :         }
    1301              :     }
    1302              : 
    1303              :   return type;
    1304       663506 : }
    1305              : 
    1306              : // Return the type given an index.  Set *PARSED if we parsed it here.
    1307              : 
    1308              : Type*
    1309     12347919 : Import::type_for_index(int index, const std::string& input_name,
    1310              :                        size_t input_offset, bool* parsed)
    1311              : {
    1312     12347919 :   *parsed = false;
    1313     12347919 :   if (index >= 0 && !this->type_data_.empty())
    1314              :     {
    1315      6514300 :       if (static_cast<size_t>(index) >= this->type_offsets_.size())
    1316              :         {
    1317            0 :           go_error_at(this->location_,
    1318              :                       "error in %s at %lu: bad type index %d, max %d",
    1319              :                       input_name.c_str(),
    1320              :                       static_cast<unsigned long>(input_offset),
    1321            0 :                       index, static_cast<int>(this->type_offsets_.size()));
    1322            0 :           return Type::make_error_type();
    1323              :         }
    1324              : 
    1325      6514300 :       if (this->types_[index] == NULL)
    1326              :         {
    1327      1838716 :           if (!this->parse_type(index))
    1328            0 :             return Type::make_error_type();
    1329      1838716 :           *parsed = true;
    1330              :         }
    1331              :     }
    1332              : 
    1333     12347919 :   if (index < 0
    1334     12347919 :       ? (static_cast<size_t>(- index) >= this->builtin_types_.size()
    1335      5833619 :          || this->builtin_types_[- index] == NULL)
    1336      6514300 :       : (static_cast<size_t>(index) >= this->types_.size()
    1337      6514300 :          || this->types_[index] == NULL))
    1338              :     {
    1339            0 :       go_error_at(this->location_,
    1340              :                   "error in %s at %lu: bad type index %d",
    1341              :                   input_name.c_str(),
    1342              :                   static_cast<unsigned long>(input_offset), index);
    1343            0 :       return Type::make_error_type();
    1344              :     }
    1345              : 
    1346     12347919 :   return index < 0 ? this->builtin_types_[- index] : this->types_[index];
    1347              : }
    1348              : 
    1349              : // Read an escape note.
    1350              : 
    1351              : std::string
    1352      6290244 : Import::read_escape()
    1353              : {
    1354      6290244 :   if (this->match_c_string(" <esc:"))
    1355              :     {
    1356      2196059 :       Stream* stream = this->stream_;
    1357      2196059 :       this->require_c_string(" <esc:");
    1358              : 
    1359      2196059 :       std::string escape = "esc:";
    1360      9145292 :       int c;
    1361      6949233 :       while (true)
    1362              :         {
    1363      9145292 :           c = stream->get_char();
    1364      9145292 :           if (c != 'x' && !ISXDIGIT(c))
    1365              :             break;
    1366      6949233 :           escape += c;
    1367              :         }
    1368              : 
    1369      2196059 :       if (c != '>')
    1370              :         {
    1371            0 :           go_error_at(this->location(),
    1372              :                       ("error in import data at %d: "
    1373              :                        "expect %< %> or %<>%>, got %c"),
    1374              :                       stream->pos(), c);
    1375            0 :           stream->set_saw_error();
    1376            0 :           stream->advance(1);
    1377            0 :           escape = Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
    1378              :         }
    1379              :       return escape;
    1380              :     }
    1381              :   else
    1382      4094185 :     return Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
    1383              : }
    1384              : 
    1385              : 
    1386              : // Register the builtin types.
    1387              : 
    1388              : void
    1389        21808 : Import::register_builtin_types(Gogo* gogo)
    1390              : {
    1391        21808 :   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
    1392        21808 :   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
    1393        21808 :   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
    1394        21808 :   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
    1395        21808 :   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
    1396        21808 :   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
    1397        21808 :   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
    1398        21808 :   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
    1399        21808 :   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
    1400        21808 :   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
    1401        21808 :   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
    1402        21808 :   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
    1403        21808 :   this->register_builtin_type(gogo, "int", BUILTIN_INT);
    1404        21808 :   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
    1405        21808 :   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
    1406        21808 :   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
    1407        21808 :   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
    1408        21808 :   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
    1409        21808 :   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
    1410        21808 :   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
    1411        21808 :   this->register_builtin_type(gogo, "any", BUILTIN_ANY);
    1412        21808 : }
    1413              : 
    1414              : // Register a single builtin type.
    1415              : 
    1416              : void
    1417       457968 : Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
    1418              : {
    1419       457968 :   Named_object* named_object = gogo->lookup_global(name);
    1420       457968 :   go_assert(named_object != NULL && named_object->is_type());
    1421       457968 :   int index = - static_cast<int>(code);
    1422       457968 :   go_assert(index > 0
    1423              :              && static_cast<size_t>(index) < this->builtin_types_.size());
    1424       457968 :   this->builtin_types_[index] = named_object->type_value();
    1425       457968 : }
    1426              : 
    1427              : // Characters that stop read_identifier.  We base this on the
    1428              : // characters that stop an identifier, without worrying about
    1429              : // characters that are permitted in an identifier.  That lets us skip
    1430              : // UTF-8 parsing.
    1431              : static const char * const identifier_stop = " \n;:,()[]";
    1432              : 
    1433              : // Read an identifier from the stream.
    1434              : 
    1435              : std::string
    1436     27909115 : Import::read_identifier()
    1437              : {
    1438     27909115 :   std::string ret;
    1439     27909115 :   Stream* stream = this->stream_;
    1440    163288820 :   int c;
    1441    298668525 :   while (true)
    1442              :     {
    1443    163288820 :       c = stream->peek_char();
    1444    163288820 :       if (c == -1 || strchr(identifier_stop, c) != NULL)
    1445              :         break;
    1446              : 
    1447              :       // FIXME: Probably we shouldn't accept '.', but that might break
    1448              :       // some existing imports.
    1449    135379705 :       if (c == '.' && stream->match_c_string("..."))
    1450              :         break;
    1451              : 
    1452    135379705 :       ret += c;
    1453    135379705 :       stream->advance(1);
    1454              :     }
    1455     27909115 :   return ret;
    1456              : }
    1457              : 
    1458              : // Read a possibly qualified identifier from IMP.  The qualification
    1459              : // is <pID>, where ID is a package number.  If the name has a leading
    1460              : // '.', it is not exported; otherwise, it is.  Set *NAME, *PKG and
    1461              : // *IS_EXPORTED.  Reports whether the read succeeded.
    1462              : 
    1463              : bool
    1464      3454531 : Import::read_qualified_identifier(Import_expression* imp, std::string* name,
    1465              :                                   Package** pkg, bool* is_exported)
    1466              : {
    1467      3454531 :   *pkg = NULL;
    1468      3454531 :   if (imp->match_c_string("<p"))
    1469              :     {
    1470       246614 :       imp->advance(2);
    1471       246614 :       char buf[50];
    1472       246614 :       char *pbuf = &buf[0];
    1473       958780 :       while (true)
    1474              :         {
    1475       602697 :           int next = imp->peek_char();
    1476       602697 :           if (next == -1 || static_cast<size_t>(pbuf - buf) >= sizeof buf - 1)
    1477            0 :             return false;
    1478       602697 :           if (next == '>')
    1479              :             {
    1480       246614 :               imp->advance(1);
    1481       246614 :               break;
    1482              :             }
    1483       356083 :           *pbuf = static_cast<char>(next);
    1484       356083 :           ++pbuf;
    1485       356083 :           imp->advance(1);
    1486       356083 :         }
    1487              : 
    1488       246614 :       *pbuf = '\0';
    1489       246614 :       char *end;
    1490       246614 :       long index = strtol(buf, &end, 10);
    1491       246614 :       if (*end != '\0'
    1492       246614 :           || index <= 0
    1493       493228 :           || static_cast<size_t>(index) > imp->max_package_index())
    1494            0 :         return false;
    1495              : 
    1496       246614 :       *pkg = imp->package_at_index(index);
    1497       246614 :       go_assert(*pkg != NULL);
    1498              :     }
    1499              : 
    1500      3454531 :   *is_exported = true;
    1501      3454531 :   if (imp->match_c_string("."))
    1502              :     {
    1503      1648177 :       imp->advance(1);
    1504      1648177 :       *is_exported = false;
    1505              :     }
    1506              : 
    1507      3454531 :   *name = imp->read_identifier();
    1508              : 
    1509      3454531 :   return !name->empty();
    1510              : }
    1511              : 
    1512              : // Read a name from the stream.
    1513              : 
    1514              : std::string
    1515      6597967 : Import::read_name()
    1516              : {
    1517      6597967 :   std::string ret = this->read_identifier();
    1518      6597967 :   if (ret == "?")
    1519       625070 :     ret.clear();
    1520      6597967 :   return ret;
    1521              : }
    1522              : 
    1523              : // Read LENGTH bytes from the stream.
    1524              : 
    1525              : void
    1526       506685 : Import::read(size_t length, std::string* out)
    1527              : {
    1528       506685 :   const char* data;
    1529       506685 :   if (!this->stream_->peek(length, &data))
    1530              :     {
    1531            0 :       if (!this->stream_->saw_error())
    1532            0 :         go_error_at(this->location_, "import error at %d: expected %d bytes",
    1533            0 :                     this->stream_->pos(), static_cast<int>(length));
    1534            0 :       this->stream_->set_saw_error();
    1535            0 :       *out = std::string("");
    1536            0 :       return;
    1537              :     }
    1538       506685 :   *out = std::string(data, length);
    1539       506685 :   this->advance(length);
    1540              : }
    1541              : 
    1542              : // Turn a string into a integer with appropriate error handling.
    1543              : 
    1544              : bool
    1545     24146345 : Import::string_to_int(const std::string &s, bool is_neg_ok, int* ret)
    1546              : {
    1547     24146345 :   char* end;
    1548     24146345 :   long prio = strtol(s.c_str(), &end, 10);
    1549     24146345 :   if (*end != '\0' || prio > 0x7fffffff || (prio < 0 && !is_neg_ok))
    1550              :     {
    1551            0 :       go_error_at(this->location_, "invalid integer in import data at %d",
    1552            0 :                   this->stream_->pos());
    1553            0 :       this->stream_->set_saw_error();
    1554            0 :       return false;
    1555              :     }
    1556     24146345 :   *ret = prio;
    1557     24146345 :   return true;
    1558              : }
    1559              : 
    1560              : // Class Import::Stream.
    1561              : 
    1562      1998586 : Import::Stream::Stream()
    1563      1998586 :   : pos_(0), saw_error_(false)
    1564              : {
    1565      1998586 : }
    1566              : 
    1567      1998586 : Import::Stream::~Stream()
    1568              : {
    1569      1998586 : }
    1570              : 
    1571              : // Return the next character to come from the stream.
    1572              : 
    1573              : int
    1574    267521045 : Import::Stream::peek_char()
    1575              : {
    1576    267521045 :   const char* read;
    1577    267521045 :   if (!this->do_peek(1, &read))
    1578              :     return -1;
    1579              :   // Make sure we return an unsigned char, so that we don't get
    1580              :   // confused by \xff.
    1581    267499237 :   unsigned char ret = *read;
    1582    267499237 :   return ret;
    1583              : }
    1584              : 
    1585              : // Return true if the next LENGTH characters from the stream match
    1586              : // BYTES
    1587              : 
    1588              : bool
    1589     60891628 : Import::Stream::match_bytes(const char* bytes, size_t length)
    1590              : {
    1591     60891628 :   const char* read;
    1592     60891628 :   if (!this->do_peek(length, &read))
    1593              :     return false;
    1594     60067051 :   return memcmp(bytes, read, length) == 0;
    1595              : }
    1596              : 
    1597              : // Require that the next LENGTH bytes from the stream match BYTES.
    1598              : 
    1599              : void
    1600     74584897 : Import::Stream::require_bytes(Location location, const char* bytes,
    1601              :                               size_t length)
    1602              : {
    1603     74584897 :   const char* read;
    1604     74584897 :   if (!this->do_peek(length, &read)
    1605     74584897 :       || memcmp(bytes, read, length) != 0)
    1606              :     {
    1607            0 :       if (!this->saw_error_)
    1608            0 :         go_error_at(location, "import error at %d: expected %<%.*s%>",
    1609              :                     this->pos(), static_cast<int>(length), bytes);
    1610            0 :       this->saw_error_ = true;
    1611            0 :       return;
    1612              :     }
    1613     74584897 :   this->advance(length);
    1614              : }
    1615              : 
    1616              : // Class Stream_from_file.
    1617              : 
    1618            0 : Stream_from_file::Stream_from_file(int fd)
    1619            0 :   : fd_(fd), data_()
    1620              : {
    1621            0 :   if (lseek(fd, 0, SEEK_SET) != 0)
    1622              :     {
    1623            0 :       go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
    1624            0 :       this->set_saw_error();
    1625              :     }
    1626            0 : }
    1627              : 
    1628            0 : Stream_from_file::~Stream_from_file()
    1629              : {
    1630            0 :   close(this->fd_);
    1631            0 : }
    1632              : 
    1633              : // Read next bytes.
    1634              : 
    1635              : bool
    1636            0 : Stream_from_file::do_peek(size_t length, const char** bytes)
    1637              : {
    1638            0 :   if (this->data_.length() >= length)
    1639              :     {
    1640            0 :       *bytes = this->data_.data();
    1641            0 :       return true;
    1642              :     }
    1643              : 
    1644            0 :   this->data_.resize(length);
    1645            0 :   ssize_t got = ::read(this->fd_, &this->data_[0], length);
    1646              : 
    1647            0 :   if (got < 0)
    1648              :     {
    1649            0 :       if (!this->saw_error())
    1650            0 :         go_fatal_error(Linemap::unknown_location(), "read failed: %m");
    1651            0 :       this->set_saw_error();
    1652            0 :       return false;
    1653              :     }
    1654              : 
    1655            0 :   if (lseek(this->fd_, - got, SEEK_CUR) < 0)
    1656              :     {
    1657            0 :       if (!this->saw_error())
    1658            0 :         go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
    1659            0 :       this->set_saw_error();
    1660            0 :       return false;
    1661              :     }
    1662              : 
    1663            0 :   if (static_cast<size_t>(got) < length)
    1664              :     return false;
    1665              : 
    1666            0 :   *bytes = this->data_.data();
    1667            0 :   return true;
    1668              : }
    1669              : 
    1670              : // Advance.
    1671              : 
    1672              : void
    1673            0 : Stream_from_file::do_advance(size_t skip)
    1674              : {
    1675            0 :   if (lseek(this->fd_, skip, SEEK_CUR) < 0)
    1676              :     {
    1677            0 :       if (!this->saw_error())
    1678            0 :         go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
    1679            0 :       this->set_saw_error();
    1680              :     }
    1681            0 :   if (!this->data_.empty())
    1682              :     {
    1683            0 :       if (this->data_.length() > skip)
    1684            0 :         this->data_.erase(0, skip);
    1685              :       else
    1686            0 :         this->data_.clear();
    1687              :     }
    1688            0 : }
    1689              : 
    1690              : // Class Import_function_body.
    1691              : 
    1692        12247 : Import_function_body::Import_function_body(Gogo* gogo,
    1693              :                                            Import* imp,
    1694              :                                            Named_object* named_object,
    1695              :                                            const std::string& body,
    1696              :                                            size_t off,
    1697              :                                            Block* block,
    1698        12247 :                                            int indent)
    1699        12247 :     : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
    1700        12247 :       off_(off), indent_(indent), temporaries_(), labels_(),
    1701        12247 :       saw_error_(false)
    1702              : {
    1703        12247 :   this->blocks_.push_back(block);
    1704        12247 : }
    1705              : 
    1706        12247 : Import_function_body::~Import_function_body()
    1707              : {
    1708              :   // At this point we should be left with the original outer block only.
    1709        12247 :   go_assert(saw_errors() || this->blocks_.size() == 1);
    1710        12247 : }
    1711              : 
    1712              : // The name of the function we are parsing.
    1713              : 
    1714              : const std::string&
    1715        23999 : Import_function_body::name() const
    1716              : {
    1717        23999 :   return this->named_object_->name();
    1718              : }
    1719              : 
    1720              : // Class Import_function_body.
    1721              : 
    1722              : // Require that the next bytes match STR, issuing an error if not.
    1723              : // Advance past the string.
    1724              : 
    1725              : void
    1726       213628 : Import_function_body::require_c_string(const char* str)
    1727              : {
    1728       213628 :   if (!this->match_c_string(str))
    1729              :     {
    1730            0 :       if (!this->saw_error_)
    1731            0 :         go_error_at(this->location(),
    1732              :                     "invalid export data for %qs: expected %qs at %lu",
    1733            0 :                     this->name().c_str(), str,
    1734            0 :                     static_cast<unsigned long>(this->off_));
    1735            0 :       this->saw_error_ = true;
    1736            0 :       return;
    1737              :     }
    1738       213628 :   this->advance(strlen(str));
    1739              : }
    1740              : 
    1741              : // Read an identifier.
    1742              : 
    1743              : std::string
    1744        98951 : Import_function_body::read_identifier()
    1745              : {
    1746        98951 :   size_t start = this->off_;
    1747       536275 :   for (size_t i = start; i < this->body_.length(); i++)
    1748              :     {
    1749       536275 :       int c = static_cast<unsigned char>(this->body_[i]);
    1750       536275 :       if (strchr(identifier_stop, c) != NULL)
    1751              :         {
    1752        98657 :           this->off_ = i;
    1753        98657 :           return this->body_.substr(start, i - start);
    1754              :         }
    1755              : 
    1756              :       // FIXME: Probably we shouldn't accept '.', but that might break
    1757              :       // some existing imports.
    1758       437618 :       if (c == '.'
    1759          880 :           && i + 2 < this->body_.length()
    1760          880 :           && this->body_[i + 1] == '.'
    1761       437915 :           && this->body_[i + 2] == '.')
    1762              :         {
    1763          294 :           this->off_ = i;
    1764          294 :           return this->body_.substr(start, i - start);
    1765              :         }
    1766              :     }
    1767            0 :   this->off_ = this->body_.length();
    1768            0 :   return this->body_.substr(start);
    1769              : }
    1770              : 
    1771              : // Read a type.
    1772              : 
    1773              : Type*
    1774        23999 : Import_function_body::read_type()
    1775              : {
    1776        23999 :   this->require_c_string("<type ");
    1777        23999 :   size_t start = this->off_;
    1778        23999 :   size_t i;
    1779        23999 :   int c = '\0';
    1780        86597 :   for (i = start; i < this->body_.length(); ++i)
    1781              :     {
    1782        86597 :       c = static_cast<unsigned char>(this->body_[i]);
    1783        86597 :       if (c != '-' && (c < '0' || c > '9'))
    1784              :         break;
    1785              :     }
    1786        23999 :   this->off_ = i + 1;
    1787              : 
    1788        23999 :   char *end;
    1789        23999 :   std::string num = this->body_.substr(start, i - start);
    1790        23999 :   long val = strtol(num.c_str(), &end, 10);
    1791        23999 :   if (*end != '\0' || val > 0x7fffffff)
    1792              :     {
    1793            0 :       if (!this->saw_error_)
    1794            0 :         go_error_at(this->location(),
    1795              :                     "invalid export data for %qs: expected integer at %lu",
    1796            0 :                     this->name().c_str(),
    1797              :                     static_cast<unsigned long>(start));
    1798            0 :       this->saw_error_ = true;
    1799            0 :       return Type::make_error_type();
    1800              :     }
    1801              : 
    1802        23999 :   if (c != '>')
    1803              :     {
    1804            0 :       if (!this->saw_error_)
    1805            0 :         go_error_at(this->location(),
    1806              :                     "invalid export data for %qs: expected %<>%> at %lu",
    1807            0 :                     this->name().c_str(),
    1808              :                     static_cast<unsigned long>(i));
    1809            0 :       this->saw_error_ = true;
    1810            0 :       return Type::make_error_type();
    1811              :     }
    1812              : 
    1813        23999 :   bool parsed;
    1814        23999 :   Type* type = this->imp_->type_for_index(static_cast<int>(val), this->name(),
    1815              :                                           static_cast<unsigned long>(start),
    1816              :                                           &parsed);
    1817              : 
    1818              :   // If we just read this type's information, its methods will not
    1819              :   // have been finalized.  Do that now.
    1820        23999 :   if (parsed)
    1821          563 :     this->gogo_->finalize_methods_for_type(type);
    1822              : 
    1823              :   return type;
    1824        23999 : }
    1825              : 
    1826              : // Return the next size to use for a vector mapping indexes to values.
    1827              : 
    1828              : size_t
    1829         1378 : Import_function_body::next_size(size_t have)
    1830              : {
    1831         1378 :   if (have == 0)
    1832              :     return 8;
    1833            0 :   else if (have < 256)
    1834            0 :     return have * 2;
    1835              :   else
    1836            0 :     return have + 64;
    1837              : }
    1838              : 
    1839              : // Record the index of a temporary statement.
    1840              : 
    1841              : void
    1842         2661 : Import_function_body::record_temporary(Temporary_statement* temp,
    1843              :                                        unsigned int idx)
    1844              : {
    1845         2661 :   size_t have = this->temporaries_.size();
    1846         3353 :   while (static_cast<size_t>(idx) >= have)
    1847              :     {
    1848          692 :       size_t want = Import_function_body::next_size(have);
    1849          692 :       this->temporaries_.resize(want, NULL);
    1850          692 :       have = want;
    1851              :     }
    1852         2661 :   this->temporaries_[idx] = temp;
    1853         2661 : }
    1854              : 
    1855              : // Return a temporary statement given an index.
    1856              : 
    1857              : Temporary_statement*
    1858         3923 : Import_function_body::temporary_statement(unsigned int idx)
    1859              : {
    1860         3923 :   if (static_cast<size_t>(idx) >= this->temporaries_.size())
    1861              :     return NULL;
    1862         3923 :   return this->temporaries_[idx];
    1863              : }
    1864              : 
    1865              : // Return an unnamed label given an index, defining the label if we
    1866              : // haven't seen it already.
    1867              : 
    1868              : Unnamed_label*
    1869         2955 : Import_function_body::unnamed_label(unsigned int idx, Location loc)
    1870              : {
    1871         2955 :   size_t have = this->labels_.size();
    1872         3641 :   while (static_cast<size_t>(idx) >= have)
    1873              :     {
    1874          686 :       size_t want = Import_function_body::next_size(have);
    1875          686 :       this->labels_.resize(want, NULL);
    1876          686 :       have = want;
    1877              :     }
    1878         2955 :   Unnamed_label* label = this->labels_[idx];
    1879         2955 :   if (label == NULL)
    1880              :     {
    1881         1433 :       label = new Unnamed_label(loc);
    1882         1433 :       this->labels_[idx] = label;
    1883              :     }
    1884         2955 :   return label;
    1885              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.