// Copyright (C) 2020-2023 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . // rust-linemap.cc -- GCC implementation of Linemap. #include "rust-linemap.h" // This class implements the Linemap interface defined by the // frontend. class Gcc_linemap : public Linemap { public: Gcc_linemap () : Linemap (), in_file_ (false) {} void start_file (const char *file_name, unsigned int line_begin); void start_line (unsigned int line_number, unsigned int line_size); Location get_location (unsigned int column); void stop (); std::string to_string (Location); std::string location_file (Location); int location_line (Location); int location_column (Location); protected: Location get_predeclared_location (); Location get_unknown_location (); bool is_predeclared (Location); bool is_unknown (Location); private: // Whether we are currently reading a file. bool in_file_; }; Linemap *Linemap::instance_ = NULL; // Start getting locations from a new file. void Gcc_linemap::start_file (const char *file_name, unsigned line_begin) { if (this->in_file_) linemap_add (line_table, LC_LEAVE, 0, NULL, 0); linemap_add (line_table, LC_ENTER, 0, file_name, line_begin); this->in_file_ = true; } // Stringify a location std::string Gcc_linemap::to_string (Location location) { const line_map_ordinary *lmo; location_t resolved_location; // Screen out unknown and predeclared locations; produce output // only for simple file:line locations. resolved_location = linemap_resolve_location (line_table, location.gcc_location (), LRK_SPELLING_LOCATION, &lmo); if (lmo == NULL || resolved_location < RESERVED_LOCATION_COUNT) return ""; const char *path = LINEMAP_FILE (lmo); if (!path) return ""; // Strip the source file down to the base file, to reduce clutter. std::stringstream ss; ss << lbasename (path) << ":" << SOURCE_LINE (lmo, location.gcc_location ()) << ":" << SOURCE_COLUMN (lmo, location.gcc_location ()); return ss.str (); } // Return the file name for a given location. std::string Gcc_linemap::location_file (Location loc) { return LOCATION_FILE (loc.gcc_location ()); } // Return the line number for a given location. int Gcc_linemap::location_line (Location loc) { return LOCATION_LINE (loc.gcc_location ()); } // Return the column number for a given location. int Gcc_linemap::location_column (Location loc) { return LOCATION_COLUMN (loc.gcc_location ()); } // Stop getting locations. void Gcc_linemap::stop () { linemap_add (line_table, LC_LEAVE, 0, NULL, 0); this->in_file_ = false; } // Start a new line. void Gcc_linemap::start_line (unsigned lineno, unsigned linesize) { linemap_line_start (line_table, lineno, linesize); } // Get a location. Location Gcc_linemap::get_location (unsigned column) { return Location (linemap_position_for_column (line_table, column)); } // Get the unknown location. Location Gcc_linemap::get_unknown_location () { return Location (UNKNOWN_LOCATION); } // Get the predeclared location. Location Gcc_linemap::get_predeclared_location () { return Location (BUILTINS_LOCATION); } // Return whether a location is the predeclared location. bool Gcc_linemap::is_predeclared (Location loc) { return loc.gcc_location () == BUILTINS_LOCATION; } // Return whether a location is the unknown location. bool Gcc_linemap::is_unknown (Location loc) { return loc.gcc_location () == UNKNOWN_LOCATION; } // Return the Linemap to use for the gcc backend. Linemap * rust_get_linemap () { return new Gcc_linemap; } RichLocation::RichLocation (Location root) : gcc_rich_loc (line_table, root.gcc_location ()) { /*rich_location (line_maps *set, location_t loc, const range_label *label = NULL);*/ } RichLocation::~RichLocation () {} void RichLocation::add_range (Location loc) { gcc_rich_loc.add_range (loc.gcc_location ()); } void RichLocation::add_fixit_insert_before (const std::string &new_parent) { gcc_rich_loc.add_fixit_insert_before (new_parent.c_str ()); } void RichLocation::add_fixit_insert_before (Location where, const std::string &new_parent) { gcc_rich_loc.add_fixit_insert_before (where.gcc_location (), new_parent.c_str ()); } void RichLocation::add_fixit_insert_after (const std::string &new_parent) { gcc_rich_loc.add_fixit_insert_after (new_parent.c_str ()); } void RichLocation::add_fixit_insert_after (Location where, const std::string &new_parent) { gcc_rich_loc.add_fixit_insert_after (where.gcc_location (), new_parent.c_str ()); }