[cfe-commits] r162570 - in /cfe/trunk: include/clang/AST/CommentSema.h lib/AST/CommentSema.cpp test/Sema/warn-documentation.cpp test/Sema/warn-documentation.m

Dmitri Gribenko gribozavr at gmail.com
Fri Aug 24 10:45:39 PDT 2012


Author: gribozavr
Date: Fri Aug 24 12:45:39 2012
New Revision: 162570

URL: http://llvm.org/viewvc/llvm-project?rev=162570&view=rev
Log:
Comment diagnostics: for unresolved parameters, do not suggest parameter fixit
with parameter that is documented.

Fixes PR13670, <rdar://problem/12155840>.

Modified:
    cfe/trunk/include/clang/AST/CommentSema.h
    cfe/trunk/lib/AST/CommentSema.cpp
    cfe/trunk/test/Sema/warn-documentation.cpp
    cfe/trunk/test/Sema/warn-documentation.m

Modified: cfe/trunk/include/clang/AST/CommentSema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentSema.h?rev=162570&r1=162569&r2=162570&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/CommentSema.h (original)
+++ cfe/trunk/include/clang/AST/CommentSema.h Fri Aug 24 12:45:39 2012
@@ -46,13 +46,6 @@
   /// Information about the declaration this comment is attached to.
   DeclInfo *ThisDeclInfo;
 
-  /// 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 DeclInfo->IsFilled is
-  /// true.
-  llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
-
   /// Comment AST nodes that correspond to parameter names in
   /// \c TemplateParameters.
   ///
@@ -190,6 +183,10 @@
   /// used only once per comment, e.g., \\brief and \\returns.
   void checkBlockCommandDuplicate(const BlockCommandComment *Command);
 
+  /// Resolve parameter names to parameter indexes in function declaration.
+  /// Emit diagnostics about unknown parametrs.
+  void resolveParamCommandIndexes(const FullComment *FC);
+
   bool isFunctionDecl();
   bool isTemplateOrSpecialization();
 

Modified: cfe/trunk/lib/AST/CommentSema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentSema.cpp?rev=162570&r1=162569&r2=162570&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CommentSema.cpp (original)
+++ cfe/trunk/lib/AST/CommentSema.cpp Fri Aug 24 12:45:39 2012
@@ -142,56 +142,6 @@
                                                      ArgLocEnd),
                                          Arg);
   Command->setArgs(llvm::makeArrayRef(A, 1));
-
-  if (!isFunctionDecl()) {
-    // We already warned that this \\param is not attached to a function decl.
-    return;
-  }
-
-  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
-
-  // Check that referenced parameter name is in the function decl.
-  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;
-  }
-
-  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
-  Diag(ArgLocBegin, diag::warn_doc_param_not_found)
-    << Arg << ArgRange;
-
-  // No parameters -- can't suggest a correction.
-  if (ParamVars.size() == 0)
-    return;
-
-  unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
-  if (ParamVars.size() == 1) {
-    // If function has only one parameter then only that parameter
-    // can be documented.
-    CorrectedParamIndex = 0;
-  } else {
-    // Do typo correction.
-    CorrectedParamIndex = correctTypoInParmVarReference(Arg, ParamVars);
-  }
-  if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
-    const ParmVarDecl *CorrectedPVD = ParamVars[CorrectedParamIndex];
-    if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
-      Diag(ArgLocBegin, diag::note_doc_param_name_suggestion)
-        << CorrectedII->getName()
-        << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
-  }
-
-  return;
 }
 
 void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
@@ -445,7 +395,9 @@
 
 FullComment *Sema::actOnFullComment(
                               ArrayRef<BlockContentComment *> Blocks) {
-  return new (Allocator) FullComment(Blocks, ThisDeclInfo);
+  FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
+  resolveParamCommandIndexes(FC);
+  return FC;
 }
 
 void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
@@ -529,6 +481,91 @@
         << Name;
 }
 
