This revision was automatically updated to reflect the committed changes.
Closed by commit rGd3a4033d6ee1: Comment parsing: Allow inline commands to have 
0 or more than 1 argument (authored by aaronpuchert).

Changed prior to commit:
  https://reviews.llvm.org/D125429?vs=428968&id=429203#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125429/new/

https://reviews.llvm.org/D125429

Files:
  clang/include/clang/AST/Comment.h
  clang/include/clang/AST/CommentCommands.td
  clang/include/clang/AST/CommentParser.h
  clang/include/clang/AST/CommentSema.h
  clang/include/clang/Basic/DiagnosticCommentKinds.td
  clang/lib/AST/CommentParser.cpp
  clang/lib/AST/CommentSema.cpp
  clang/test/AST/ast-dump-comment.cpp
  clang/test/Headers/x86-intrinsics-headers-clean.cpp
  clang/test/Sema/warn-documentation.cpp

Index: clang/test/Sema/warn-documentation.cpp
===================================================================
--- clang/test/Sema/warn-documentation.cpp
+++ clang/test/Sema/warn-documentation.cpp
@@ -1116,49 +1116,49 @@
 void test_attach38<int>::test_attach39(int, B);
 
 // The inline comments expect a string after the command.
-// expected-warning@+1 {{'\a' command does not have a valid word argument}}
+// expected-warning@+1 {{'\a' command has no word arguments, expected 1}}
 /// \a
 int test_inline_no_argument_a_bad(int);
 
 /// \a A
 int test_inline_no_argument_a_good(int);
 
-// expected-warning@+1 {{'\anchor' command does not have a valid word argument}}
+// expected-warning@+1 {{'\anchor' command has no word arguments, expected 1}}
 /// \anchor
 int test_inline_no_argument_anchor_bad(int);
 
 /// \anchor A
 int test_inline_no_argument_anchor_good(int);
 
-// expected-warning@+1 {{'@b' command does not have a valid word argument}}
+// expected-warning@+1 {{'@b' command has no word arguments, expected 1}}
 /// @b
 int test_inline_no_argument_b_bad(int);
 
 /// @b A
 int test_inline_no_argument_b_good(int);
 
-// expected-warning@+1 {{'\c' command does not have a valid word argument}}
+// expected-warning@+1 {{'\c' command has no word arguments, expected 1}}
 /// \c
 int test_inline_no_argument_c_bad(int);
 
 /// \c A
 int test_inline_no_argument_c_good(int);
 
-// expected-warning@+1 {{'\e' command does not have a valid word argument}}
+// expected-warning@+1 {{'\e' command has no word arguments, expected 1}}
 /// \e
 int test_inline_no_argument_e_bad(int);
 
 /// \e A
 int test_inline_no_argument_e_good(int);
 
-// expected-warning@+1 {{'\em' command does not have a valid word argument}}
+// expected-warning@+1 {{'\em' command has no word arguments, expected 1}}
 /// \em
 int test_inline_no_argument_em_bad(int);
 
 /// \em A
 int test_inline_no_argument_em_good(int);
 
-// expected-warning@+1 {{'\p' command does not have a valid word argument}}
+// expected-warning@+1 {{'\p' command has no word arguments, expected 1}}
 /// \p
 int test_inline_no_argument_p_bad(int);
 
Index: clang/test/Headers/x86-intrinsics-headers-clean.cpp
===================================================================
--- clang/test/Headers/x86-intrinsics-headers-clean.cpp
+++ clang/test/Headers/x86-intrinsics-headers-clean.cpp
@@ -1,11 +1,11 @@
 // Make sure the intrinsic headers compile cleanly with no warnings or errors.
 
 // RUN: %clang_cc1 -ffreestanding -triple i386-unknown-unknown \
