diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-08-12 15:06:52 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-12 15:06:52 +0000 |
commit | 3610c9b202b3197bd92ce7b8dbabcb86d4641ee6 (patch) | |
tree | a8be78ea928d605ce6ea8f29a896fcbb48f42af4 /gcc | |
parent | 7be0232c686a75f98b2ca3c27f7de3139b8999c6 (diff) | |
parent | b4993a629348279023b2c0159169ed62f10ac453 (diff) | |
download | gcc-3610c9b202b3197bd92ce7b8dbabcb86d4641ee6.zip gcc-3610c9b202b3197bd92ce7b8dbabcb86d4641ee6.tar.gz gcc-3610c9b202b3197bd92ce7b8dbabcb86d4641ee6.tar.bz2 |
Merge #613
613: Resolve module filename r=philberty a=CohenArthur
This PR is a first attempt at resolving the filename corresponding to an external module correctly. Some of the cases are not handled yet and a lot of FIXMEs are still here, as I am looking for feedback on certain things:
* Am I correct in assuming that we have to go through directories the C way because we are using C++11 and the `filesystem` header is not available until C++17? Is there some gcc abstraction for this that I'm overlooking?
* How important is the existence of a separate SEPARATOR macro for Windows? From what I'm understanding, the OS also understands normal slashes `/` on top of the backward slashes it usually uses `\`. I don't know what happens when they are mixed and matched or how the file system handles it.
* For review simplicity, outer attributes could be accessed in a later PR. I believe they can already be accessed and looked at but haven't looked into it. I'm also unsure if this would be the right place to implement that outer_attr lookup
Co-authored-by: CohenArthur <arthur.cohen@epita.fr>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 70 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 13 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 4 | ||||
-rw-r--r-- | gcc/rust/lex/rust-lex.h | 5 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 5 | ||||
-rw-r--r-- | gcc/rust/rust-system.h | 8 |
6 files changed, 99 insertions, 6 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index dfd9cdb..6033ce9 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -17,6 +17,9 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +// FIXME: This does not work on Windows +#include <unistd.h> + #include "rust-ast-full.h" #include "rust-diagnostics.h" #include "rust-ast-visitor.h" @@ -4050,6 +4053,73 @@ Module::add_crate_name (std::vector<std::string> &names) const item->add_crate_name (names); } +static bool +file_exists (const std::string path) +{ + // Simply check if the file exists + // FIXME: This does not work on Windows + return access (path.c_str (), F_OK) != -1; +} + +// FIXME: This function should also check if the module has a `path` outer +// attribute and fetch the path from here in that case, i.e: +// ``` +// #[path="<dir>/<subdir>/<file>.rs"] +// mod <mod_name>; +// ``` +std::string +Module::get_filename () +{ + rust_assert (kind == Module::ModuleKind::UNLOADED); + + // This corresponds to the path of the file 'including' the module. So the + // file that contains the 'mod <file>;' directive + std::string including_fname (outer_filename); + + std::string expected_file_path = module_name + ".rs"; + std::string expected_dir_path = "mod.rs"; + + auto dir_slash_pos = including_fname.rfind (file_separator); + std::string current_directory_name; + + // If we haven't found a file_separator, then we have to look for files in the + // current directory ('.') + if (dir_slash_pos == std::string::npos) + current_directory_name = std::string (".") + file_separator; + else + current_directory_name + = including_fname.substr (0, dir_slash_pos) + file_separator; + + // FIXME: We also have to search for + // <directory>/<including_fname>/<module_name>.rs In rustc, this is done via + // the concept of `DirOwnernship`, which is based on whether or not the + // current file is titled `mod.rs`. + + // First, we search for <directory>/<module_name>.rs + bool file_mod_found + = file_exists (current_directory_name + expected_file_path); + + // Then, search for <directory>/<module_name>/mod.rs + current_directory_name += module_name + file_separator; + bool dir_mod_found = file_exists (current_directory_name + expected_dir_path); + + bool multiple_candidates_found = file_mod_found && dir_mod_found; + bool no_candidates_found = !file_mod_found && !dir_mod_found; + + if (multiple_candidates_found) + rust_error_at (locus, + "two candidates found for module %s: %s.rs and %s%smod.rs", + module_name.c_str (), module_name.c_str (), + module_name.c_str (), file_separator); + + if (no_candidates_found) + rust_error_at (locus, "no candidate found for module %s", + module_name.c_str ()); + + return file_mod_found ? expected_file_path + : current_directory_name + expected_dir_path; +} + void Attribute::parse_attr_to_meta_item () { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 32fb56f..dac76f5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -977,6 +977,8 @@ private: Location locus; ModuleKind kind; + // Name of the file including the module + std::string outer_filename; // bool has_inner_attrs; std::vector<Attribute> inner_attrs; // bool has_items; @@ -998,10 +1000,11 @@ public: // Unloaded module constructor Module (Identifier module_name, Visibility visibility, - std::vector<Attribute> outer_attrs, Location locus) + std::vector<Attribute> outer_attrs, Location locus, + std::string outer_filename) : VisItem (std::move (visibility), std::move (outer_attrs)), module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED), - inner_attrs (std::vector<Attribute> ()), + outer_filename (outer_filename), inner_attrs (std::vector<Attribute> ()), items (std::vector<std::unique_ptr<Item>> ()) {} @@ -1013,7 +1016,8 @@ public: std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : VisItem (std::move (visibility), std::move (outer_attrs)), module_name (name), locus (locus), kind (ModuleKind::LOADED), - inner_attrs (std::move (inner_attrs)), items (std::move (items)) + outer_filename (std::string ()), inner_attrs (std::move (inner_attrs)), + items (std::move (items)) {} // Copy constructor with vector clone @@ -1049,6 +1053,9 @@ public: return *this; } + // Search for the filename associated with an external module + std::string get_filename (); + void accept_vis (ASTVisitor &vis) override; /* Override that runs the function recursively on all items contained within diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 0a25471..4998dc8 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -2036,6 +2036,10 @@ public: return; } } + else + { + std::string mod_file = module.get_filename (); + } // strip items if required expand_pointer_allow_strip (module.get_items ()); diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index 902745f..1b37a9c 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -14,6 +14,7 @@ struct RAIIFile { private: FILE *file; + const char *filename; void close () { @@ -22,7 +23,7 @@ private: } public: - RAIIFile (const char *filename) + RAIIFile (const char *filename) : filename (filename) { if (strcmp (filename, "-") == 0) file = stdin; @@ -47,6 +48,7 @@ public: ~RAIIFile () { close (); } FILE *get_raw () { return file; } + const char *get_filename () { return filename; } }; class Lexer @@ -136,6 +138,7 @@ public: void split_current_token (TokenId new_left, TokenId new_right); Linemap *get_line_map () { return line_map; } + std::string get_filename () { return std::string (input.get_filename ()); } private: // File for use as input. diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index c94c637..731e0b3 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2101,10 +2101,11 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis, case SEMICOLON: lexer.skip_token (); + // Construct an external module return std::unique_ptr<AST::Module> ( new AST::Module (std::move (name), std::move (vis), - std::move (outer_attrs), - locus)); // module name? + std::move (outer_attrs), locus, + lexer.get_filename ())); case LEFT_CURLY: { lexer.skip_token (); diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index d62e676..40bca63 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -59,6 +59,14 @@ #include "diagnostic-core.h" /* For error_at and friends. */ #include "intl.h" /* For _(). */ +// File separator to use based on whether or not the OS we're working with is +// DOS-based +#if defined(HAVE_DOS_BASED_FILE_SYSTEM) +constexpr static const char *file_separator = "\\"; +#else +constexpr static const char *file_separator = "/"; +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ + // When using gcc, rust_assert is just gcc_assert. #define rust_assert(EXPR) gcc_assert (EXPR) |