Comment parsing: actually check for a block command after "\param x"

This fixes PR15068.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173539 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h
index 5f6e0c5..8bf629b 100644
--- a/include/clang/AST/CommentParser.h
+++ b/include/clang/AST/CommentParser.h
@@ -86,6 +86,11 @@
     Tok = Toks[0];
   }
 
+  bool isTokBlockCommand() {
+    return Tok.is(tok::command) &&
+           Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand;
+  }
+
 public:
   Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
          const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index a7ba013..5f45125 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -329,8 +329,7 @@
   }
   consumeToken();
 
-  if (Tok.is(tok::command) &&
-      Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand) {
+  if (isTokBlockCommand()) {
     // Block command ahead.  We can't nest block commands, so pretend that this
     // command has an empty argument.
     ParagraphComment *Paragraph = S.actOnParagraphComment(
@@ -362,10 +361,28 @@
     Retokenizer.putBackLeftoverTokens();
   }
 
-  BlockContentComment *Block = parseParagraphOrBlockCommand();
-  // Since we have checked for a block command, we should have parsed a
-  // paragraph.
-  ParagraphComment *Paragraph = cast<ParagraphComment>(Block);
+  // If there's a block command ahead, we will attach an empty paragraph to
+  // this command.
+  bool EmptyParagraph = false;
+  if (isTokBlockCommand())
+    EmptyParagraph = true;
+  else if (Tok.is(tok::newline)) {
+    Token PrevTok = Tok;
+    consumeToken();
+    EmptyParagraph = isTokBlockCommand();
+    putBack(PrevTok);
+  }
+
+  ParagraphComment *Paragraph;
+  if (EmptyParagraph)
+    Paragraph = S.actOnParagraphComment(ArrayRef<InlineContentComment *>());
+  else {
+    BlockContentComment *Block = parseParagraphOrBlockCommand();
+    // Since we have checked for a block command, we should have parsed a
+    // paragraph.
+    Paragraph = cast<ParagraphComment>(Block);
+  }
+
   if (IsParam) {
     S.actOnParamCommandFinish(PC, Paragraph);
     return PC;
diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp
index df9d906..c884475 100644
--- a/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1,6 +1,7 @@
 // RUN: rm -f %t
 // RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true %s > %t 2>&1
 // RUN: FileCheck --input-file=%t %s
+// XPASS: *
 
 class A {
 public:
diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp
index 5678fd9..6a6b8dd 100644
--- a/test/Sema/warn-documentation.cpp
+++ b/test/Sema/warn-documentation.cpp
@@ -836,3 +836,31 @@
 /// aaa \unknown aaa \unknown aaa
 int test_nocrash9;
 
+
+// We used to crash on this.  PR15068
+
+// expected-warning@+2 {{empty paragraph passed to '\param' command}}
+// expected-warning@+2 {{empty paragraph passed to '\param' command}}
+///@param x
+///@param y
+int test_nocrash10(int x, int y);
+
+// expected-warning@+2 {{empty paragraph passed to '\param' command}} expected-warning@+2 {{parameter 'x' not found in the function declaration}}
+// expected-warning@+2 {{empty paragraph passed to '\param' command}} expected-warning@+2 {{parameter 'y' not found in the function declaration}}
+///@param x
+///@param y
+int test_nocrash11();
+
+// expected-warning@+3 {{empty paragraph passed to '\param' command}} expected-warning@+3 {{parameter 'x' not found in the function declaration}}
+// expected-warning@+3 {{empty paragraph passed to '\param' command}} expected-warning@+3 {{parameter 'y' not found in the function declaration}}
+/**
+@param x
+@param y
+**/
+int test_nocrash12();
+
+// expected-warning@+2 {{empty paragraph passed to '\param' command}}
+// expected-warning@+1 {{empty paragraph passed to '\param' command}}
+///@param x@param y
+int test_nocrash13(int x, int y);
+