-// RUN:    -Wextra -Werror -Wsystem-headers -Wsign-conversion -Wcast-qual -Wdocumentation \
+// RUN:    -Wextra -Werror -Wsystem-headers -Wsign-conversion -Wcast-qual -Wdocumentation -Wdocumentation-pedantic -Wdocumentation-unknown-command \
 // RUN:    -fsyntax-only -fretain-comments-from-system-headers -flax-vector-conversions=none -x c++ -verify %s
 
 // RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown \
-// RUN:    -Wextra -Werror -Wsystem-headers -Wsign-conversion -Wcast-qual -Wdocumentation \
+// RUN:    -Wextra -Werror -Wsystem-headers -Wsign-conversion -Wcast-qual -Wdocumentation -Wdocumentation-pedantic -Wdocumentation-unknown-command \
 // RUN:    -fsyntax-only -fretain-comments-from-system-headers -flax-vector-conversions=none -x c++ -verify %s
 
 // expected-no-diagnostics
Index: clang/test/AST/ast-dump-comment.cpp
===================================================================
--- clang/test/AST/ast-dump-comment.cpp
+++ clang/test/AST/ast-dump-comment.cpp
@@ -62,6 +62,12 @@
 // CHECK:      VarDecl{{.*}}Test_InlineCommandComment
 // CHECK:        InlineCommandComment{{.*}} Name="c" RenderMonospaced Arg[0]="Aaa"
 
+/// \n Aaa
+int Test_InlineCommandComment_NoArgs;
+// CHECK:      VarDecl{{.*}}Test_InlineCommandComment_NoArgs
+// CHECK:        InlineCommandComment{{.*}} Name="n" RenderNormal
+// CHECK-NEXT:   TextComment{{.*}} Text=" Aaa"
+
 /// \anchor Aaa
 int Test_InlineCommandCommentAnchor;
 // CHECK:      VarDecl{{.*}}Test_InlineCommandComment
Index: clang/lib/AST/CommentSema.cpp
===================================================================
--- clang/lib/AST/CommentSema.cpp
+++ clang/lib/AST/CommentSema.cpp
@@ -265,10 +265,8 @@
     // User didn't provide a direction argument.
     Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
   }
-  typedef BlockCommandComment::Argument Argument;
-  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
-                                                     ArgLocEnd),
-                                         Arg);
+  auto *A = new (Allocator)
+      Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg};
   Command->setArgs(llvm::makeArrayRef(A, 1));
 }
 
@@ -303,10 +301,8 @@
   // Parser will not feed us more arguments than needed.
   assert(Command->getNumArgs() == 0);
 
-  typedef BlockCommandComment::Argument Argument;
-  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
-                                                     ArgLocEnd),
-                                         Arg);
+  auto *A = new (Allocator)
+      Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg};
   Command->setArgs(llvm::makeArrayRef(A, 1));
 
   if (!isTemplateOrSpecialization()) {
@@ -361,37 +357,15 @@
   checkBlockCommandEmptyParagraph(Command);
 }
 
-InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
-                                               SourceLocation CommandLocEnd,
-                                               unsigned CommandID) {
-  ArrayRef<InlineCommandComment::Argument> Args;
+InlineCommandComment *
+Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
+                         SourceLocation CommandLocEnd, unsigned CommandID,
+                         ArrayRef<Comment::Argument> Args) {
   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
-  return new (Allocator) InlineCommandComment(
-                                  CommandLocBegin,
-                                  CommandLocEnd,
-                                  CommandID,
-                                  getInlineCommandRenderKind(CommandName),
-                                  Args);
-}
 
-InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
-                                               SourceLocation CommandLocEnd,
-                                               unsigned CommandID,
-                                               SourceLocation ArgLocBegin,
-                                               SourceLocation ArgLocEnd,
-                                               StringRef Arg) {
-  typedef InlineCommandComment::Argument Argument;
-  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
-                                                     ArgLocEnd),
-                                         Arg);
-  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
-
-  return new (Allocator) InlineCommandComment(
-                                  CommandLocBegin,
-                                  CommandLocEnd,
-                                  CommandID,
-                                  getInlineCommandRenderKind(CommandName),
-                                  llvm::makeArrayRef(A, 1));
+  return new (Allocator)
+      InlineCommandComment(CommandLocBegin, CommandLocEnd, CommandID,
+                           getInlineCommandRenderKind(CommandName), Args);
 }
 
 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
