Skip to content

Commit 677a886

Browse files
committed
format-args: Only pass the format string to the parser.
This fixes an issue we had where the generated code ended with more static pieces than its rustc counterpart. gcc/rust/ChangeLog: * expand/rust-macro-builtins.cc (struct FormatArgsInput): Store the format_str as a string instead of an AST::Expr. (format_args_parse_arguments): Transform format_expr into a format string properly - add note for handling eager macro invocations later on. (MacroBuiltin::format_args_handler): Parse the correct input, append newline to format_str if necessary.
1 parent b4de854 commit 677a886

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

gcc/rust/expand/rust-macro-builtins.cc

+22-15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "expected.h"
2020
#include "libproc_macro_internal/tokenstream.h"
21+
#include "optional.h"
2122
#include "rust-ast-full-decls.h"
2223
#include "rust-builtin-ast-nodes.h"
2324
#include "rust-expand-format-args.h"
@@ -961,7 +962,7 @@ MacroBuiltin::stringify_handler (location_t invoc_locus,
961962

962963
struct FormatArgsInput
963964
{
964-
std::unique_ptr<AST::Expr> format_str;
965+
std::string format_str;
965966
AST::FormatArguments args;
966967
// bool is_literal?
967968
};
@@ -985,12 +986,18 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
985986

986987
auto args = AST::FormatArguments ();
987988
auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
988-
std::unique_ptr<AST::Expr> format_str = nullptr;
989+
std::unique_ptr<AST::Expr> format_expr = nullptr;
989990

990991
// TODO: Handle the case where we're not parsing a string literal (macro
991992
// invocation for e.g.)
992993
if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
993-
format_str = parser.parse_literal_expr ();
994+
format_expr = parser.parse_literal_expr ();
995+
996+
// TODO(Arthur): Clean this up - if we haven't parsed a string literal but a
997+
// macro invocation, what do we do here? return a tl::unexpected?
998+
auto format_str = static_cast<AST::LiteralExpr &> (*format_expr)
999+
.get_literal ()
1000+
.as_string ();
9941001

9951002
// TODO: Allow implicit captures ONLY if the the first arg is a string literal
9961003
// and not a macro invocation
@@ -1053,6 +1060,13 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
10531060
{
10541061
auto input = format_args_parse_arguments (invoc);
10551062

1063+
if (!input)
1064+
{
1065+
rust_error_at (invoc_locus,
1066+
"could not parse arguments to %<format_args!()%>");
1067+
return tl::nullopt;
1068+
}
1069+
10561070
// TODO(Arthur): We need to handle this
10571071
// // if it is not a literal, it's an eager macro invocation - return it
10581072
// if (!fmt_expr->is_literal ())
@@ -1080,20 +1094,13 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
10801094
// rust_unreachable ();
10811095
// }
10821096

1083-
// Remove the delimiters from the macro invocation:
1084-
// the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`,
1085-
// so we pop the front and back to remove the parentheses (or curly brackets,
1086-
// or brackets)
1087-
auto tokens = invoc.get_delim_tok_tree ().to_token_stream ();
1088-
tokens.erase (tokens.begin ());
1089-
tokens.pop_back ();
1097+
bool append_newline = nl == AST::FormatArgs::Newline::Yes;
10901098

1091-
std::stringstream stream;
1092-
for (const auto &tok : tokens)
1093-
stream << tok->as_string () << ' ';
1099+
auto fmt_str = std::move (input->format_str);
1100+
if (append_newline)
1101+
fmt_str += '\n';
10941102

1095-
auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false;
1096-
auto pieces = Fmt::Pieces::collect (stream.str (), append_newline);
1103+
auto pieces = Fmt::Pieces::collect (fmt_str, append_newline);
10971104

10981105
// TODO:
10991106
// do the transformation into an AST::FormatArgs node

0 commit comments

Comments
 (0)