aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorLiam Naddell <liamnprg@gmail.com>2025-01-30 20:51:21 -0500
committerCohenArthur <arthur.cohen@embecosm.com>2025-01-31 15:44:25 +0000
commit761d424d2a7af38aacad9ffd5b5132fcf286ac2e (patch)
tree01cc83831b41d9365a22fc2b0b1540dbfb82d7fe /gcc/rust
parent51a2da3d567dfbc70e9407276dfabc0b963ad420 (diff)
downloadgcc-761d424d2a7af38aacad9ffd5b5132fcf286ac2e.zip
gcc-761d424d2a7af38aacad9ffd5b5132fcf286ac2e.tar.gz
gcc-761d424d2a7af38aacad9ffd5b5132fcf286ac2e.tar.bz2
Add option_env! support
gcc/rust/ChangeLog: * expand/rust-macro-builtins-utility.cc: Add macro expansion for option_env with eager expansion * expand/rust-macro-builtins.cc: Add option_env to builtin list * expand/rust-macro-builtins.h: Add option_env handler to header file * resolve/rust-late-name-resolver-2.0.cc: Prevent NR2.0 from recursing into lang-item segments gcc/testsuite/ChangeLog: * rust/compile/macros/builtin/option_env1.rs: Add success case for option_env * rust/compile/macros/builtin/option_env2.rs: Add failure case for option_env * rust/execute/torture/builtin_macro_option_env.rs: Add execution case for option_env
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/expand/rust-macro-builtins-utility.cc78
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc2
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h4
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc2
4 files changed, 85 insertions, 1 deletions
diff --git a/gcc/rust/expand/rust-macro-builtins-utility.cc b/gcc/rust/expand/rust-macro-builtins-utility.cc
index ff64879..28829a1 100644
--- a/gcc/rust/expand/rust-macro-builtins-utility.cc
+++ b/gcc/rust/expand/rust-macro-builtins-utility.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-fmt.h"
+#include "rust-ast-builder.h"
#include "rust-macro-builtins.h"
#include "rust-macro-builtins-helpers.h"
@@ -226,6 +227,83 @@ MacroBuiltin::env_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
return AST::Fragment ({node}, std::move (tok));
}
+/* Expand builtin macro option_env!(), which inspects an environment variable at
+ compile time. */
+tl::optional<AST::Fragment>
+MacroBuiltin::option_env_handler (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon)
+{
+ auto invoc_token_tree = invoc.get_delim_tok_tree ();
+ MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+
+ auto last_token_id = macro_end_token (invoc_token_tree, parser);
+ std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;
+ bool has_error = false;
+
+ auto start = lex.get_offs ();
+ auto expanded_expr = try_expand_many_expr (parser, last_token_id,
+ invoc.get_expander (), has_error);
+ auto end = lex.get_offs ();
+
+ auto tokens = lex.get_token_slice (start, end);
+
+ if (has_error)
+ return AST::Fragment::create_error ();
+
+ auto pending = check_for_eager_invocations (expanded_expr);
+ if (!pending.empty ())
+ return make_eager_builtin_invocation (BuiltinMacro::OptionEnv, invoc_locus,
+ invoc_token_tree,
+ std::move (pending));
+
+ if (expanded_expr.size () != 1)
+ {
+ rust_error_at (invoc_locus, "%<option_env!%> takes 1 argument");
+ return AST::Fragment::create_error ();
+ }
+
+ if (expanded_expr.size () > 0)
+ if (!(lit_expr
+ = try_extract_string_literal_from_fragment (invoc_locus,
+ expanded_expr[0])))
+ return AST::Fragment::create_error ();
+
+ parser.skip_token (last_token_id);
+
+ auto env_value = getenv (lit_expr->as_string ().c_str ());
+ AST::Builder b (invoc_locus);
+
+ if (env_value == nullptr)
+ {
+ auto none_expr = std::unique_ptr<AST::Expr> (
+ new AST::PathInExpression (LangItem::Kind::OPTION_NONE, {},
+ invoc_locus));
+
+ auto node = AST::SingleASTNode (std::move (none_expr));
+ std::vector<AST::SingleASTNode> nodes;
+ nodes.push_back (node);
+
+ return AST::Fragment (nodes, std::vector<std::unique_ptr<AST::Token>> ());
+ }
+ std::vector<std::unique_ptr<AST::Expr>> args;
+ args.push_back (b.literal_string (env_value));
+
+ std::unique_ptr<AST::Expr> some_expr
+ = b.call (std::unique_ptr<AST::Expr> (
+ new AST::PathInExpression (LangItem::Kind::OPTION_SOME, {},
+ invoc_locus)),
+ std::move (args));
+
+ auto node = AST::SingleASTNode (std::move (some_expr));
+
+ std::vector<AST::SingleASTNode> nodes;
+ nodes.push_back (node);
+
+ return AST::Fragment (nodes, std::vector<std::unique_ptr<AST::Token>> ());
+}
+
tl::optional<AST::Fragment>
MacroBuiltin::cfg_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon)
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 07a1f3c..59b8f6a 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -120,8 +120,8 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)},
{"asm", inline_asm_maker (AST::AsmKind::Inline)},
{"global_asm", inline_asm_maker (AST::AsmKind::Global)},
+ {"option_env", MacroBuiltin::option_env_handler},
/* Unimplemented macro builtins */
- {"option_env", MacroBuiltin::sorry},
{"concat_idents", MacroBuiltin::sorry},
{"module_path", MacroBuiltin::sorry},
{"log_syntax", MacroBuiltin::sorry},
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index b0c4a64..1d17b43 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -159,6 +159,10 @@ public:
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
+ static tl::optional<AST::Fragment>
+ option_env_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon);
+
static tl::optional<AST::Fragment> cfg_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index b0364d1..ec20e9a 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -254,6 +254,8 @@ Late::visit (AST::PathInExpression &expr)
// TODO: How do we have a nice error with `can't capture dynamic environment
// in a function item` error here?
// do we emit it in `get<Namespace::Labels>`?
+ if (expr.is_lang_item ())
+ return;
auto resolved
= ctx.values.resolve_path (expr.get_segments ()).or_else ([&] () {