From f6e926a68941cda00086c3ed29523de0c0980b9f Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 6 Mar 2023 09:58:02 +0100 Subject: expand: Add stringify macro Add the stringify macro expansion as well as some tests. gcc/rust/ChangeLog: * ast/rust-macro.cc (builtin_macro_from_string): Add identifier identification. * ast/rust-macro.h (enum class): Add Stringify builtin macro type. * expand/rust-macro-builtins.cc (make_macro_path_str): Add path for builtin stringify macro. (MacroBuiltin::stringify_handler): Add handler for builtin stringify macro. * expand/rust-macro-builtins.h: Add stringify handler's prototype. * util/rust-hir-map.cc (Mappings::insert_macro_def): Add stringify handler to builtin hir map. gcc/testsuite/ChangeLog: * rust/compile/stringify.rs: Add a basic test with some text. * rust/execute/torture/builtin_macro_stringify.rs: Verify the text is left as is without any other macro expansion. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-macro.cc | 3 ++ gcc/rust/ast/rust-macro.h | 1 + gcc/rust/expand/rust-macro-builtins.cc | 33 +++++++++++++++++++++ gcc/rust/expand/rust-macro-builtins.h | 3 ++ gcc/rust/util/rust-hir-map.cc | 1 + gcc/testsuite/rust/compile/stringify.rs | 10 +++++++ .../execute/torture/builtin_macro_stringify.rs | 34 ++++++++++++++++++++++ 7 files changed, 85 insertions(+) create mode 100644 gcc/testsuite/rust/compile/stringify.rs create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_stringify.rs (limited to 'gcc') diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc index b6f8f6c..cb4bae7 100644 --- a/gcc/rust/ast/rust-macro.cc +++ b/gcc/rust/ast/rust-macro.cc @@ -42,6 +42,9 @@ builtin_macro_from_string (const std::string &identifier) if (identifier == "include_str") return BuiltinMacro::IncludeStr; + if (identifier == "stringify") + return BuiltinMacro::Stringify; + if (identifier == "compile_error") return BuiltinMacro::CompileError; diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index be8ed56..f667a0a 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -589,6 +589,7 @@ enum class BuiltinMacro Column, IncludeBytes, IncludeStr, + Stringify, CompileError, Concat, Env, diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index 5f317a0..f30c963 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -58,6 +58,9 @@ make_macro_path_str (AST::BuiltinMacro kind) case AST::BuiltinMacro::IncludeStr: path_str = "include_str"; break; + case AST::BuiltinMacro::Stringify: + path_str = "stringify"; + break; case AST::BuiltinMacro::CompileError: path_str = "compile_error"; break; @@ -845,4 +848,34 @@ MacroBuiltin::line_handler (Location invoc_locus, AST::MacroInvocData &) return AST::Fragment ({line_no}, std::move (tok)); } +AST::Fragment +MacroBuiltin::stringify_handler (Location invoc_locus, + AST::MacroInvocData &invoc) +{ + std::string content; + auto invoc_token_tree = invoc.get_delim_tok_tree (); + auto tokens = invoc_token_tree.to_token_stream (); + + // Tokens stream includes the first and last delimiter + // which we need to skip. + for (auto token = tokens.cbegin () + 1; token < tokens.cend () - 1; token++) + { + // Rust stringify format has no garantees but the reference compiler + // removes spaces before some tokens depending on the lexer's behavior, + // let's mimick some of those behaviors. + auto token_id = (*token)->get_id (); + if (token_id != RIGHT_PAREN && token_id != EXCLAM + && token != tokens.cbegin () + 1) + { + content.push_back (' '); + } + content += (*token)->as_string (); + } + + auto node = AST::SingleASTNode (make_string (invoc_locus, content)); + auto token + = make_token (Token::make_string (invoc_locus, std::move (content))); + return AST::Fragment ({node}, std::move (token)); +} // namespace Rust + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index 6d7a012..ea0f64a 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -79,6 +79,9 @@ public: static AST::Fragment include_str_handler (Location invoc_locus, AST::MacroInvocData &invoc); + static AST::Fragment stringify_handler (Location invoc_locus, + AST::MacroInvocData &invoc); + static AST::Fragment compile_error_handler (Location invoc_locus, AST::MacroInvocData &invoc); diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index a968704..57c0a3c 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -856,6 +856,7 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro) {"column", MacroBuiltin::column_handler}, {"include_bytes", MacroBuiltin::include_bytes_handler}, {"include_str", MacroBuiltin::include_str_handler}, + {"stringify", MacroBuiltin::stringify_handler}, {"compile_error", MacroBuiltin::compile_error_handler}, {"concat", MacroBuiltin::concat_handler}, {"env", MacroBuiltin::env_handler}, diff --git a/gcc/testsuite/rust/compile/stringify.rs b/gcc/testsuite/rust/compile/stringify.rs new file mode 100644 index 0000000..0350a3c --- /dev/null +++ b/gcc/testsuite/rust/compile/stringify.rs @@ -0,0 +1,10 @@ +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +fn main() { + let _a = stringify!(sample text with parenthesis () and things! This will become a "string".); +} diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_stringify.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_stringify.rs new file mode 100644 index 0000000..e6f4a33 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/builtin_macro_stringify.rs @@ -0,0 +1,34 @@ +// { dg-output "a! ()" } +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +macro_rules! a { + () => { + " foo" + }; +} + +extern "C" { + fn printf(fmt: *const i8, ...); +} + +fn print(s: &str) { + unsafe { + printf( + "%s" as *const str as *const i8, + s as *const str as *const i8, + ); + } +} + +fn main() -> i32 { + let a = stringify!(a!()); + + print(a); + + 0 +} -- cgit v1.1