Comment diagnostics: warn on duplicate \brief and \return commands.
Doxygen manual claims that multiple \brief or \returns commands will be merged
together, but actual behavior is different (second \brief command becomes a
part of a discussion, second \returns becomes a "Returns: blah" paragraph on
its own). Anyway, it seems to be a bad idea to use multiple \brief or \returns
commands in a single command.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161325 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index 770d5bb..57f8fda 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -20,7 +20,7 @@
Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),
- ThisDeclInfo(NULL) {
+ ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) {
}
void Sema::setDecl(const Decl *D) {
@@ -55,6 +55,7 @@
ParagraphComment *Paragraph) {
Command->setParagraph(Paragraph);
checkBlockCommandEmptyParagraph(Command);
+ checkBlockCommandDuplicate(Command);
checkReturnsCommand(Command);
return Command;
}
@@ -507,6 +508,39 @@
<< Command->getSourceRange();
}
+void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
+ StringRef Name = Command->getCommandName();
+ const BlockCommandComment *PrevCommand = NULL;
+ if (isBriefCommand(Name)) {
+ if (!BriefCommand) {
+ BriefCommand = Command;
+ return;
+ }
+ PrevCommand = BriefCommand;
+ } else if (isReturnsCommand(Name)) {
+ if (!ReturnsCommand) {
+ ReturnsCommand = Command;
+ return;
+ }
+ PrevCommand = ReturnsCommand;
+ } else {
+ // We don't want to check this command for duplicates.
+ return;
+ }
+ Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
+ << Name
+ << Command->getSourceRange();
+ if (Name == PrevCommand->getCommandName())
+ Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
+ << PrevCommand->getCommandName()
+ << Command->getSourceRange();
+ else
+ Diag(PrevCommand->getLocation(),
+ diag::note_doc_block_command_previous_alias)
+ << PrevCommand->getCommandName()
+ << Name;
+}
+
bool Sema::isFunctionDecl() {
if (!ThisDeclInfo)
return false;
@@ -678,10 +712,9 @@
// TODO: tablegen
bool Sema::isBlockCommand(StringRef Name) {
- return isReturnsCommand(Name) ||
+ return isBriefCommand(Name) || isReturnsCommand(Name) ||
isParamCommand(Name) || isTParamCommand(Name) ||
llvm::StringSwitch<bool>(Name)
- .Cases("brief", "short", true)
.Case("author", true)
.Case("authors", true)
.Case("pre", true)
@@ -700,6 +733,10 @@
return Name == "tparam";
}
+bool Sema::isBriefCommand(StringRef Name) {
+ return Name == "brief" || Name == "short";
+}
+
bool Sema::isReturnsCommand(StringRef Name) {
return Name == "returns" || Name == "return" || Name == "result";
}