public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Handle doc comment strings in lexer and parser
@ 2021-07-11 20:10 Mark Wielaard
  2021-07-12  8:09 ` Philip Herron
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Wielaard @ 2021-07-11 20:10 UTC (permalink / raw)
  To: gcc-rust; +Cc: Mark Wielaard

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\r 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\r 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\r 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\r 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\r 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\r is allowed
+pub fn main () { }
-- 
2.32.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-07-18 20:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-11 20:10 [PATCH] Handle doc comment strings in lexer and parser Mark Wielaard
2021-07-12  8:09 ` Philip Herron
2021-07-12  8:32   ` Mark Wielaard
2021-07-12 10:06     ` Philip Herron
2021-07-12 22:44       ` New contributor tasks Mark Wielaard
2021-07-13 13:16         ` Philip Herron
     [not found]           ` <CADYxmzTdEH2pHba1+1nq5AXEQAyb6UhT8xvRKdWB7bu41ex1UA@mail.gmail.com>
2021-07-17 14:25             ` Fwd: " The Other
2021-07-17 21:23               ` Mark Wielaard
2021-07-18 20:45               ` Mark Wielaard
2021-07-13 13:30         ` Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).