+void Sema::resolveParamCommandIndexes(const FullComment *FC) {
+  if (!isFunctionDecl()) {
+    // We already warned that \\param commands are not attached to a function
+    // decl.
+    return;
+  }
+
+  llvm::SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
+
+  // 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.
+  llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
+
+  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
+  ParamVarDocs.resize(ParamVars.size(), NULL);
+
+  // First pass over all \\param commands: resolve all parameter names.
+  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
+       I != E; ++I) {
+    ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
+    if (!PCC || !PCC->hasParamName())
+      continue;
+    StringRef ParamName = PCC->getParamName();
+
+    // Check that referenced parameter name is in the function decl.
+    const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
+                                                                ParamVars);
+    if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
+      UnresolvedParamCommands.push_back(PCC);
+      continue;
+    }
+    PCC->setParamIndex(ResolvedParamIndex);
+    if (ParamVarDocs[ResolvedParamIndex]) {
+      SourceRange ArgRange = PCC->getParamNameRange();
+      Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
+        << ParamName << ArgRange;
+      ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
+      Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
+        << PrevCommand->getParamNameRange();
+    }
+    ParamVarDocs[ResolvedParamIndex] = PCC;
+  }
+
+  // Find parameter declarations that have no corresponding \\param.
+  llvm::SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
+  for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
+    if (!ParamVarDocs[i])
+      OrphanedParamDecls.push_back(ParamVars[i]);
+  }
+
+  // Second pass over unresolved \\param commands: do typo correction.
+  // Suggest corrections from a set of parameter declarations that have no
+  // corresponding \\param.
+  for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
+    const ParamCommandComment *PCC = UnresolvedParamCommands[i];
+
+    SourceRange ArgRange = PCC->getParamNameRange();
+    StringRef ParamName = PCC->getParamName();
+    Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
+      << ParamName << ArgRange;
+
+    // All parameters documented -- can't suggest a correction.
+    if (OrphanedParamDecls.size() == 0)
+      continue;
+
+    unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
+    if (OrphanedParamDecls.size() == 1) {
+      // If one parameter is not documented then that parameter is the only
+      // possible suggestion.
+      CorrectedParamIndex = 0;
+    } else {
+      // Do typo correction.
+      CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
+                                                          OrphanedParamDecls);
+    }
+    if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
+      const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
+      if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
+        Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
+          << CorrectedII->getName()
+          << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
+    }
+  }
+}
+
 bool Sema::isFunctionDecl() {
   if (!ThisDeclInfo)
     return false;
@@ -553,7 +590,6 @@
 
 void Sema::inspectThisDecl() {
   ThisDeclInfo->fill();
-  ParamVarDocs.resize(ThisDeclInfo->ParamVars.size(), NULL);
 }
 
 unsigned Sema::resolveParmVarReference(StringRef Name,

Modified: cfe/trunk/test/Sema/warn-documentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-documentation.cpp?rev=162570&r1=162569&r2=162570&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-documentation.cpp (original)
+++ cfe/trunk/test/Sema/warn-documentation.cpp Fri Aug 24 12:45:39 2012
@@ -218,9 +218,32 @@
 /// \param aab Blah blah.
 int test_param13(int aaa, int bbb);
 
+// expected-warning at +2 {{parameter 'aab' not found in the function declaration}} expected-note at +2 {{did you mean 'bbb'?}}
+/// \param aaa Blah blah.
+/// \param aab Blah blah.
+int test_param14(int aaa, int bbb);
+
 // expected-warning at +1 {{parameter 'aab' not found in the function declaration}}
 /// \param aab Blah blah.
-int test_param14(int bbb, int ccc);
+int test_param15(int bbb, int ccc);
+
+// expected-warning at +1 {{parameter 'aab' not found in the function declaration}}
+/// \param aab Ccc.
+/// \param aaa Aaa.
+/// \param bbb Bbb.
+int test_param16(int aaa, int bbb);
+
+// expected-warning at +2 {{parameter 'aab' not found in the function declaration}}
+/// \param aaa Aaa.
+/// \param aab Ccc.
+/// \param bbb Bbb.
+int test_param17(int aaa, int bbb);
+
+// expected-warning at +3 {{parameter 'aab' not found in the function declaration}}
+/// \param aaa Aaa.
+/// \param bbb Bbb.
+/// \param aab Ccc.
+int test_param18(int aaa, int bbb);
 
 class C {
   // expected-warning at +1 {{parameter 'aaa' not found in the function declaration}}
@@ -229,50 +252,51 @@
 
   // expected-warning at +1 {{parameter 'aaa' not found in the function declaration}}
   /// \param aaa Blah blah.
- int test_param15(int bbb, int ccc);
+ int test_param19(int bbb, int ccc);
 };
 
 // expected-warning at +1 {{parameter 'aab' not found in the function declaration}}
 /// \param aab Blah blah.
 template<typename T>
-void test_param16(int bbb, int ccc);
+void test_param20(int bbb, int ccc);
 
 // expected-warning at +3 {{parameter 'a' is already documented}}
 // expected-note at +1 {{previous documentation}}
 /// \param a Aaa.
 /// \param a Aaa.
-int test_param17(int a);
+int test_param21(int a);
 
 // expected-warning at +4 {{parameter 'x2' is already documented}}
 // expected-note at +2 {{previous documentation}}
 /// \param x1 Aaa.
 /// \param x2 Bbb.
 /// \param x2 Ccc.
-int test_param18(int x1, int x2, int x3);
+int test_param22(int x1, int x2, int x3);
 
-// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'aaa'?}}
+// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'ccc'?}}
 /// \param aaa Meow.
 /// \param bbb Bbb.
 /// \returns aaa.
-typedef int test_param19(int aaa);
+typedef int test_param23(int aaa, int ccc);
 
-// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'aaa'?}}
+// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'ccc'?}}
 /// \param aaa Meow.
 /// \param bbb Bbb.
 /// \returns aaa.
-typedef int (*test_param20)(int aaa);
+typedef int (*test_param24)(int aaa, int ccc);
 
-// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'aaa'?}}
+// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'ccc'?}}
 /// \param aaa Meow.
 /// \param bbb Bbb.
 /// \returns aaa.
-typedef int (* const test_param21)(int aaa);
+typedef int (* const test_param25)(int aaa, int ccc);
 
-// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'aaa'?}}
+// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'ccc'?}}
 /// \param aaa Meow.
 /// \param bbb Bbb.
 /// \returns aaa.
-typedef int (C::*test_param22)(int aaa);
+typedef int (C::*test_param26)(int aaa, int ccc);
+
 
 // expected-warning at +1 {{'\tparam' command used in a comment that is not attached to a template declaration}}
 /// \tparam T Aaa

Modified: cfe/trunk/test/Sema/warn-documentation.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-documentation.m?rev=162570&r1=162569&r2=162570&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-documentation.m (original)
+++ cfe/trunk/test/Sema/warn-documentation.m Fri Aug 24 12:45:39 2012
@@ -91,9 +91,9 @@
 - (void)test2:(NSString *)aaa;
 @end
 
-// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'aaa'?}}
+// expected-warning at +2 {{parameter 'bbb' not found in the function declaration}} expected-note at +2 {{did you mean 'ccc'?}}
 /// \param aaa Meow.
 /// \param bbb Bbb.
 /// \returns aaa.
-typedef int (^test_param1)(int aaa);
+typedef int (^test_param1)(int aaa, int ccc);
 





More information about the cfe-commits mailing list