On 11/07/2021 21:10, Mark Wielaard wrote:
> Remove (unused) comment related tokens and replace them with
> INNER_DOC_COMMENT and OUTER_DOC_COMMENT tokens, which keep the comment
> text as a string. These can be constructed with the new
> make_inner_doc_comment and make_outer_doc_comment methods.
>
> Make sure to not confuse doc strings with normal comments in the lexer
> when detecting shebang lines. Both single line //! and /*! */ blocks
> are turned into INNER_DOC_COMMENT tokens. And both single line /// and
> /** */ blocks are turned into OUTER_DOC_COMMENT tokens.
>
> Also fixes some issues with cr/lf line endings and keeping the line
> map correct when seeing \n in a comment.
>
> In the parser handle INNER_DOC_COMMENT and OUTER_DOC_COMMENTS where
> inner (#[]) and outer (#![]) attributes are handled. Add a method
> parse_doc_comment which turns the tokens into an "doc" Attribute with
> the string as literal expression.
>
> Add get_locus method to Attribute class for better error reporting.
>
> Tests are added for correctly placed and formatted doc strings, with
> or without cr/lf line endings. Incorrect formatted (isolated CRs) doc
> strings and badly placed inner doc strings. No tests add handling of
> the actual doc attributes yet. These could be tested once we add
> support for the #![warn(missing_docs)] attribute.
> ---
> gcc/rust/ast/rust-ast.h | 2 +
> gcc/rust/lex/rust-lex.cc | 214 ++++++++++++++++--
> gcc/rust/lex/rust-token.h | 25 +-
> gcc/rust/parse/rust-parse-impl.h | 60 ++++-
> gcc/rust/parse/rust-parse.h | 1 +
> gcc/testsuite/rust/compile/bad_inner_doc.rs | 15 ++
> .../compile/doc_isolated_cr_block_comment.rs | 3 +
> .../doc_isolated_cr_inner_block_comment.rs | 5 +
> .../doc_isolated_cr_inner_line_comment.rs | 5 +
> .../compile/doc_isolated_cr_line_comment.rs | 3 +
> .../torture/all_doc_comment_line_blocks.rs | 47 ++++
> .../all_doc_comment_line_blocks_crlf.rs | 47 ++++
> .../torture/isolated_cr_block_comment.rs | 2 +
> .../torture/isolated_cr_line_comment.rs | 2 +
> 14 files changed, 401 insertions(+), 30 deletions(-)
> create mode 100644 gcc/testsuite/rust/compile/bad_inner_doc.rs
> create mode 100644
> gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
> create mode 100644
> gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
> create mode 100644
> gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
> create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
> create mode 100644
> gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
> create mode 100644
> gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
> create mode 100644
> gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
> create mode 100644
> gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
>
> diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
> index 75b08f8aa66..3e3e185b9b5 100644
> --- a/gcc/rust/ast/rust-ast.h
> +++ b/gcc/rust/ast/rust-ast.h
> @@ -455,6 +455,8 @@ public:
> // Returns whether the attribute is considered an "empty" attribute.
> bool is_empty () const { return attr_input == nullptr && path.is_empty ();
> }
>
> + Location get_locus () const { return locus; }
> +
> /* e.g.:
> #![crate_type = "lib"]
> #[test]
> diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
> index 617dd69a080..0b8a8eae651 100644
> --- a/gcc/rust/lex/rust-lex.cc
> +++ b/gcc/rust/lex/rust-lex.cc
> @@ -265,9 +265,16 @@ Lexer::build_token ()
> int next_char = peek_input (n);
> if (is_whitespace (next_char))
> n++;
> - else if (next_char == '/' && peek_input (n + 1) == '/')
> + else if ((next_char == '/' && peek_input (n + 1) == '/'
> + && peek_input (n + 2) != '!'
> + && peek_input (n + 2) != '/')
> + || (next_char == '/' && peek_input (n + 1) == '/'
> + && peek_input (n + 2) == '/'
> + && peek_input (n + 3) == '/'))
> {
> + // two // or four ////
> // A single line comment
> + // (but not an inner or outer doc comment)
> n += 2;
> next_char = peek_input (n);
> while (next_char != '\n' && next_char != EOF)
> @@ -278,9 +285,30 @@ Lexer::build_token ()
> if (next_char == '\n')
> n++;
> }
> - else if (next_char == '/' && peek_input (n + 1) == '*')
> + else if (next_char == '/' && peek_input (n + 1) == '*'
> + && peek_input (n + 2) == '*'
> + && peek_input (n + 3) == '/')
> {
> + /**/
> + n += 4;
> + }
> + else if (next_char == '/' && peek_input (n + 1) == '*'
> + && peek_input (n + 2) == '*' && peek_input (n + 3) == '*'
> + && peek_input (n + 4) == '/')
> + {
> + /***/
> + n += 5;
> + }
> + else if ((next_char == '/' && peek_input (n + 1) == '*'
> + && peek_input (n + 2) != '*'
> + && peek_input (n + 2) != '!')
> + || (next_char == '/' && peek_input (n + 1) == '*'
> + && peek_input (n + 2) == '*'
> + && peek_input (n + 3) == '*'))
> + {
> + // one /* or three /***
> // Start of a block comment
> + // (but not an inner or outer doc comment)
> n += 2;
> int level = 1;
> while (level > 0)
> @@ -339,6 +367,9 @@ Lexer::build_token ()
> // tell line_table that new line starts
> line_map->start_line (current_line, max_column_hint);
> continue;
> + case '\r': // cr
> + // Ignore, we expect a newline (lf) soon.
> + continue;
> case ' ': // space
> current_column++;
> continue;
> @@ -445,11 +476,14 @@ Lexer::build_token ()
>
> return Token::make (DIV_EQ, loc);
> }
> - else if (peek_input () == '/')
> + else if ((peek_input () == '/' && peek_input (1) != '!'
> + && peek_input (1) != '/')
> + || (peek_input () == '/' && peek_input (1) == '/'
> + && peek_input (2) == '/'))
> {
> - // TODO: single-line doc comments
> -
> + // two // or four ////
> // single line comment
> + // (but not an inner or outer doc comment)
> skip_input ();
> current_column += 2;
>
> @@ -461,23 +495,85 @@ Lexer::build_token ()
> current_char = peek_input ();
> }
> continue;
> - break;
> }
> - else if (peek_input () == '*')
> + else if (peek_input () == '/'
> + && (peek_input (1) == '!' || peek_input (1) == '/'))
> {
> + /* single line doc comment, inner or outer. */
> + bool is_inner = peek_input (1) == '!';
> + skip_input (1);
> + current_column += 3;
> +
> + std::string str;
> + str.reserve (32);
> + current_char = peek_input ();
> + while (current_char != '\n')
> + {
> + skip_input ();
> + if (current_char == '\r')
> + {
> + char next_char = peek_input ();
> + if (next_char == '\n')
> + {
> + current_char = '\n';
> + break;
> + }
> + rust_error_at (
> + loc, "Isolated CR %<\\r%> not allowed in doc comment");
> + current_char = next_char;
> + continue;
> + }
> + if (current_char == EOF)
> + {
> + rust_error_at (
> + loc, "unexpected EOF while looking for end of comment");
> + break;
> + }
> + str += current_char;
> + current_char = peek_input ();
> + }
> + skip_input ();
> + current_line++;
> + current_column = 1;
> + // tell line_table that new line starts
> + line_map->start_line (current_line, max_column_hint);
> +
> + str.shrink_to_fit ();
> + if (is_inner)
> + return Token::make_inner_doc_comment (loc, std::move (str));
> + else
> + return Token::make_outer_doc_comment (loc, std::move (str));
> + }
> + else if (peek_input () == '*' && peek_input (1) == '*'
> + && peek_input (2) == '/')
> + {
> + /**/
> + skip_input (2);
> + current_column += 4;
> + continue;
> + }
> + else if (peek_input () == '*' && peek_input (1) == '*'
> + && peek_input (2) == '*' && peek_input (3) == '/')
> + {
> + /***/
> + skip_input (3);
> + current_column += 5;
> + continue;
> + }
> + else if ((peek_input () == '*' && peek_input (1) != '!'
> + && peek_input (1) != '*')
> + || (peek_input () == '*' && peek_input (1) == '*'
> + && peek_input (2) == '*'))
> + {
> + // one /* or three /***
> // block comment
> + // (but not an inner or outer doc comment)
> skip_input ();
> current_column += 2;
>
> - // TODO: block doc comments
> -
> - current_char = peek_input ();
> -
> int level = 1;
> while (level > 0)
> {
> - skip_input ();
> - current_column++; // for error-handling
> current_char = peek_input ();
>
> if (current_char == EOF)
> @@ -496,6 +592,7 @@ Lexer::build_token ()
> current_column += 2;
>
> level += 1;
> + continue;
> }
>
> // ignore until */ is found
> @@ -505,16 +602,101 @@ Lexer::build_token ()
> skip_input (1);
>
> current_column += 2;
> - // should only break inner loop here - seems to do so
> - // break;
>
> level -= 1;
> + continue;
> }
> +
> + if (current_char == '\n')
> + {
> + skip_input ();
> + current_line++;
> + current_column = 1;
> + // tell line_table that new line starts
> + line_map->start_line (current_line, max_column_hint);
> + continue;
> + }
> +
> + skip_input ();
> + current_column++;
> }
>
> // refresh new token
> continue;
> - break;
> + }
> + else if (peek_input () == '*'
> + && (peek_input (1) == '!' || peek_input (1) == '*'))
> + {
> + // block doc comment, inner /*! or outer /**
> + bool is_inner = peek_input (1) == '!';
> + skip_input (1);
> + current_column += 3;
> +
> + std::string str;
> + str.reserve (96);
> +
> + int level = 1;
> + while (level > 0)
> + {
> + current_char = peek_input ();
> +
> + if (current_char == EOF)
> + {
> + rust_error_at (
> + loc, "unexpected EOF while looking for end of comment");
> + break;
> + }
> +
> + // if /* found
> + if (current_char == '/' && peek_input (1) == '*')
> + {
> + // skip /* characters
> + skip_input (1);
> + current_column += 2;
> +
> + level += 1;
> + str += "/*";
> + continue;
> + }
> +
> + // ignore until */ is found
> + if (current_char == '*' && peek_input (1) == '/')
> + {
> + // skip */ characters
> + skip_input (1);
> + current_column += 2;
> +
> + level -= 1;
> + if (level > 0)
> + str += "*/";
> + continue;
> + }
> +
> + if (current_char == '\r' && peek_input (1) != '\n')
> + rust_error_at (
> + loc, "Isolated CR %<\\r%> not allowed in doc comment");
> +
> + if (current_char == '\n')
> + {
> + skip_input ();
> + current_line++;
> + current_column = 1;
> + // tell line_table that new line starts
> + line_map->start_line (current_line, max_column_hint);
> + str += '\n';
> + continue;
> + }
> +
> + str += current_char;
> + skip_input ();
> + current_column++;
> + }
> +
> + str.shrink_to_fit ();
> + if (is_inner)
> + return Token::make_inner_doc_comment (loc, std::move (str));
> + else
> + return Token::make_outer_doc_comment (loc, std::move (str));
> }
> else
> {
> diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
> index 771910119b7..1c397c839fd 100644
> --- a/gcc/rust/lex/rust-token.h
> +++ b/gcc/rust/lex/rust-token.h
> @@ -151,15 +151,10 @@ enum PrimitiveCoreType
> RS_TOKEN (RIGHT_SQUARE, "]")
> \
> /* Macros */
> \
> RS_TOKEN (DOLLAR_SIGN, "$")
> \
> - /* Comments */
> \
> - RS_TOKEN (LINE_COMMENT, "//")
> \
> - RS_TOKEN (INNER_LINE_DOC, "//!")
> \
> - RS_TOKEN (OUTER_LINE_DOC, "///")
> \
> - RS_TOKEN (BLOCK_COMMENT_START, "/*")
> \
> - RS_TOKEN (BLOCK_COMMENT_END, "*/")
> \
> - RS_TOKEN (INNER_BLOCK_DOC_START, "/*!")
> \
> - RS_TOKEN (OUTER_BLOCK_DOC_START,
> \
> - "/**") /* have "weak" union and 'static keywords? */ \
> + /* Doc Comments */
> \
> + RS_TOKEN (INNER_DOC_COMMENT, "#![doc]")
> \
> + RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]")
> \
> + /* have "weak" union and 'static keywords? */
> \
>
> \
> RS_TOKEN_KEYWORD (ABSTRACT, "abstract") /* unused */
> \
> RS_TOKEN_KEYWORD (AS, "as")
> \
> @@ -368,6 +363,18 @@ public:
> return TokenPtr (new Token (BYTE_STRING_LITERAL, locus, std::move
> (str)));
> }
>
> + // Makes and returns a new TokenPtr of type INNER_DOC_COMMENT.
> + static TokenPtr make_inner_doc_comment (Location locus, std::string &&str)
> + {
> + return TokenPtr (new Token (INNER_DOC_COMMENT, locus, std::move (str)));
> + }
> +
> + // Makes and returns a new TokenPtr of type OUTER_DOC_COMMENT.
> + static TokenPtr make_outer_doc_comment (Location locus, std::string &&str)
> + {
> + return TokenPtr (new Token (OUTER_DOC_COMMENT, locus, std::move (str)));
> + }
> +
> // Makes and returns a new TokenPtr of type LIFETIME.
> static TokenPtr make_lifetime (Location locus, std::string &&str)
> {
> diff --git a/gcc/rust/parse/rust-parse-impl.h
> b/gcc/rust/parse/rust-parse-impl.h
> index a8597fa401e..eedc76db43e 100644
> --- a/gcc/rust/parse/rust-parse-impl.h
> +++ b/gcc/rust/parse/rust-parse-impl.h
> @@ -434,8 +434,9 @@ Parser<ManagedTokenSource>::parse_inner_attributes ()
> AST::AttrVec inner_attributes;
>
> // only try to parse it if it starts with "#!" not only "#"
> - while (lexer.peek_token ()->get_id () == HASH
> - && lexer.peek_token (1)->get_id () == EXCLAM)
> + while ((lexer.peek_token ()->get_id () == HASH
> + && lexer.peek_token (1)->get_id () == EXCLAM)
> + || lexer.peek_token ()->get_id () == INNER_DOC_COMMENT)
> {
> AST::Attribute inner_attr = parse_inner_attribute ();
>
> @@ -457,11 +458,33 @@ Parser<ManagedTokenSource>::parse_inner_attributes ()
> return inner_attributes;
> }
>
> +// Parse a inner or outer doc comment into an doc attribute
> +template <typename ManagedTokenSource>
> +AST::Attribute
> +Parser<ManagedTokenSource>::parse_doc_comment ()
> +{
> + const_TokenPtr token = lexer.peek_token ();
> + Location locus = token->get_locus ();
> + AST::SimplePathSegment segment ("doc", locus);
> + std::vector<AST::SimplePathSegment> segments;
> + segments.push_back (std::move (segment));
> + AST::SimplePath attr_path (std::move (segments), false, locus);
> + AST::LiteralExpr lit_expr (token->get_str (), AST::Literal::STRING,
> + PrimitiveCoreType::CORETYPE_STR, {}, locus);
> + std::unique_ptr<AST::AttrInput> attr_input (
> + new AST::AttrInputLiteral (std::move (lit_expr)));
> + lexer.skip_token ();
> + return AST::Attribute (std::move (attr_path), std::move (attr_input),
> locus);
> +}
> +
> // Parse a single inner attribute.
> template <typename ManagedTokenSource>
> AST::Attribute
> Parser<ManagedTokenSource>::parse_inner_attribute ()
> {
> + if (lexer.peek_token ()->get_id () == INNER_DOC_COMMENT)
> + return parse_doc_comment ();
> +
> if (lexer.peek_token ()->get_id () != HASH)
> {
> Error error (lexer.peek_token ()->get_locus (),
> @@ -1019,7 +1042,15 @@ Parser<ManagedTokenSource>::parse_item (bool
> called_from_statement)
> switch (t->get_id ())
> {
> case END_OF_FILE:
> - // not necessarily an error
> + // not necessarily an error, unless we just read outer
> + // attributes which needs to be attached
> + if (!outer_attrs.empty ())
> + {
> + Rust::AST::Attribute attr = outer_attrs.back ();
> + Error error (attr.get_locus (),
> + "expected item after outer attribute or doc comment");
> + add_error (std::move (error));
> + }
> return nullptr;
> case PUB:
> case MOD:
> @@ -1091,7 +1122,11 @@ Parser<ManagedTokenSource>::parse_outer_attributes ()
> {
> AST::AttrVec outer_attributes;
>
> - while (lexer.peek_token ()->get_id () == HASH)
> + while (lexer.peek_token ()->get_id ()
> + == HASH /* Can also be #!, which catches errors. */
> + || lexer.peek_token ()->get_id () == OUTER_DOC_COMMENT
> + || lexer.peek_token ()->get_id ()
> + == INNER_DOC_COMMENT) /* For error handling. */
> {
> AST::Attribute outer_attr = parse_outer_attribute ();
>
> @@ -1121,6 +1156,20 @@ template <typename ManagedTokenSource>
> AST::Attribute
> Parser<ManagedTokenSource>::parse_outer_attribute ()
> {
> + if (lexer.peek_token ()->get_id () == OUTER_DOC_COMMENT)
> + return parse_doc_comment ();
> +
> + if (lexer.peek_token ()->get_id () == INNER_DOC_COMMENT)
> + {
> + Error error (
> + lexer.peek_token ()->get_locus (),
> + "inner doc (%<//!%> or %</*!%>) only allowed at start of item "
> + "and before any outer attribute or doc (%<#[%>, %<///%> or %</**%>)");
> + add_error (std::move (error));
> + lexer.skip_token ();
> + return AST::Attribute::create_empty ();
> + }
> +
> /* OuterAttribute -> '#' '[' Attr ']' */
>
> if (lexer.peek_token ()->get_id () != HASH)
> @@ -1134,12 +1183,13 @@ Parser<ManagedTokenSource>::parse_outer_attribute ()
> if (id == EXCLAM)
> {
> // this is inner attribute syntax, so throw error
> + // inner attributes were either already parsed or not allowed here.
> Error error (
> lexer.peek_token ()->get_locus (),
> "token %<!%> found, indicating inner attribute definition. Inner "
> "attributes are not possible at this location");
> add_error (std::move (error));
> - } // TODO: are there any cases where this wouldn't be an error?
> + }
> return AST::Attribute::create_empty ();
> }
>
> diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
> index bde2613f03d..1cd85eae8c2 100644
> --- a/gcc/rust/parse/rust-parse.h
> +++ b/gcc/rust/parse/rust-parse.h
> @@ -107,6 +107,7 @@ private:
> AST::Attribute parse_outer_attribute ();
> AST::Attribute parse_attribute_body ();
> std::unique_ptr<AST::AttrInput> parse_attr_input ();
> + AST::Attribute parse_doc_comment ();
>
> // Path-related
> AST::SimplePath parse_simple_path ();
> diff --git a/gcc/testsuite/rust/compile/bad_inner_doc.rs
> b/gcc/testsuite/rust/compile/bad_inner_doc.rs
> new file mode 100644
> index 00000000000..cfd166ce3ec
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/bad_inner_doc.rs
> @@ -0,0 +1,15 @@
> +pub fn main ()
> +{
> + //! inner doc allowed
> + let _x = 42;
> + // { dg-error "inner doc" "" { target *-*-* } .+1 }
> + //! inner doc disallowed
> + mod module
> + {
> + /*! inner doc allowed */
> + /// outer doc allowed
> + // { dg-error "inner doc" "" { target *-*-* } .+1 }
> + /*! but inner doc not here */
> + mod x { }
> + }
> +}
> diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
> b/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
> new file mode 100644
> index 00000000000..0ada77f69cf
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
> @@ -0,0 +1,3 @@
> +// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
> +/** doc cr
> comment */
> +pub fn main () { }
> diff --git
> a/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
> b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
> new file mode 100644
> index 00000000000..7db35341bee
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
> @@ -0,0 +1,5 @@
> +pub fn main ()
> +{
> +// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
> + /*! doc cr
> comment */
> +}
> diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
> b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
> new file mode 100644
> index 00000000000..d75da75e218
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
> @@ -0,0 +1,5 @@
> +pub fn main ()
> +{
> +// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
> + //! doc cr
> comment
> +}
> diff --git a/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
> b/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
> new file mode 100644
> index 00000000000..7b6ef989c30
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
> @@ -0,0 +1,3 @@
> +// { dg-error "Isolated CR" "" { target *-*-* } .+1 }
> +/// doc cr
> comment
> +pub fn main () { }
> diff --git
> a/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
> b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
> new file mode 100644
> index 00000000000..ab38ac69610
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
> @@ -0,0 +1,47 @@
> +// comment line not a doc
> +/* comment block not a doc */
> +
> +//! inner line comment for most outer crate
> +/*! inner block comment for most outer crate */
> +
> +// comment line not a doc
> +/* comment block not a doc */
> +
> +/// outer doc line for module
> +/** outer doc block for module */
> +pub mod module
> +{
> + //! inner line doc
> + //!! inner line doc!
> + /*! inner block doc */
> + /*!! inner block doc! */
> +
> + // line comment
> + /// outer line doc
> + //// line comment
> +
> + /* block comment */
> + /** outer block doc */
> + /*** block comment */
> +
> + mod block_doc_comments
> + {
> + /* /* */ /** */ /*! */ */
> + /*! /* */ /** */ /*! */ */
> + /** /* */ /** */ /*! */ */
> + mod item { }
> + }
> +
> + pub mod empty
> + {
> + //!
> + /*!*/
> + //
> +
> + ///
> + mod doc { }
> + /**/
> + /***/
> + }
> +}
> +pub fn main () { }
> diff --git
> a/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
> b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
> new file mode 100644
> index 00000000000..3ea2cd01c8c
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
> @@ -0,0 +1,47 @@
> +// comment line not a doc
> +/* comment block not a doc */
> +
> +//! inner line comment for most outer crate
> +/*! inner block comment for most outer crate */
> +
> +// comment line not a doc
> +/* comment block not a doc */
> +
> +/// outer doc line for module
> +/** outer doc block for module */
> +pub mod module
> +{
> + //! inner line doc
> + //!! inner line doc!
> + /*! inner block doc */
> + /*!! inner block doc! */
> +
> + // line comment
> + /// outer line doc
> + //// line comment
> +
> + /* block comment */
> + /** outer block doc */
> + /*** block comment */
> +
> + mod block_doc_comments
> + {
> + /* /* */ /** */ /*! */ */
> + /*! /* */ /** */ /*! */ */
> + /** /* */ /** */ /*! */ */
> + mod item { }
> + }
> +
> + pub mod empty
> + {
> + //!
> + /*!*/
> + //
> +
> + ///
> + mod doc { }
> + /**/
> + /***/
> + }
> +}
> +pub fn main () { }
> diff --git a/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
> b/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
> new file mode 100644
> index 00000000000..9a1e090f330
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
> @@ -0,0 +1,2 @@
> +/* comment cr
> is allowed */
> +pub fn main () { }
> diff --git a/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
> b/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
> new file mode 100644
> index 00000000000..4e921a225c2
> --- /dev/null
> +++ b/gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs
> @@ -0,0 +1,2 @@
> +// comment cr
> is allowed
> +pub fn main () { }Hi Mark, This patch looks good to me. When I tried to apply it to merge it I got the following: ``` $ git amĀ '[PATCH] Handle doc comment strings in lexer and parser.eml' Applying: Handle doc comment strings in lexer and parser error: corrupt patch at line 531 Patch failed at 0001 Handle doc comment strings in lexer and parser hint: Use 'git am --show-current-patch' to see the failed patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". ``` Not sure if I have done something wrong, have you any pointers? Thanks --Phil
OpenPGP_signature
Description: OpenPGP digital signature
-- Gcc-rust mailing list [email protected] https://gcc.gnu.org/mailman/listinfo/gcc-rust