Index: clang/lib/AST/CommentParser.cpp
===================================================================
--- clang/lib/AST/CommentParser.cpp
+++ clang/lib/AST/CommentParser.cpp
@@ -289,22 +289,19 @@
                                      Arg.getText());
 }
 
-void Parser::parseBlockCommandArgs(BlockCommandComment *BC,
-                                   TextTokenRetokenizer &Retokenizer,
-                                   unsigned NumArgs) {
-  typedef BlockCommandComment::Argument Argument;
-  Argument *Args =
-      new (Allocator.Allocate<Argument>(NumArgs)) Argument[NumArgs];
+ArrayRef<Comment::Argument>
+Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) {
+  auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))
+      Comment::Argument[NumArgs];
   unsigned ParsedArgs = 0;
   Token Arg;
   while (ParsedArgs < NumArgs && Retokenizer.lexWord(Arg)) {
-    Args[ParsedArgs] = Argument(SourceRange(Arg.getLocation(),
-                                            Arg.getEndLocation()),
-                                Arg.getText());
+    Args[ParsedArgs] = Comment::Argument{
+        SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
     ParsedArgs++;
   }
 
-  S.actOnBlockCommandArgs(BC, llvm::makeArrayRef(Args, ParsedArgs));
+  return llvm::makeArrayRef(Args, ParsedArgs);
 }
 
 BlockCommandComment *Parser::parseBlockCommand() {
@@ -360,7 +357,7 @@
     else if (TPC)
       parseTParamCommandArgs(TPC, Retokenizer);
     else
-      parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs);
+      S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs));
 
     Retokenizer.putBackLeftoverTokens();
   }
@@ -401,32 +398,24 @@
 
 InlineCommandComment *Parser::parseInlineCommand() {
   assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
+  const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
 
   const Token CommandTok = Tok;
   consumeToken();
 
   TextTokenRetokenizer Retokenizer(Allocator, *this);
+  ArrayRef<Comment::Argument> Args =
+      parseCommandArgs(Retokenizer, Info->NumArgs);
 
-  Token ArgTok;
-  bool ArgTokValid = Retokenizer.lexWord(ArgTok);
-
-  InlineCommandComment *IC;
-  if (ArgTokValid) {
-    IC = S.actOnInlineCommand(CommandTok.getLocation(),
-                              CommandTok.getEndLocation(),
-                              CommandTok.getCommandID(),
-                              ArgTok.getLocation(),
-                              ArgTok.getEndLocation(),
-                              ArgTok.getText());
-  } else {
-    IC = S.actOnInlineCommand(CommandTok.getLocation(),
-                              CommandTok.getEndLocation(),
-                              CommandTok.getCommandID());
+  InlineCommandComment *IC = S.actOnInlineCommand(
+      CommandTok.getLocation(), CommandTok.getEndLocation(),
+      CommandTok.getCommandID(), Args);
 
+  if (Args.size() < Info->NumArgs) {
     Diag(CommandTok.getEndLocation().getLocWithOffset(1),
-         diag::warn_doc_inline_contents_no_argument)
-        << CommandTok.is(tok::at_command)
-        << Traits.getCommandInfo(CommandTok.getCommandID())->Name
+         diag::warn_doc_inline_command_not_enough_arguments)
+        << CommandTok.is(tok::at_command) << Info->Name << Args.size()
+        << Info->NumArgs
         << SourceRange(CommandTok.getLocation(), CommandTok.getEndLocation());
   }
 
Index: clang/include/clang/Basic/DiagnosticCommentKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticCommentKinds.td
+++ clang/include/clang/Basic/DiagnosticCommentKinds.td
@@ -155,8 +155,8 @@
 
 // inline contents commands
 
-def warn_doc_inline_contents_no_argument : Warning<
-  "'%select{\\|@}0%1' command does not have a valid word argument">,
+def warn_doc_inline_command_not_enough_arguments : Warning<
+  "'%select{\\|@}0%1' command has %plural{0:no|:%2}2 word argument%s2, expected %3">,
   InGroup<Documentation>, DefaultIgnore;
 
 // verbatim block commands
Index: clang/include/clang/AST/CommentSema.h
===================================================================
--- clang/include/clang/AST/CommentSema.h
+++ clang/include/clang/AST/CommentSema.h
@@ -128,16 +128,10 @@
   void actOnTParamCommandFinish(TParamCommandComment *Command,
                                 ParagraphComment *Paragraph);
 
-  InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
-                                           SourceLocation CommandLocEnd,
-                                           unsigned CommandID);
-
   InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
                                            SourceLocation CommandLocEnd,
                                            unsigned CommandID,
