diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.cc | 56 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.h | 3 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.h | 13 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 1 |
4 files changed, 73 insertions, 0 deletions
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index 8c68a7d..fb30241 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -412,4 +412,60 @@ MacroBuiltin::cfg (Location invoc_locus, AST::MacroInvocData &invoc) return AST::ASTFragment ({literal_exp}); } +/* Expand builtin macro include!(), which includes a source file at the current + scope compile time. */ + +AST::ASTFragment +MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc) +{ + /* Get target filename from the macro invocation, which is treated as a path + relative to the include!-ing file (currently being compiled). */ + auto lit_expr + = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus); + if (lit_expr == nullptr) + return AST::ASTFragment::create_error (); + + std::string filename + = source_relative_path (lit_expr->as_string (), invoc_locus); + auto target_filename + = Rust::Session::get_instance ().include_extra_file (std::move (filename)); + + RAIIFile target_file (target_filename); + Linemap *linemap = Session::get_instance ().linemap; + + if (target_file.get_raw () == nullptr) + { + rust_error_at (lit_expr->get_locus (), + "cannot open included file %qs: %m", target_filename); + return AST::ASTFragment::create_error (); + } + + rust_debug ("Attempting to parse included file %s", target_filename); + + Lexer lex (target_filename, std::move (target_file), linemap); + Parser<Lexer> parser (std::move (lex)); + + auto parsed_items = parser.parse_items (); + bool has_error = !parser.get_errors ().empty (); + + for (const auto &error : parser.get_errors ()) + error.emit_error (); + + if (has_error) + { + // inform the user that the errors above are from a included file + rust_inform (invoc_locus, "included from here"); + return AST::ASTFragment::create_error (); + } + + std::vector<AST::SingleASTNode> nodes{}; + for (auto &item : parsed_items) + { + AST::SingleASTNode node (std::move (item)); + nodes.push_back (node); + } + + return AST::ASTFragment (nodes); +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index e284c03..f1d10df 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -95,6 +95,9 @@ public: static AST::ASTFragment cfg (Location invoc_locus, AST::MacroInvocData &invoc); + + static AST::ASTFragment include (Location invoc_locus, + AST::MacroInvocData &invoc); }; } // namespace Rust diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 6fa83d9..0c15711 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -235,6 +235,10 @@ struct Session * every file so eh. */ std::string injected_crate_name; + /* extra files get included during late stages of compilation (e.g. macro + * expansion) */ + std::vector<std::string> extra_files; + // backend wrapper to GCC GENERIC Backend *backend; @@ -267,6 +271,15 @@ public: void parse_files (int num_files, const char **files); void init_options (); + /* This function saves the filename data into the session manager using the + * `move` semantics, and returns a C-style string referencing the input + * std::string */ + inline const char *include_extra_file (std::string filename) + { + extra_files.push_back (std::move (filename)); + return extra_files.back ().c_str (); + } + private: Session () = default; void parse_file (const char *filename); diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index e9ad87c..b08258c 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -757,6 +757,7 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro) {"concat", MacroBuiltin::concat}, {"env", MacroBuiltin::env}, {"cfg", MacroBuiltin::cfg}, + {"include", MacroBuiltin::include}, }; auto builtin = builtin_macros.find (macro->get_rule_name ()); |