From d49963609d58ceaf85de6ad90170a359258a3a2c Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 1 Mar 2013 22:51:30 +0000 Subject: [PATCH] comment parsing. Keep the original command format in AST for source fidelity and use it in diagnostics to refer to the original format. // rdar://13066276 llvm-svn: 176387 --- clang/include/clang/AST/Comment.h | 17 ++++++++++--- clang/include/clang/AST/CommentLexer.h | 7 ++++++ .../include/clang/Basic/DiagnosticCommentKinds.td | 16 ++++++------- clang/lib/AST/CommentLexer.cpp | 1 + clang/lib/AST/CommentParser.cpp | 4 ++++ clang/lib/AST/CommentSema.cpp | 6 +++++ clang/test/Sema/warn-documentation.cpp | 28 +++++++++++++++------- 7 files changed, 60 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/AST/Comment.h b/clang/include/clang/AST/Comment.h index 78b703d..f00993b 100644 --- a/clang/include/clang/AST/Comment.h +++ b/clang/include/clang/AST/Comment.h @@ -570,13 +570,16 @@ protected: /// Paragraph argument. ParagraphComment *Paragraph; - + + /// Header Doc command, if true + bool HDCommand; + BlockCommandComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID) : BlockContentComment(K, LocBegin, LocEnd), - Paragraph(NULL) { + Paragraph(NULL), HDCommand(false) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; } @@ -586,7 +589,7 @@ public: SourceLocation LocEnd, unsigned CommandID) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Paragraph(NULL) { + Paragraph(NULL), HDCommand(false) { setLocation(getCommandNameBeginLoc()); BlockCommandCommentBits.CommandID = CommandID; } @@ -657,6 +660,14 @@ public: if (NewLocEnd.isValid()) setSourceRange(SourceRange(getLocStart(), NewLocEnd)); } + + bool getHDCommand() const LLVM_READONLY { + return HDCommand; + } + + void setHDCommand(bool HDC) { + HDCommand = HDC; + } }; /// Doxygen \\param command. diff --git a/clang/include/clang/AST/CommentLexer.h b/clang/include/clang/AST/CommentLexer.h index b90414b..240a8ea 100644 --- a/clang/include/clang/AST/CommentLexer.h +++ b/clang/include/clang/AST/CommentLexer.h @@ -75,6 +75,9 @@ class Token { /// unused (command spelling can be found with CommandTraits). Otherwise, /// contains the length of the string that starts at TextPtr. unsigned IntVal; + + /// This command is a Header Doc command (command starts with '@'). + bool HDCommand; public: SourceLocation getLocation() const LLVM_READONLY { return Loc; } @@ -122,6 +125,10 @@ public: return IntVal; } + bool getHDCommand() const LLVM_READONLY { + return HDCommand; + } + void setCommandID(unsigned ID) { assert(is(tok::command)); IntVal = ID; diff --git a/clang/include/clang/Basic/DiagnosticCommentKinds.td b/clang/include/clang/Basic/DiagnosticCommentKinds.td index e6dfe5b..f8a2af3 100644 --- a/clang/include/clang/Basic/DiagnosticCommentKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommentKinds.td @@ -44,18 +44,18 @@ def note_doc_html_end_tag : Note< // Commands def warn_doc_block_command_empty_paragraph : Warning< - "empty paragraph passed to '\\%0' command">, + "empty paragraph passed to '%select{\\|@}0%1' command">, InGroup, DefaultIgnore; def warn_doc_block_command_duplicate : Warning< - "duplicated command '\\%0'">, + "duplicated command '%select{\\|@}0%1'">, InGroup, DefaultIgnore; def note_doc_block_command_previous : Note< - "previous command '\\%0' here">; + "previous command '%select{\\|@}0%1' here">; def note_doc_block_command_previous_alias : Note< - "previous command '\\%0' (an alias of '\\%1') here">; + "previous command '%select{\\|@}0%1' (an alias of '\\%2') here">; // \param command @@ -111,14 +111,14 @@ def note_doc_tparam_name_suggestion : Note< // \returns command def warn_doc_returns_not_attached_to_a_function_decl : Warning< - "'\\%0' command used in a comment that is not attached to " + "'%select{\\|@}0%1' command used in a comment that is not attached to " "a function or method declaration">, InGroup, DefaultIgnore; def warn_doc_returns_attached_to_a_void_function : Warning< - "'\\%0' command used in a comment that is attached to a " + "'%select{\\|@}0%1' command used in a comment that is attached to a " "%select{function returning void|constructor|destructor|" - "method returning void}1">, + "method returning void}2">, InGroup, DefaultIgnore; // \deprecated command @@ -134,7 +134,7 @@ def note_add_deprecation_attr : Note< // verbatim block commands def warn_verbatim_block_end_without_start : Warning< - "'\\%0' command does not terminate a verbatim text block">, + "'%select{\\|@}0%1' command does not terminate a verbatim text block">, InGroup, DefaultIgnore; } // end of documentation issue category diff --git a/clang/lib/AST/CommentLexer.cpp b/clang/lib/AST/CommentLexer.cpp index cee086e..da865d2 100644 --- a/clang/lib/AST/CommentLexer.cpp +++ b/clang/lib/AST/CommentLexer.cpp @@ -298,6 +298,7 @@ void Lexer::lexCommentText(Token &T) { switch(*TokenPtr) { case '\\': case '@': { + T.HDCommand = (*TokenPtr == '@'); TokenPtr++; if (TokenPtr == CommentEnd) { formTextToken(T, TokenPtr); diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp index 952c10c..f5c933e 100644 --- a/clang/lib/AST/CommentParser.cpp +++ b/clang/lib/AST/CommentParser.cpp @@ -313,15 +313,18 @@ BlockCommandComment *Parser::parseBlockCommand() { PC = S.actOnParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandID()); + PC->setHDCommand(Tok.getHDCommand()); } else if (Info->IsTParamCommand) { IsTParam = true; TPC = S.actOnTParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandID()); + TPC->setHDCommand(Tok.getHDCommand()); } else { BC = S.actOnBlockCommandStart(Tok.getLocation(), Tok.getEndLocation(), Tok.getCommandID()); + BC->setHDCommand(Tok.getHDCommand()); } consumeToken(); @@ -569,6 +572,7 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { if (Info->IsVerbatimBlockEndCommand) { Diag(Tok.getLocation(), diag::warn_verbatim_block_end_without_start) + << Tok.getHDCommand() << Info->Name << SourceRange(Tok.getLocation(), Tok.getEndLocation()); consumeToken(); diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 73e49e7..3227138 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -432,6 +432,7 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { if (!DiagLoc.isValid()) DiagLoc = Command->getCommandNameRange(Traits).getEnd(); Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph) + << Command->getHDCommand() << Command->getCommandName(Traits) << Command->getSourceRange(); } @@ -459,6 +460,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } Diag(Command->getLocation(), diag::warn_doc_returns_attached_to_a_void_function) + << Command->getHDCommand() << Command->getCommandName(Traits) << DiagKind << Command->getSourceRange(); @@ -470,6 +472,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) + << Command->getHDCommand() << Command->getCommandName(Traits) << Command->getSourceRange(); } @@ -502,15 +505,18 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { StringRef CommandName = Command->getCommandName(Traits); StringRef PrevCommandName = PrevCommand->getCommandName(Traits); Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate) + << Command->getHDCommand() << CommandName << Command->getSourceRange(); if (CommandName == PrevCommandName) Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous) + << PrevCommand->getHDCommand() << PrevCommandName << PrevCommand->getSourceRange(); else Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous_alias) + << PrevCommand->getHDCommand() << PrevCommandName << CommandName; } diff --git a/clang/test/Sema/warn-documentation.cpp b/clang/test/Sema/warn-documentation.cpp index e2e49e5..d166ae0 100644 --- a/clang/test/Sema/warn-documentation.cpp +++ b/clang/test/Sema/warn-documentation.cpp @@ -862,28 +862,28 @@ 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}} +// 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}} +// 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}} +// 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}} +// 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); @@ -895,3 +895,15 @@ int test_nocrash13(int x, int y); /// \headerfile foo.h int test_duplicate_headerfile1(int); + +// rdar://13066276 +// expected-warning@+1 {{'@return' command used in a comment that is not attached to a function or method declaration}} +/** @return s */ +struct s* f(void); +struct s; + +// expected-warning@+1 {{'\return' command used in a comment that is not attached to a function or method declaration}} +/** \return s */ +struct q* g(void); +struct q; + -- 2.7.4