From: Dmitri Gribenko Date: Sat, 26 Jan 2013 00:36:14 +0000 (+0000) Subject: Comment parsing: actually check for a block command after "\param x" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=10442564e1ba3c4dfb184cc4e36beffbee4811c3;p=clang 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 5f6e0c56e2..8bf629b45e 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -86,6 +86,11 @@ class Parser { 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 a7ba013efc..5f45125bdc 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -329,8 +329,7 @@ BlockCommandComment *Parser::parseBlockCommand() { } 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 @@ BlockCommandComment *Parser::parseBlockCommand() { Retokenizer.putBackLeftoverTokens(); } - BlockContentComment *Block = parseParagraphOrBlockCommand(); - // Since we have checked for a block command, we should have parsed a - // paragraph. - ParagraphComment *Paragraph = cast(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()); + else { + BlockContentComment *Block = parseParagraphOrBlockCommand(); + // Since we have checked for a block command, we should have parsed a + // paragraph. + Paragraph = cast(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 df9d906c98..c8844754be 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 5678fd94cb..6a6b8dd599 100644 --- a/test/Sema/warn-documentation.cpp +++ b/test/Sema/warn-documentation.cpp @@ -836,3 +836,31 @@ typedef const struct test_nocrash7 * test_nocrash8; /// 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); +