]> granicus.if.org Git - clang/commitdiff
Comment diagnostics: add warning for multiple \param commands with duplicate
authorDmitri Gribenko <gribozavr@gmail.com>
Tue, 24 Jul 2012 21:44:16 +0000 (21:44 +0000)
committerDmitri Gribenko <gribozavr@gmail.com>
Tue, 24 Jul 2012 21:44:16 +0000 (21:44 +0000)
parameter names.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160696 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/CommentSema.h
include/clang/Basic/DiagnosticCommentKinds.td
lib/AST/CommentSema.cpp
test/Sema/warn-documentation.cpp

index f8b35d0c6f3e324759d0d672f642ed42fe09221e..56d61f1693c223f190571d38839275818fb0ae21 100644 (file)
@@ -46,6 +46,13 @@ class Sema {
   /// Contains a valid value if \c IsThisDeclInspected is true.
   ArrayRef<const ParmVarDecl *> ParamVars;
 
+  /// Comment AST nodes that correspond to \c ParamVars for which we have
+  /// found a \\param command or NULL if no documentation was found so far.
+  ///
+  /// Has correct size and contains valid values if \c IsThisDeclInspected is
+  /// true.
+  llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
+
   /// True if we extracted all important information from \c ThisDecl into
   /// \c Sema members.
   unsigned IsThisDeclInspected : 1;
index 890606a85a4ebdcce6b4f63e8e3e1f9c09760627..91aa5f19e6578d842fad2dae387010412ced090d 100644 (file)
@@ -63,6 +63,13 @@ def warn_doc_param_not_attached_to_a_function_decl : Warning<
   "a function declaration">,
   InGroup<Documentation>, DefaultIgnore;
 
+def warn_doc_param_duplicate : Warning<
+  "parameter '%0' is already documented">,
+  InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_param_previous : Note<
+  "previous documentation">;
+
 def warn_doc_param_not_found : Warning<
   "parameter '%0' not found in the function declaration">,
   InGroup<Documentation>, DefaultIgnore;
index 8fa8ab7d06f5804ffe89bfa8561d29eb084e1bca..5301bfebe962bd40b2e292033256740b24f528f3 100644 (file)
@@ -153,6 +153,15 @@ ParamCommandComment *Sema::actOnParamCommandParamNameArg(
   const unsigned ResolvedParamIndex = resolveParmVarReference(Arg, ParamVars);
   if (ResolvedParamIndex != ParamCommandComment::InvalidParamIndex) {
     Command->setParamIndex(ResolvedParamIndex);
+    if (ParamVarDocs[ResolvedParamIndex]) {
+      SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
+      Diag(ArgLocBegin, diag::warn_doc_param_duplicate)
+        << Arg << ArgRange;
+      ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
+      Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
+        << PrevCommand->getParamNameRange();
+    }
+    ParamVarDocs[ResolvedParamIndex] = Command;
     return Command;
   }
 
@@ -351,7 +360,6 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
 
 FullComment *Sema::actOnFullComment(
                               ArrayRef<BlockContentComment *> Blocks) {
-  SmallVector<ParamCommandComment *, 8> Params;
   return new (Allocator) FullComment(Blocks);
 }
 
@@ -382,6 +390,7 @@ ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
 }
 
 void Sema::inspectThisDecl() {
+  assert(!IsThisDeclInspected);
   if (!ThisDecl) {
     IsFunctionDecl = false;
     ParamVars = ArrayRef<const ParmVarDecl *>();
@@ -397,6 +406,7 @@ void Sema::inspectThisDecl() {
     IsFunctionDecl = false;
     ParamVars = ArrayRef<const ParmVarDecl *>();
   }
+  ParamVarDocs.resize(ParamVars.size(), NULL);
   IsThisDeclInspected = true;
 }
 
index 69e12b5097eab7646ab153828b5fd167bcfdc2e5..b59c6e4c5bc131c675d48cf8314e13434e993604 100644 (file)
@@ -166,6 +166,18 @@ class C {
  int test_param14(int bbb, int ccc);
 };
 
+// expected-warning@+3 {{parameter 'a' is already documented}}
+// expected-note@+1 {{previous documentation}}
+/// \param a Aaa.
+/// \param a Aaa.
+int test_param15(int a);
+
+// expected-warning@+4 {{parameter 'x2' is already documented}}
+// expected-note@+2 {{previous documentation}}
+/// \param x1 Aaa.
+/// \param x2 Bbb.
+/// \param x2 Ccc.
+int test_param16(int x1, int x2, int x3);
 
 // expected-warning@+1 {{empty paragraph passed to '\brief' command}}
 int test1; ///< \brief\brief Aaa