aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-08-12 15:06:52 +0000
committerGitHub <noreply@github.com>2021-08-12 15:06:52 +0000
commit3610c9b202b3197bd92ce7b8dbabcb86d4641ee6 (patch)
treea8be78ea928d605ce6ea8f29a896fcbb48f42af4 /gcc
parent7be0232c686a75f98b2ca3c27f7de3139b8999c6 (diff)
parentb4993a629348279023b2c0159169ed62f10ac453 (diff)
downloadgcc-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.cc70
-rw-r--r--gcc/rust/ast/rust-item.h13
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc4
-rw-r--r--gcc/rust/lex/rust-lex.h5
-rw-r--r--gcc/rust/parse/rust-parse-impl.h5
-rw-r--r--gcc/rust/rust-system.h8
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)