-                                           SourceLocation ArgLocBegin,
-                                           SourceLocation ArgLocEnd,
-                                           StringRef Arg);
+                                           ArrayRef<Comment::Argument> Args);
 
   InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
                                             SourceLocation LocEnd,
Index: clang/include/clang/AST/CommentParser.h
===================================================================
--- clang/include/clang/AST/CommentParser.h
+++ clang/include/clang/AST/CommentParser.h
@@ -97,9 +97,8 @@
   void parseTParamCommandArgs(TParamCommandComment *TPC,
                               TextTokenRetokenizer &Retokenizer);
 
-  void parseBlockCommandArgs(BlockCommandComment *BC,
-                             TextTokenRetokenizer &Retokenizer,
-                             unsigned NumArgs);
+  ArrayRef<Comment::Argument>
+  parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
 
   BlockCommandComment *parseBlockCommand();
   InlineCommandComment *parseInlineCommand();
Index: clang/include/clang/AST/CommentCommands.td
===================================================================
--- clang/include/clang/AST/CommentCommands.td
+++ clang/include/clang/AST/CommentCommands.td
@@ -31,6 +31,7 @@
 }
 
 class InlineCommand<string name> : Command<name> {
+  let NumArgs = 1;
   let IsInlineCommand = 1;
 }
 
@@ -86,6 +87,7 @@
 def P      : InlineCommand<"p">;
 def A      : InlineCommand<"a">;
 def E      : InlineCommand<"e">;
+def N      : InlineCommand<"n"> { let NumArgs = 0; }
 def Em     : InlineCommand<"em">;
 def Emoji  : InlineCommand<"emoji">;
 
Index: clang/include/clang/AST/Comment.h
===================================================================
--- clang/include/clang/AST/Comment.h
+++ clang/include/clang/AST/Comment.h
@@ -194,6 +194,11 @@
 #include "clang/AST/CommentNodes.inc"
   };
 
+  struct Argument {
+    SourceRange Range;
+    StringRef Text;
+  };
+
   Comment(CommentKind K,
           SourceLocation LocBegin,
           SourceLocation LocEnd) :
@@ -296,13 +301,6 @@
 /// A command with word-like arguments that is considered inline content.
 class InlineCommandComment : public InlineContentComment {
 public:
-  struct Argument {
-    SourceRange Range;
-    StringRef Text;
-
-    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
-  };
-
   /// The most appropriate rendering mode for this command, chosen on command
   /// semantics in Doxygen.
   enum RenderKind {
@@ -588,15 +586,6 @@
 /// arguments depends on command name) and a paragraph as an argument
 /// (e. g., \\brief).
 class BlockCommandComment : public BlockContentComment {
-public:
-  struct Argument {
-    SourceRange Range;
-    StringRef Text;
-
-    Argument() { }
-    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
-  };
-
 protected:
   /// Word-like arguments.
   ArrayRef<Argument> Args;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to